eos

Arista Extensible API (EAPI) – Network Automation with JSON-RPC and Python Scripting

October 16, 2017
Arista EOS EAPI – Application Programmable Interface
by Pablo Narváez

NETWORK AUTOMATION

Network automation is usually associated with doing things more quickly which is true, but it’s not the only reason why we should adopt it.

Network administrators usually touch the CLI to make changes on the network. Things get messy when there’s more than one administrator in a multi-vendor environment: Chances for human error are increased when different admins try to make changes on the network using different CLI/tools at the same time.

Replacing manual changes with standardized configuration management tools for network automation help achieve more predictable behavior and minimize “the human error factor”.

Network automation is the use of IT controls to supervise and carry out every-day network management functions. These functions can range from basic network mapping and device discovery to network configuration management and the provisioning of virtual network resources.

Network automation is a powerful and flexible enabler to:

●   Efficiently automate repetitive manual operational tasks
●   Answer open questions and resolve nonfeasible tasks
●   Enable tailored solutions and architectures beyond standard features

Through a step-by-step approach and thanks to many open source examples made available, network automation is easy to adopt in your network today.

Just keep in mind:

“With network automation, the point is to start small, but think through what else you may need in the future.” – Network Programmability by Jason Edelman; Scott S. Lowe; Matt Oswalt

 ARISTA EAPI

Introduction

Arista EOS offers multiple programmable interfaces for applications. These interfaces can be leveraged by applications running on the switch, or external to EOS.

The Extensible API (eAPI) allows applications and scripts to have complete programmatic control over EOS, with a stable and easy to use syntax. It also provides access to all switch state.

Once the API is enabled, the switch accepts commands using Arista’s CLI syntax, and responds with machine-readable output and errors serialized in JSON, served over HTTP.

Configuring the Extensible API Interface

One of the benefits about working with Arista EOS eAPI is the ability to script with JSON-RPC.  A network administrator can get machine-friendly data from the switch using CLI syntax.

In this post, I will show you the use of eAPI with a simple example using Python.

First, we need to activate the eAPI in each switch. To enable it, we need to bring up the API virtual interface.

leaf01#conf ter
leaf01(config)#management api http-commands 
leaf01(config-mgmt-api-http-cmds)#no shutdown 
leaf01(config-mgmt-api-http-cmds)#

eAPI requires a username and password to be configured. This is a regular username setup on global configuration:

leaf01#conf ter
leaf01(config)#username admineapi secret arista

Default configuration for eAPI uses HTTPS on port 443. Both the port and the protocol can be changed.

leaf01#conf ter
leaf01 (config)#management api http-commands
leaf01(config-mgmt-api-http-cmds)#protocol ?
   http         Configure HTTP server options
   https        Configure HTTPS server options
   unix-socket  Configure Unix Domain Socket

leaf01(config-mgmt-api-http-cmds)#protocol http ?
   localhost  Server bound on localhost
   port       Specify the TCP port to serve on
   <cr>      

leaf01(config-mgmt-api-http-cmds)#protocol http port ?

  <1-65535>  TCP port

leaf01(config-mgmt-api-http-cmds)#protocol http port 8080
leaf01(config-mgmt-api-http-cmds)#

NOTE: When configuring a non-default http/https pot under “protocol”, that port needs to be manually added to an updated version of the switch´s control-plane access-list to permit remote access.

To verify that the eAPI is running use the following command:

leaf01#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
 Hits:               0
 Last hit:           never
 Bytes in:           0
 Bytes out:          0
 Requests:           0
 Commands:           0
 Duration:           0.000 seconds
 SSL Profile:        none
 QoS DSCP:           0

 URLs        
------------------------------------- 
Ethernet4   : https://172.16.0.2:443 
Ethernet5   : https://172.16.0.14:443  
Loopback0   : https://10.0.1.21:443    
Loopback1   : https://10.0.2.1:443     
Vlan11      : https://192.168.11.2:443 
Vlan4094    : https://172.16.254.1:443

In the output shown above notice the URLs, we are going to need them to access the switch eAPI through HTTP/HTTPS.

USING ARISTA EAPI

There are two methods of using the eAPI:

  • Web access
  • Programming

eAPI Web Access

The eAPI uses the lightweight, standardized protocol JSON-RPC 2.0 to communicate between your program (the client) and the switch (the server).

