Working with the Python eAPI Client

This article builds on the Introduction to the Python Client for eAPI by taking a look at the pyeapi client a little deeper.  The client module provides a number of functions for making it easier to build connectivity to Arista EOS nodes running eAPI.

To get started, lets begin by simply importing the pyeapi client in Python and review the how to build a node object.

>>> import pyeapi
>>> node = pyeapi.connect_to('veos01')

As discussed in the introduction article, the above will search for and load the eapi.conf file.  Once the configuration file has been found and loaded by pyeapi, we can easily create a node object by specifying the name as an argument to the connect_to method.   However, what happens if the eapi.conf file is not found or the wrong name (or typo in the name) is passed to the connect_to function?

>>> node = pyeapi.connect_to('foo')
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   File "pyeapi/client.py", line 633, in connect_to
      connection = connect(transport=kwargs.get('transport'),
AttributeError: 'NoneType' object has no attribute 'get'

As you can see from the above example, specifying a connection name that is not present in the configuration file returns a pretty ugly traceback function.  In this case, the connection name ‘foo’ was passed to the connect_to function. However, there is no [connection:foo] in the eapi.conf file.  There are a couple of things we can do to address this problem.

First, we can simply check if there is a configuration for the named connection using the config_for function.  The config_for function is used to return the settings of a named connection as a Python dictionary object.  The output below demonstrates using the config_for to return the settings for veos01.

>>> pyeapi.config_for('veos01')
{'username': 'eapi', 'host': '192.168.1.16', 'password': 'password', 'transport': 'http'}

In the output from the config_for function, we can see the various settings which can be useed to connect using the veos01 named connection.  In contrast, the next example demonstrates the output from an unknown connection.

>>> pyeapi.config_for('foo')

This time there is no return from the config_for function.  Actually more properly stated the function returns the None object.  Using the config_for function allows an application to validate the named configuration exists before trying to make a call to connect_to.

The second thing we can do to handle the traceback error generated from an improper call to connect_to is to wrap the call into a try…except block and catch the error.  Below is an example of how to catch the error in an application and return a nice message.

>>> try:
...    node = pyeapi.connect_to('foo')
... except AttributeError:
...    print 'Named connection not found'
...
Named connection not found

In the above example, the call to connect_to still generates the error (specifically the AttributeError) but this time the exception is caught and the message ‘Named connection not found’ is returned instead.

Working with load_config

Up until this point the eapi.conf file has been automatically loaded by the pyeapi client.  In some cases it is advantageous to override the default functionality.  The pyeapi module provides a function that allows for loading a specific eapi.conf (or whatever name you choose) instead of automatically finding one.  By using a function to load the configuration file, we can now name our configuration file any name we choose and store it anywhere we choose.

The generalized format for loading a configuration file is to use the load_config function and pass the full path to the file to load through an argument.

>>> pyeapi.load_config('/path/to/my/config/eapi.conf')

Using the load_config function, the default behavior of the searching and loaded a configuration file based on common locations is overridden.

Exploring the connect Function

Up to this point the focus has been on loading the pyeapi client and using the connect_to function to create a node object from a named connection.  This, however, isn’t the only way to connect to eAPI (either locally or remotely).  The Python client provides a connect function for creating connections to eAPI.  The connect function is handy for application developers and devops teams that want to take advantage of the underlying transport and message structures available in pyeapi.

The connect function provides an easy to use function for creating connection objects that maximizes control over the provided input parameters by not requiring the use of a named configuration.  Lets start by taking a look at an example that creates a basic connection to eAPI using an HTTP transport.

>>> connection = pyeapi.connect(host='192.168.1.16')

In the example above, a connection object is created by simply supplying the host address (or domain name) of the destination host.  This provides a connection object that is suitable for sending and receiving eAPI request and response messages.   For instance, we can send the ‘show version’ command to the remote EOS node over eAPI.

>>> connection.enable('show version')
   Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
AttributeError: 'HttpEapiConnection' object has no attribute 'enable'

Huh? What happened?  Since we used the connect function instead of the connect_to function to create the eAPI connection, we are now working with a lower layer of pyeapi.  In this case specifically we now have a connection object which does not provide an enable function.  We can, however, still send and receive commands, but now must use the execute function of the connection object.

>>> connection.execute(['show version'])
{u'jsonrpc': u'2.0', u'result': [{u'memTotal': 2028008, u'version': u'4.14.5F', 
u'internalVersion': u'4.14.5F-2209869.4145F', u'serialNumber': u'', u'systemMacAddress': 
u'00:0c:29:f5:d2:7d', u'bootupTimestamp': 1422470099.8, u'memFree': 333380, u'modelName': 
u'vEOS', u'architecture': u'i386', u'internalBuildId': u'f590eed4-1e66-43c6-8943-cee0390fbafe', 
u'hardwareRevision': u''}], u'id': u'4497043984'}

There, that looks better and is more inline with what we might expect.  Using the connect function creates an EapiConnection object which is responsible for sending and receiving eAPI request and response messages.  The connect function allows for a number of different keyword arguments for creating a connection.  For instance, suppose there is a need to use the local Unix domain socket instead of the HTTP transport (which is the default), we can do something like the example below.

>>> connection = pyeapi.connect(transport='socket')
>>> connection_2 = pyeapi.connect(transport='https', host='veos03', username='eapi',
password='secret')

The example shown uses the transport keyword argument with a value of ‘socket’.  The second example (connection_2) above demonstrates passing multiple keyword arguments to the connect function in order to create a connection.  In this case, creating a connection using SSL and passing the eAPI username and password to the authenticate the connection.  In fact it should start to seem obvious that the connect_to function is a way to take configuration settings from a conf file and map them into a valid connect function.   Indeed that is one of its responsibilities (among a few others which we will save for another posting).

Summary

This article focuses on taking a deeper look at the client functions provided by pyeapi.  It builds on the Introduction to the Python Client for eAPI by further explorer how to use the connect_to function and catch potential problems.  In addition, it digs a little deeper into the configuration capabilities of the pyeapi configuration system and touches on building low level connection objects using the connect function.  Future articles will continue to dive into pyeapi providing information about its implementation and how best to leverage the functionality it provides.

About Arista EOS+ CS

Arista EOS+ CS is an organization that has been created to embrace, alongside our customers, the devops community. EOS+ CS remains focused on delivering technical solutions freely to the open source community for the purposes of advancing innovation around traditional network operational environments. The Arista EOS+ CS team contributes to a variety of open source projects and continues to actively engage in devops communities in support of building more advanced operational and development models that operate next generation massively scalable data center environments.