IDE

The general problem is this: you want a systematic way of creating network device configurations based on templates and variables.

As background, Ansible is an open-source automation application that can be used to automate many tasks in your environment (predominantly compute and cloud tasks). Ansible can also generate files based on Jinja2 templates and variables. Jinja2 is a widely-used Python templating system, see http://jinja.pocoo.org/ for more information about Jinja2.
Thus, Ansible has all the components for network configuration templating built into it. This is a very good initial use case for Ansible for network engineers.

Week 4

SNMP

In this article, I briefly introduce Python and SNMP using the pysnmp library.

I assume that you already have some knowledge on SNMP including MIBs and OIDs. If not, you should be able to find this information fairly easily on the Internet.

In order to get started, you need to install the pysnmp library. For context, I am testing on an AWS AMI server (RedHat based i.e. yum instead of apt).

For installation just use ‘pip’:
# As root or sudo (or in a virtual environment)
$ pip install pysnmp

I also installed net-snmp to simplify testing and to add an easy way to perform an SNMP walk. The installation method for net-snmp will vary depending on your system.

# As root or sudo
$ yum install net-snmp
$ yum install net-snmp-utils

To keep things simple I am only going to use SNMPv1/2c (i.e. this article does not cover SNMPv3). This is obviously not secure.

Now that I have the pysnmp library installed, the next step is to verify that I can communicate with my test router using SNMP. First, let’s test this directly from the Linux command line:

$ snmpget -v 2c -c <COMMUNITY> <IP_ADDR> .1.3.6.1.2.1.1.1.0
SNMPv2-MIB::sysDescr.0 = STRING: Cisco IOS Software, C880 Software (C880DATA-UNIVERSALK9-M), Version 15.0(1)M4, RELEASE SOFTWARE (fc1)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2010 by Cisco Systems, Inc.
Compiled Fri 29-Oct-10 00:02 by prod_rel_team
The OID .1.3.6.1.2.1.1.1.0 is the MIB-2 sysDecr object. During testing I had multiple problems getting SNMP to work on the router including that I had Cisco’s Control Plane Policing enabled (ooops) and that I needed to allow access through both an edge ACL and through a separate SNMP ACL.

At this point, I am able to communicate using SNMP from my AWS server to my test router.

Now let’s try the same thing except using the pysnmp library. In order to simplify this I have created a couple of SNMP helper functions see:

This code loads my two functions (snmp_get_oid and snmp_extract); it also creates a tuple named ‘a_device’ consisting of an IP, community string, and port 161.

I then call my snmp_get_oid function using the OID of MIB-2 sysDescr:
>>> snmp_data = snmp_get_oid(a_device, oid=’.1.3.6.1.2.1.1.1.0′, display_errors=True)
>>> snmp_data
[(MibVariable(ObjectName(1.3.6.1.2.1.1.1.0)), DisplayString(hexValue=’436973636f20494f5320536f6674776172652c204338383020536f6674776172652
02843383830444154412d554e4956455253414c4b392d4d292c2056657273696f6e2031352e302831294d
342c2052454c4541534520534f4654574152452028666331290d0a546563686e6963616c20537570706f72
743a20687474703a2f2f7777772e636973636f2e636f6d2f74656368737570706f72740d0a436f7079726967
68742028632920313938362d3230313020627920436973636f2053797374656d732c20496e632e0d0a436
f6d70696c6564204672692032392d4f63742d31302030303a30322062792070726f645f72656c5f74656
16d’))]
I can see that I received SNMP data back albeit in an ugly format. I can now use the snmp_extract function to display the output in a more friendly way.

Now, let’s repeat this process but using a different OID. Using snmpwalk on the ‘interfaces’ MIB and the Cisco SNMP Object Navigator, I was able to determine that the OID = .1.3.6.1.2.1.2.2.1.16.5 corresponded to the output octets on FastEthernet4.

Note, this data structure is a dictionary that contains additional dictionaries. The key to the outer dictionary is a hostname and the data corresponding to this key is another dictionary. For example, for ‘R1’:

# Assign the key ‘R1’ to network_devices using a value of a blank dictionary (in other words, I am adding a key:value pair to network_devices where the key is ‘R1’ and the value is {} )
>>> network_devices[‘R1’] = {}

# Look at network_devices at this point
>>> network_devices
{‘R1’: {}}

2. Create a second program that expands upon the program from exercise 1.

This program will keep track of which network devices are physically adjacent to each other (physically connected to each other).

You will accomplish this by adding a new field (adjacent_devices) to your network_devices inner dictionary. adjacent_devices will be a list of hostnames that a given network device is physically connected to.

For example, the dictionary entries for ‘R1’ and ‘SW1’ should look as follows:

For the output to this exercise, print network_devices to standard output. Your output should look similar to the following (six network devices with their associated attributes including ‘adjacent_devices’).