To explore the API, point your web browser to https://myswitch after enabling the API interface on the switch.

NOTE: “myswitch” refers to the IP address of the switch you want to configure. To select the appropriate IP address, choose one of the URLs displayed in the command output shown above.

This web-app lets you interactively explore the protocol, return values and model documentation.

eapi_web

The way it works is by sending a JSON-RPC request via an HTTP POST request to https://myswitch/command-api from the client, the request 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 test the eAPI via web browser, let’s try a common command like “show version”:

web_showversion

See the command response in the Response Viewer window.

You can try other commands available in CLI. Check the full list of CLIs supported commands and the corresponding output data entries definition in the top right corner in the “Command Documentation” tab.

Easy to use, right? While the web interface is useful for testing eAPI, it’s not really designed to be a day-to-day function. For a more robust, scalable and complete eAPI experience, the use of the Programming interface is recommended.

eAPI Programming Interface

When using the programming interface to communicate with the switches, we need to read the JSON formatted output. To do so, we are going to add JSON libraries to our environment. For this lab, we have a dedicated Ubuntu Linux server (client) to download the JSON/Python libraries.

NOTE: You don’t need to have an external PC to run the JSON/Python libraries, you can run scripts on the Arista switch itself since all the required JSON libraries are part of the base EOS build.

To enable JSON for use in Python, we need to download the libraries to the Linux server.

superadmin@server00-eapi:~$ sudo apt-get install python-pip
superadmin@server00-eapi:~$ sudo pip install jsonrpclib

This is all we need to communicate with the eAPI.

Now we need to create and run a python script to request some information to the switch. To do so, I will use a really simple example to retrieve the output of “show version”.

#!/usr/bin/python
 
from jsonrpclib import Server
 
