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:

For example, to set the message of the day to 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
CodeDescription
-32700Parse Error
-32600Invalid Request
-32601Method not found
-32602Invalid params
-32603Internal server error
Command API Errors
CodeDescription
1000General error
1001Command caused internal exception
1002Invalid command: the string does not match any command
1003Command 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.
1004Command incompatible: cannot run command over the Command API
1005Command 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:

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" )