if/CommandRunner.thrift (171 lines of code) (raw):

# Copyright (c) Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. include "common/fb303/if/fb303.thrift" namespace py.asyncio fbnet.command_runner_asyncio.CommandRunner enum FcrErrorCode { /* Error Codes */ // UNKNOWN: default, for all unidentifed exceptions UNKNOWN = 1, // RUNTIME_ERROR: for built-in RuntimeError RUNTIME_ERROR = 2, // ASSERTION_ERROR: for built-in AssertionError ASSERTION_ERROR = 3, // LOOKUP_ERROR: for built-in LookupError // and errors that inherit from it LOOKUP_ERROR = 4, // STREAM_READER_ERROR: for errors related // to asyncio.StreamReader STREAM_READER_ERROR = 5, // COMMAND_EXECUTION_TIMEOUT_ERROR: FCR timeout // when executing command COMMAND_EXECUTION_TIMEOUT_ERROR = 6, // NOT_IMPLEMENTED_ERROR: for built-in // NotImplementedError NOT_IMPLEMENTED_ERROR = 7, // PARSING_ERROR: error with parsing // requests and responses PARSING_ERROR = 8, // Error code 9 is in use // VALUE_ERROR: for built-in ValueError and when // argument has right type but invalid value VALUE_ERROR = 10, // TYPE_ERROR: for built-in TypeError and when // operation applied to unsupported object type TYPE_ERROR = 11, // ATTRIBUTE_ERROR: for built-in AttributeError and // when attribute reference or assignment fails ATTRIBUTE_ERROR = 12, // TIMEOUT_ERROR: for built-in TimeoutError and // when a function timed out at the system level TIMEOUT_ERROR = 13, // 100-199: User error // VALIDATION_ERROR: invalid inputs VALIDATION_ERROR = 100, // PERMISSION_ERROR: invalid credentials or // authentication PERMISSION_ERROR = 101, // UNSUPPORTED_DEVICE_ERROR: user // inputs unsupported device UNSUPPORTED_DEVICE_ERROR = 103, // UNSUPPORTED_COMMAND_ERROR: user // inputs unsupported command UNSUPPORTED_COMMAND_ERROR = 104, // 200-299: Device error // DEVICE_ERROR: for general device-related errors DEVICE_ERROR = 200, // COMMAND_EXECUTION_ERROR: device has // has already received the command // but error when trying to execute it COMMAND_EXECUTION_ERROR = 201, // 300-399: Network error // CONNECTION_ERROR: for general network-related // connection errors CONNECTION_ERROR = 300, // CONNECTION_TIMEOUT_ERROR: connection times out CONNECTION_TIMEOUT_ERROR = 301, // Error code 302 and 303 is in use } // This exception is deprecated; raise a SessionException instead exception FBNetDataException { 1: string message; } // This exception is deprecated; raise a SessionException instead exception UnsupportedDeviceException { 1: string message; } exception SessionException { 1: string message; 2: FcrErrorCode code; } // This exception is deprecated; raise a SessionException instead exception UnsupportedCommandException { 1: string message; } exception InstanceOverloaded { 1: string message; } const string CONS_AUTO = 'auto'; const string FAILURE_STATUS = 'failure'; const string SUCCESS_STATUS = 'success'; enum SessionType { SSH = 1, SSH_NETCONF = 2, } struct SessionData { // see section 6.5 in RFC: https://tools.ietf.org/html/rfc4254 // One of the following needs to be specified. // We will prefer subsystem over exec_command if both are specified. // This uses the SSH subsystem command to start the netconf session // // session_data = fcr_ttypes.SessionData(subsystem='xmlagent') // // dev = Device(hostname='rtr-name', // session_type=fcr_ttypes.SessionType.SSH_NETCONF, // session_data=session_data) // // cmd = '''<?xml version="1.0"?> // <nf:rpc xmlns:nf="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nxos="http://www.cisco.com/nxos:1.0" message-id="110"> // <nxos:exec-command> // <nxos:cmd>show interface brief</nxos:cmd> // </nxos:exec-command> // </nf:rpc>''' // // with get_client(FcrClient) as client: // res = client.run(cmd, dev) // 1: optional string subsystem; // This command is executed on the remote system to start a session // // session_data = fcr_ttypes.SessionData(exec_command='netconf format') // // dev = Device(hostname='rtr-name', // session_type=fcr_ttypes.SessionType.SSH_NETCONF, // session_data=session_data) // // cmd = '''<?xml version="1.0" ?> // <rpc message-id="8566" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> // <get> // <filter type="subtree"> // <optics-oper xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-controller-optics-oper"> // <optics-ports> // <optics-port> // <name>Ots-Och0/2/0/0/1</name> // <optics-info /> // </optics-port> // </optics-ports> // </optics-oper> // </filter> // </get> // </rpc>''' // // with get_client(FcrClient) as client: // res = client.run(cmd, dev) 2: optional string exec_command; // Extra options that supported by the given session type. For example, // - The following session support extra_options={'port': PORT}: SSH, NETCONF 3: optional map<string, string> extra_options; } struct Device { 1: required string hostname; 10: required string username; 11: required string password; 13: optional string console = ''; // default not using mgmt ip 14: optional bool mgmt_ip = 0; /* * explicitly specify the expected prompts for commands. This can be used * for commands that don't result in normal prompts (exit, reboot etc) * e.g * prompts = { * 'exit': 'login:\s*', # Expect a login prompt on exit command * 'reboot': 'Shutting Down' * } * device = Device(hostname='bb01.iad1', prompts=prompts) */ 15: optional map<string, string> command_prompts; /* * IP address (v4/v6) to be used for the device. If specified, this will be * used instead of doing a lookup. */ 16: optional string ip_address; /* * Session Type to use for this device. This overrides the default session * type for the device. */ 17: optional SessionType session_type; /* * The optional session data that is needed to initialize the session. */ 18: optional SessionData session_data; /* List of commands that FCR will execute immediately after login to the device and before running cli_setup commands Example of usecase: Some unprovisioned device needs to enter `cli` before actually execute any commands, with this field, user can specify this usecase and force the device to enter cli mode */ 19: optional list<string> pre_setup_commands; /* The command to be sent to clear the command line (in bytes). E.g. "\x15" * 1. Omit or set to None if clear_command should fall-back to default ("\x15") * 2. Set to non-empty string for custom clear_command to override the default * 3. Set to empty string (= "") to forgo sending a clear_command in-between commands. */ 20: optional string clear_command; /* default do not fail over If the first IP FCR chooses to connect to a device does not succeed in making the connection, then failover to the other ips which FBNet has for the device till a connection has been made or all IPs have been exhausted. */ 21: optional bool failover_to_backup_ips; } struct CommandResult { 1: required string output; // if everything works, status = SUCCESS_STATUS // if there is some error, status contains the error msg and output has // what has received so far 2: required string status; 3: required string command; // Capabilities for the session. // This used to return the initial hello message from the peer. // The hello message specifies the server capabilities that clients can // use to verify support for data models. 4: optional string capabilities; 5: string uuid; } struct Session { 1: required i64 id; 2: required string name; 3: required string hostname; 4: string uuid; } struct DeviceCommands { 1: Device device; /* List of commands to be run on the device. * The commands in this list will be executed sequentially according * to the order in the list. */ 2: list<string> commands; } struct BulkRunCommandRequest { // A list of DeviceCommands struct 1: list<DeviceCommands> device_commands_list; /* * optional arguments */ // max time (sec) to wait to get the full response of a single command. // the max time it could take per device is timeout * number of commands 3: i32 timeout = 300; // max time (sec) allowed to spend authenticating into the device 4: i32 open_timeout = 30; /* * don't populate the following arguments unless you know what you are doing */ 10: string client_ip = ""; 11: string client_port = ""; 12: string uuid = ""; } struct BulkRunCommandResponse { 1: map<string, list<CommandResult>> device_to_result; } service Command extends fb303.FacebookService { /* Run a command on a device. * * A command string is a single command, e.g., 'show version'. * A command string could contain multiple commands separated by newlines, * e.g., a configlet like * * 'conf t\nsnmp-server community TEST RO\nexit' * * @return CommandResult */ CommandResult run( 1: string command, 2: Device device, /* * optional arguments */ // max time (sec) to wait to get the full response 3: i32 timeout = 300, // max time (sec) allowed to spend authenticating into the device 4: i32 open_timeout = 30, /* * don't populate the following arguments unless you know what you are doing */ 10: string client_ip = "", 11: string client_port = "", 12: string uuid = "", ) throws (1: SessionException se, 2: UnsupportedDeviceException ude); /* Run a list of commands on a list of devices. * * All commands to each device are run serially within a single session * in the specified order. If a command in a list fails to execute, * subsequent commands to the device are skipped. A command string could be a * single command or a configlet, see comments for run() for examples. * * @return Mapping from hostname to CommandResult */ map<string, list<CommandResult>> bulk_run( 1: map<Device, list<string>> device_to_commands, /* * optional arguments */ // max time (sec) to wait to get the full response of a single command. // the max time it could take per device is timeout * number of commands 3: i32 timeout = 300, // max time (sec) allowed to spend authenticating into the device 4: i32 open_timeout = 30, /* * don't populate the following arguments unless you know what you are doing */ 10: string client_ip = "", 11: string client_port = "", 12: string uuid = "", ); /* DO NOT USE THIS API. This is in the process of development. * This is the version 2 of the bulk_run, with compliance to modern thrift guidance. */ BulkRunCommandResponse bulk_run_v2(1: BulkRunCommandRequest request); /* * To USER: DO NOT use this function * * To Developer: This is another version of bulk_run which * does not split big request into smaller one * */ map<string, list<CommandResult>> bulk_run_local( 1: map<Device, list<string>> device_to_commands, 3: i32 timeout = 300, 4: i32 open_timeout = 30, /* * don't populate the following arguments unless you know what you are doing */ 10: string client_ip = "", 11: string client_port = "", 12: string uuid = "", ) throws (1: InstanceOverloaded ioe); /* * The following APIs is used to interact with a single device just * as if you are accessing the device CLI. * * IMPORTANT: * 1. You MUST use the same thrift connection to open and run * commands on a session. Sessions opened by one thrift connection aren't * valid for running commands via another thrift connection. * 2. Remember to close the session after use to prevent any stale connection * to the device. * * Example: * session = fcr_client.open_session(device) * fcr_client.run_session(session, 'show version') * // push a configlet * configlet = '''conf t snmp-server community TEST RO exit wr mem''' * fcr_client.run_session(session, configlet) * fcr_client.run_session(session, 'show run | include snmp-server') * fcr_client.close_session(session) * */ /* Establish a management session with a device. The session does not persist * across thrift connections, i.e., the session dies when you are disconnected * from the command runner thrift service. * * @return Session */ Session open_session( 1: Device device, /* * optional arguments */ // max time (sec) allowed to spend authenticating into the device 2: i32 open_timeout = 60, // max time (sec) allowed for the session to go unused 3: i32 idle_timeout = 300, /* * don't populate the following arguments unless you know what you are doing */ 10: string client_ip = "", 11: string client_port = "", 12: string uuid = "", ) throws (1: SessionException se); /* Run a command within a session. The command could potentially modify * the device configuration based on the permission you have on the device. * The command could be multi-line (separated by \n'), e.g., * command = """ conf t ? """ * * @return CommandResult */ CommandResult run_session( 1: Session session, 2: string command, /* * optional arguments */ // max time (sec) to wait to get the full response 3: i32 timeout = 300, /* * don't populate the following arguments unless you know what you are doing */ 10: string client_ip = "", 11: string client_port = "", 12: string uuid = "", ) throws (1: SessionException se); /* Close the session. Each open_session call should be accompanied with a * close_session call to free connection with the device. * * @return void */ void close_session( 1: Session session, /* * don't populate the following arguments unless you know what you are doing */ 10: string client_ip = "", 11: string client_port = "", 12: string uuid = "", ) throws (1: SessionException se); // open_raw_session() should be used when user want to bypass session setup // (login and run setup commands). // If open_raw_session(), following calls should be run_raw_session() and // close_raw_session(). Session open_raw_session( 1: Device device, /* * optional arguments */ // max time (sec) allowed to spend authenticating into the device 2: i32 open_timeout = 60, // max time (sec) allowed for the session to go unused 3: i32 idle_timeout = 300, /* * don't populate the following arguments unless you know what you are doing */ 10: string client_ip = "", 11: string client_port = "", 12: string uuid = "", ) throws (1: SessionException se); /* * This is similar to run_session(). This is used in conjunction with * open_raw_session. The user needs to explicitly specify the expected * prompt_regex. * * @return CommandResult */ CommandResult run_raw_session( 1: Session session, 2: string command, /* * optional arguments */ // max time (sec) to wait to get the full response 3: i32 timeout = 300, // Specify a prompt that you expect at the end of command. 4: string prompt_regex, /* * don't populate the following arguments unless you know what you are doing */ 10: string client_ip = "", 11: string client_port = "", 12: string uuid = "", ) throws (1: SessionException se); /* Close the session. Each open_raw_session call should be accompanied with a * close_session call to free connection with the device. * * @return void */ void close_raw_session( 1: Session session, /* * don't populate the following arguments unless you know what you are doing */ 10: string client_ip = "", 11: string client_port = "", 12: string uuid = "", ) throws (1: SessionException se); }