switch = Server(http://admineapi:arista@192.168.11.2/command-api)
response = switch.runCmds(1, [“show version”])
 
print response

In order to create and run your own Python scripts the use of an IDE (Integrated Development Environment) is strongly recommended. An IDE is a software suite that consolidates the basic tools developers need to write and test software. Typically, an IDE contains a code editor, a compiler or interpreter (Python uses an interpreter) and a debugger that the developer accesses through a single graphical user interface (GUI). There are several IDEs available, please check the following link that contains a review of the most popular ones:

Python Integrated Development Environments

Let’s take a closer look at the script.

This line defines the target (switch). It is broken down as a URL with the following format:

<protocol>://<username>:<password>@<hostname or ip-address>/command-api

The “/command-api” must always be present when using eAPI.

You cannot abbreviate any CLI command and the number “1” in the command is the eAPI version which must always be 1.

Now let’s run the script.

superadmin@server00-eapi:~/scripting$ python hello.py 
[{u’memTotal’: 1893352, u’internalVersion’: u’4.17.5M-4414219.4175M’, u’serialNumber’: u”, u’systemMacAddress’: u’52:54:00:97:ea:40′, u’bootupTimestamp’: 1505842331.32, u’memFree’: 583364, u’version’: u’4.17.5M’, u’modelName’: u’vEOS’, u’isIntlVersion’: False, u’internalBuildId’: u’d02143c6-e42b-4fc3-99b6-97063bddb6b8′, u’hardwareRevision’: u”, u’architecture’: u’i386′}]

That may seem like gibberish at first glance, but it’s actually a JSON-formatted set of key-value pairs.

This is the same output, but spaced apart to line it up into more human readable format:

[{
 u'memTotal': 1893352, 
 u'internalVersion': u'4.17.5M-4414219.4175M', 
 u'serialNumber': u'', 
 u'systemMacAddress': u'52:54:00:97:ea:40', 
 u'bootupTimestamp': 1505842331.32, 
 u'memFree': 583364, 
 u'version': u'4.17.5M', 
 u'modelName': u'vEOS',
 u'isIntlVersion': False, 
 u'internalBuildId': u'd02143c6-e42b-4fc3-99b6-97063bddb6b8', 
 u'hardwareRevision': u'', 
 u'architecture': u'i386'
 }]

Now that we have the key-value pairs, we can reference them to pull out the desired information… this is where the magic happens.

Basically, we have bulk data, so we need an automated way to retrieve the information.

To so, change the script to extract just the value-pair that you need. The format is:

Response[0][“key-name”]

In the next example, I will request the system MAC Address, the EOS version and the total physical memory; all other information will not be displayed.

superadmin@server00-eapi:~/scripting$ cat hello.py  
#!/usr/bin/python
 
from jsonrpclib import Server
 
switch = Server(http://admineapi:arista@192.168.11.2/command-api)
response = switch.runCmds(1, [“show version”])
 
print “The system MAC address is:”, response[0][“systemMacAddress”]
print “The system version is:”, response[0][“version”]
print “The total physical memory is:”, response[0][“memTotal”]

This is the result of running the script:

superadmin@server00-eapi:~/scripting$ python hello.py 
The system MAC address is: 52:54:00:97:ea:40
The system version is: 4.17.5M
The total physical memory is: 1893352

Just imagine how you could use this tool compared to the closed vendor-specific monitoring apps, the eAPI provides you with the desired information the way you want it when you want it… You can even create reports and verify compliance with some advanced scripting so this is the flexibility that a programmable operating system provides.

Complex functions require a more sophisticated script. One such example is device provisioning. For deployment automation, you can send multiple commands at once to configure the switch , please see the example below.

#!/usr/bin/python
 
from jsonrpclib import Server
switch = Server(http://admineapi:arista@192.168.11.2/command-api)

for x in range (10, 19):
      response  = switch.runCmds(1, [
           “enable”,
           “configure”,
           “interface ethenet2” + str(x),
           “description [GAD Eth-“ + str(x) + “]”],
           “json”)
print “Done.”

Some commands may require input. This can be accomplished by surrounding the command with curly braces and adding the “cmd” and “input” keywords using the following format:

#!/usr/bin/python
 
 from jsonrpclib import Server
 switch = Server(http://admineapi:arista@192.168.11.2/command-api)

response  = switch.runCmds(1, [
     {“cmd”: “enable”, “input”: “arista”},
      “configure”,
      “interface ethenet2”,
      “description I can code!”],
      “json”)

The Arista eAPI (and the API of any other programmable NOS for that matter) is a tremendously powerful tool that puts the very concept of Software Defined Networking within easy reach. The ability to issue CLI commands remotely through scripts is one of the major benefits of network automation and programmable infrastructure.

You can always check my github repository to download the configuration files.

 

Advertisements

BGP Interoperability between Free Range Routing (FRR) and Arista EOS

August 17, 2017
Free Range Routing
by Pablo Narváez

Today I will test BGP between the FRR routing stack and Arista EOS. The sample configuration that I will show later in this post is just a basic integration between the two devices, nothing at all complex. Basically, I just wanted to expand my virtual environment by adding a DC/routing perimeter while testing FRR.

For this lab, I will be using the same environment I already built in my previous post so I can easily integrate FRR into the existing topology.

FREE RANGE ROUTING OVERVIEW

FRR is a routing software package that provides TCP/IP based routing services with routing protocols support such as RIPv1, RIPv2, RIPng, OSPFv2, OSPFv3, IS-IS, BGP-4, and BGP-4+.

In addition to traditional IPv4 routing protocols, FRR also supports IPv6. Since the beginning, this project has been supported by Cumulus Networks, Big Switch Networks, 6WIND, Volta Networks and Linkedin, among others.

FRR has been forked from the Quagga open-source project. For those who are not familiar with Quagga, it’s an open-source implementation of a full routing stack for Linux; it’s mostly used for WRT custom firmware, some cloud implementations, and even for control plane functionality on some network operating systems (NOS) like Cumulus Linux.

NOTE: FRR replaces Quagga as the routing suite in Cumulus Linux 3.4.0.

Quagga still exists but has a completely different development process than FRR. You can learn more about Quagga here.

ROUTING STACK VS NETWORK OPERATING SYSTEM

Just to be clear what FRR is and what it’s not, a network operating system (NOS) is the totality from Layer-1 hardware all the way up to the control plane. FRR is a full implementation of the routing control plane so it needs a base operating system to run on top.

In this regard, FRR is not a NOS that can run directly on baremetal. Instead, it´s a modern implementation of the IPv4/IPv6 routing stack that provides control plane functionality as Linux daemons.

FRR SYSTEM ARCHITECTURE

FRR is made from a collection of several daemons that work together to build the routing table.

Zebra is responsible for changing the kernel routing table and for redistribution of routes between different routing protocols. In this model, it’s easy to add a new routing protocol daemon to the entire routing system without affecting any other software.

There is no need for the FRR daemons to run on the same machine. You can actually run several instances of the same protocol daemon on the same machine and keep them apart from the rest of the daemons.

frr-architecture

FRR Architecture

Currently FRR supports GNU/Linux and BSD. The list of officially supported platforms are listed below. Note that FRR may run correctly on other platforms, and may run with partial functionality on further platforms.

  • GNU/Linux
  • FreeBSD
  • NetBSD
  • OpenBSD

FRR DOWNLOAD

FRR is distributed under the GNU General Public License and is available for download from the official FRR website.

FRR INSTALLATION

There are three steps for installing the software: configuration, compilation, and installation.

I chose Ubuntu to deploy FRR but several Linux distros are supported. If you want to install it on Ubuntu, follow these instructions. You can check the FRR webpage for any other Linux/BSD distro, it’s been pretty well documented.

When configuring FRR, there are several options to customize the build to include or exclude specific features and dependencies. You can check all the options here.

Once installed, check the FRR daemons to make sure it’s running:

ps-ef-frr

If you installed FRR from source (link above), the FRR daemon (and all the routing daemons you specify during the installation) will run as a system service after the Linux kernel is booted. As you can see in the screen capture above, the routing processes (bgpd, ospfd, ldpd, etc.) are running as part of the main FRR service.

As with any other Linux system service, you can manage the frr service with systemctl.

$ systemctl start|stop|restart frr

To access FRR, each daemon has its own configuration file and terminal interface which can be a very annoying thing. To resolve this problem, FRR provides an integrated user interface shell called vtysh.

vtysh connects to each daemon with UNIX domain socket and then works as a proxy for user input so there’s no need to connect to each daemon separately.

To access vtysh from the host OS, just type in the following command:

superadmin@frr01:~$ vtysh

Hello, this is FRRouting (version 3.1-dev-MyOwnFRRVersion-g7e4f56d).
Copyright 1996-2005 Kunihiro Ishiguro, et al.

This is a git build of frr-3.1-dev-320-g7e4f56d
Associated branch(es):
 local:master
 github/frrouting/frr.git/master

frr01#

INTERESTING FACTS ABOUT FRR

  • If you install FRR from source and follow the instructions provided above, there’s no need to modify or even touch any of the daemon configuration files (.conf) located in /etc/frr. When you log into FRR with vtysh a single configuration file is created for all the daemons. The single conf file will be stored as frr.conf in the host
  • Don’t expect to see Ethernet/WAN interfaces, FRR will show you the actual host network adapters: ens3, ens4, ens5, ens10 (depending on the Linux distro and your setup adapter names might change).
frr01#
frr01# conf ter
frr01(config)# interface ?
 IFNAME Interface's name
 ens3 ens4 ens5 ens10 lo
frr01(config)# interface ens3
frr01(config-if)#
  • As you may have noticed by now, if you know Cisco IOS or Arista EOS you are good to go! The FRR CLI is basically the same. You can check the list of CLI commands here.

BGP INTEROPERABILITY TESTING

As shown in the diagram below, I will use my existing network setup to connect the FRR routers to the Arista Spine switches.

frr-networking

Free Range Routing Network Setup

Each network device has a loopback interface which is being announced into BGP (10.0.1.21-23, 10.0.1.31-32). When we finish the configuration, we should be able to ping all these interfaces from the FRR routers.

The interfaces between the FRR routers and the Arista switches are configured as point-to-point Layer-3 links.

frr01# show running-config
Building configuration...

Current configuration:
!
frr version 3.1-dev
frr defaults traditional
hostname frr01
username root nopassword
!
service integrated-vtysh-config
!
log syslog informational
!
interface ens4
 description link_to_spine01-eth4
 ip address 172.16.0.25/30
!
interface ens5
 description link_to_spine02-eth4
 ip address 172.16.0.29/30
!
interface ens10
 description link_to_frr02-ens10
 ip address 172.16.254.5/30
!
interface lo
 description router-id
 ip address 10.0.1.1/32
!
frr02# show running-config
Building configuration...

Current configuration:
!
frr version 3.1-dev
frr defaults traditional
hostname frr02
username root nopassword
!
service integrated-vtysh-config
!
log syslog informational
!
interface ens4
 description link_to_spine01-eth5
 ip address 172.16.0.33/30
!
interface ens5
 description link_to_spine02-eth5
 ip address 172.16.0.37/30
!
interface ens10
 description link_to_frr02-ens10
 ip address 172.16.254.6/30
!
interface lo
 description router-id
 ip address 10.0.1.2/32
!

I will configure ASN 65000 for the FRR routers; frr01 and frr02 will have iBGP peer sessions with each other and eBGP peer sessions with the Arista switches.

frr01#
router bgp 65000
 bgp router-id 10.0.1.1
 distance bgp 20 200 200 
 neighbor ebgp-to-spine-peers peer-group
 neighbor ebgp-to-spine-peers remote-as 65020
 neighbor 172.16.0.26 peer-group ebgp-to-spine-peers
 neighbor 172.16.0.30 peer-group ebgp-to-spine-peers
 neighbor 172.16.254.6 remote-as 65000
 !
 address-family ipv4 unicast
 network 10.0.1.1/32
 exit-address-family
 vnc defaults
 response-lifetime 3600
 exit-vnc
frr02#
router bgp 65000
 bgp router-id 10.0.1.2
 distance bgp 20 200 200
 neighbor ebgp-to-spine-peers peer-group
 neighbor ebgp-to-spine-peers remote-as 65020
 neighbor 172.16.0.34 peer-group ebgp-to-spine-peers
 neighbor 172.16.0.38 peer-group ebgp-to-spine-peers
 neighbor 172.16.254.5 remote-as 65000
 !
 address-family ipv4 unicast
 network 10.0.1.2/32
 exit-address-family
 vnc defaults
 response-lifetime 3600
 exit-vnc

Since BGP was already configured in the Arista switches as part of my previous labs, I just added the eBGP sessions towards FRR.

spine01#
router bgp 65020
 router-id 10.0.1.11
 distance bgp 20 200 200
 maximum-paths 2 ecmp 64
 neighbor ebgp-to-frr-peers peer-group
 neighbor ebgp-to-frr-peers remote-as 65000
 neighbor ebgp-to-frr-peers maximum-routes 12000
 neighbor 172.16.0.2 remote-as 65021
 neighbor 172.16.0.2 maximum-routes 12000
 neighbor 172.16.0.6 remote-as 65021
 neighbor 172.16.0.6 maximum-routes 12000
 neighbor 172.16.0.10 remote-as 65022
 neighbor 172.16.0.10 maximum-routes 12000
 neighbor 172.16.0.25 peer-group ebgp-to-frr-peers
 neighbor 172.16.0.33 peer-group ebgp-to-frr-peers
 network 10.0.1.11/32
 redistribute connected
spine02#
router bgp 65020
 router-id 10.0.1.12
 distance bgp 20 200 200
 maximum-paths 2 ecmp 64
 neighbor ebgp-to-frr-peers peer-group
 neighbor ebgp-to-frr-peers remote-as 65000
 neighbor ebgp-to-frr-peers maximum-routes 12000
 neighbor 172.16.0.14 remote-as 65021
 neighbor 172.16.0.14 maximum-routes 12000
 neighbor 172.16.0.18 remote-as 65021
 neighbor 172.16.0.18 maximum-routes 12000
 neighbor 172.16.0.22 remote-as 65022
 neighbor 172.16.0.22 maximum-routes 12000
 neighbor 172.16.0.29 peer-group ebgp-to-frr-peers
 neighbor 172.16.0.37 peer-group ebgp-to-frr-peers
 network 10.0.1.12/32
 redistribute connected

NOTE: The “redistribute connected” command will redistribute all the directly connected interfaces into BGP for connectivity testing purposes. In production, link addresses are not typically advertised. This is because:

  • Link addresses take up valuable FIB resources. In a large CLOS (Leaf-Spine) environment, the number of such addresses can be quite large
  • Link addresses expose an additional attack vector for intruders to use to either break in or engage in DDOS attacks

We can verify the interoperability between FRR and Arista by checking the BGP neighbor adjacencies. The output of the “show ip bgp summary” command shows the BGP state as established, which indicates that the BGP peer relationship has been established successfully.

frr-bgp-summary

Finally, we check the routing table to make sure we can reach all the loopback interfaces from the FRR routers.

frr-ip-route

You can always check my github repository to download the configuration files.