Arista Command API
The Arista Command API is a simple and complete API that allows you to configure and monitor your Arista switches. Once the API is enabled, the switch accepts commands using the industry standard CLI syntax, and responds with machine readable output and errors serialized in JSON, served over HTTP.
The Command API is easy to use...
from jsonrpclib import Server switch = Server( "https://username:passw0rd@myswitch/command-api" ) response = switch.runCmds( 1, ["show version"] ) print "The switch's system MAC addess is", response[0]["systemMacAddress"]
... and easy to configure!
bash$ ssh username@myswitch Password: <passw0rd> myswitch> enable myswitch# configure terminal myswitch(config)# management api http-commands myswitch(config-mgmt-api-http-cmds)# no shutdown myswitch(config-mgmt-api-http-cmds)# show management api http-commands Enabled: Yes HTTPS server: running, set to use port 443 HTTP server: shutdown, set to use port 80 Local HTTP server: shutdown, no authentication, set to use port 8080 Unix Socket server: shutdown, no authentication VRF: default ...
Configuring the Command API Agent
Although disabled by default, it is very simple to get the Command API server running on your switch. From configure
mode, enter management api http-commands
mode. In this submode, you can turn on or off the server by typing [no] shutdown
, switch between accepting HTTP or HTTPS traffic via [no] protocol http[s]
, and adjust the ports the server should listen on using protocol http[s] port <portNumber>
. You can also configure the API to only accept connections from scripts running on the switch itself. To enable this feature, see On-box Usage of Command API
In any CLI mode, you can issue the show management api http-commands
command to view the status of the agent, including server information, attached users, last request time and other details.
myswitch> enable myswitch# configure terminal myswitch(config)# management api http-commands myswitch(config-mgmt-api-http-cmds)# [no] shutdown myswitch(config-mgmt-api-http-cmds)# [no] protocol https [port <portNumber>] myswitch(config-mgmt-api-http-cmds)# [no] protocol http [port <portNumber>] myswitch(config-mgmt-api-http-cmds)# [no] protocol http localhost [port <portNumber>] myswitch(config-mgmt-api-http-cmds)# [no] protocol unix-socket
Configuring a Certificate
Because clients use HTTP basic authentication to send usernames and passwords to the switch, we recommend using HTTPS so no passwords are sent in the clear over the network. HTTPS certificates and key can be changed with [no] protocol https certificate.
By default a self-signed certificate will be used. You can view the current certificate using show management api http-commands https certificate
myswitch> enable myswitch# configure terminal myswitch(config)# management api http-commands myswitch(config-mgmt-api-http-cmds)# protocol https certificate Enter TEXT certificate. Type 'EOF' on its own line to end. ... EOF Enter TEXT private key. Type 'EOF' on its own line to end. ... EOF myswitch(config-mgmt-api-http-cmds)# show management api http-commands https certificate Certificate: ... Private Key: ... myswitch(config-mgmt-api-http-cmds)#
The Spec
The Command API uses the lightweight, standardized protocol JSON-RPC 2.0 to communicate between your program (the client) and the switch (the server). Although most languages have client libraries which abstract away the JSON-RPC internals, it is useful to understand the communication mechanism between the client and the switch.
Exploring the Command API
To explore the API, point your web browser to http[s]://myswitch/
, after enabling Command API. This web-app lets you interactively explore the protocol, return values, and model documentation. Please note that if you visit the tool using HTTPS, your browser may emit a warning; this is because by default the agent uses a locally signed certificate for encryption purposes and can be ignored. You may always set a certificate and key issued by your own CA for enhanced security.
An annotated example
The client starts by sending a JSON-RPC request via an HTTP POST request
to http://<yourswitch>/command-api, which encapsulates a list of CLI
commands it wishes to run, and the switch replies with a JSON-RPC response
containing the result of each CLI command that was executed. The commands
in the request are run in order on the switch. After the switch has
executed all commands, it exits back to unprivileged mode. If any of the
commands emit an error, no further commands from that request are executed,
and the response from the switch will contain an error
object containing the details of the error that occurred.
To illustrate, here are annotated versions of the underlying Request and Response messages sent between the client and switch.
The Request
{ | |
"jsonrpc": "2.0", |
The protocol version. Always "2.0" , and usually set by a client library.
|
"method": "runCmds", |
The method to run on the switch. At this time runCmds is the only method supported.
|
"params": { | |
"version": 1, |
version is a mandatory parameter representing the API version. Currently always has the value 1 .
|
"cmds": [ |
cmds is a mandatory parameter which contains a list of CLI commands. Commands may either be a string or a complex object type. For more details, see the command specification
|
"enable", | |
"configure", | |
"interface Ethernet1", | |
"switchport access vlan 3", | |
"show vlan 3", | |
], | |
"format": "json" |
format is an optional parameter specifying response format. Can be text or json , and defaults to json .
|
}, | |
"id": 1 | A unique identifier that will be echoed back by the switch. May be a string or number. |
} |
The Response: success case
This response is returned by the switch after receiving the above request. All responses conform JSON-RPC 2.0 specifications.
{ | |
"jsonrpc": "2.0", |
The protocol version. Always "2.0" .
|
"result": [ |
The result list. Contains one object for each CLI command executed, and the position of the result corresponds to the original command list. If the request specified a text format, however, result will contain a list of strings.
|
{}, | |
{}, | |
{}, | |
{ "warnings": [ |
Most non-show commands produce no output and thus return an empty JSON object. However, in some cases, a command may produce warnings or errors which will be stored in arrays of the same name.
|
"Access VLAN does not exist. Creating vlan 3" | |
] | |
}, | |
{ "sourceDetail": "", |
show commands will return formatted JSON objects containing all information seen in the ASCII output in the normal CLI. In this case, show vlan 3 will give you a mapping from VLAN id to VLAN model.
|
"vlans": { | |
"3": { | |
"status": "active", | |
"name": "VLAN0003", | |
"interfaces": { | |
"Ethernet1": { | |
"annotation": null, | |
"privatePromoted": false | |
} | |
}, | |
"dynamic": false | |
} | |
} | |
} | |
], | |
"id": 1 | The same id (string/number) that was provided by the request. |
} |
The Response: failure case
In this case, let's assume our account does not have the appropriate AAA permissions to enter configure
mode.
{ | |
"jsonrpc": "2.0", | |
"error": { |
On an error, no result object is present, only an error object, which is guaranteed to have the following attributes: code , messages , and data .
|
"code": 1005, | Command API error code. |
"message": "CLI command 2 of 5 'configure' failed: permission to run command denied", | General high-level error message. |
"data": [ |
Similar to the result object in the successful response, the data object is a list of objects corresponding to the results of all commands up to, and including, the failed command. If there was a an error before any commands were executed (e.g. bad credentials), data, will be empty.
|
{}, |
The enable command passed without incident.
|
{ "errors": [ | |
"Authorization denied for command 'configure'" |
In this case, we failed on the second command. The last object in the data array will always correspond to the failed command. The command failure details are always stored in the errors array.
|
] } | |
] | |
}, | |
"id": 1 | |
} |
Command Specification
In most cases, the client will use a simple string to specify the CLI command in the cmds
parameter in the request. In certain cases, however, clients may wish to specify additional parameters during the command's execution. To use complex commands, pass a JSON object in lieu of a string, with the following attributes:
cmd
(mandatory): specify the CLI command to run.input
(optional): specify a string to be provided as standard input while running thecmd
revision
(optional): in the case of 'show' commands that have been modified over the course of different EOS releases, this parameter allows clients to request an old model format. At this time, all models are at revision 1, and this attribute will be ignored.
Hello World!
, the client should set cmds
to [ "enable", "configure", { "cmd": "banner motd", "input": "Hello World!\nEOF" } ]
Similarly, if the switch requires an enable password, the following cmds
value would let you enter exec mode and clear interface counters [ { "cmd": "enable", "input": "hunter2" }, "clear counters" ]
Error Codes
The following errors are generated if there is an issue with the request. Do note that new error codes may be introduced in future releases.
JSON-RPC 2.0 Defined Errors | |
---|---|
Code | Description |
-32700 | Parse Error |
-32600 | Invalid Request |
-32601 | Method not found |
-32602 | Invalid params |
-32603 | Internal server error |
Command API Errors | |
---|---|
Code | Description |
1000 | General error |
1001 | Command caused internal exception |
1002 | Invalid command: the string does not match any command |
1003 | Command not ready: attempted to get json from a show command, however the command has not been converted to be compatible with the Command API yet. Use format = text to run this command and get ASCII output. |
1004 | Command incompatible: cannot run command over the Command API |
1005 | Command unauthorized: user has insufficient permissions to run the command |
Using the Command API
In practice, most libraries hide the JSON-RPC version, id and protocol details. Instead you only need to call the runCmds
method with the version
and cmds
parameters and, optionally, the format
parameter. The responses generated by the client library usually follow language conventions. For example, in Python, an error response results in an Exception being thrown, while Javascript expects an error handler callback.
Unsupported commands
Certain commands are not permitted and will always return an error. The largest class of such commands are interactive commands; watch
is a prime example. Other commands, like reload
must use their non-interactive versions: such as reload now
. The bash
command is only allowed with the timeout <timeout>
argument, ie. bash timeout <timeout> <ARG>
.
Commands that attempt to use CLI pipes (e.g. show interfaces | grep Ethernet1
) are also not allowed. In addition, no abbreviations are allowed in commands. This is necessary because future versions of EOS may add more commands, rendering previous abbreviations ambiguous.
Unconverted commands
Although you can access almost any CLI command via the Command API, not all show
commands have been converted to return formatted data, and trying to run the command with the format
parameter set to json
will result in an error. However, you can still get the CLI ASCII output for the unconverted command by setting the format
parameter to text
. With this parameter set, the response will contain an array of strings (rather than an array of objects), each representing the text output of the corresponding command. When operating with format
set to text
, no errors will be generated; rather they will be included in the ASCII output, the same way they are printed in a standard CLI session. To view converted commands visit the command documentation center.
Using JSON-RPC
The JSON-RPC spec is well documented at JSON-RPC Specification, and there are libraries in almost every language that make dealing with JSON-RPC a breeze. Here are a list of some recommended client libraries:
- Python: jsonrpclib
- Perl: JSON-RPC2 Client
- Javascript: jsonrpc.js
- And many more here
On-box Usage of Command API
It is often useful to run scripts that use Command API directly on the switch itself, without configuring them with AAA credentials. EOS provides two mechanisms to accomplish this. The first is an HTTP server bound to localhost (on port 8080 by default), which only accepts connections arriving from the same machine. The other solution is a Unix domain socket. To enable one or both, use the following commands:
myswitch> enable myswitch# configure terminal myswitch(config)# management api http-commands myswitch(config-mgmt-api-http-cmds)# protocol http localhost myswitch(config-mgmt-api-http-cmds)# protocol unix-socket myswitch(config-mgmt-api-http-cmds)# no shutdown
Once Command API is enabled then you access via the local domain socket unix:/var/run/command-api.sock
switch = Server( "unix:/var/run/command-api.sock" )
If configured to use HTTP over localhost, your script can access the API as follows:
switch = Server( "http://localhost:8080/command-api" )