Tuesday, November 16, 2010

Python Programming and the Network Engineer

I’ve recently rediscovered my interest in computer programming.  As I mentioned before, I once was an avid programmer.  In my youth I hacked around in C++ and x86 assembler, making interesting little programs that didn’t accomplish much, but which gave me a great sense of accomplishment.  In high school, I was a member of the third place team in a national computer programming competition.  One of my teammates is now a software engineer at Google, so maybe I wasn’t exactly the star of the show, but my contributions seemed important at the time.  :)
My college years went a long way toward suppressing any interest I had in programming computers.  The rote, repetitive routine of programming compilers, operating systems, database engines, etc, drove me directly into a career of infrastructure work.  I have no professional regrets, but I do sort of miss the thrill of writing working code.  There is a great sense of satisfaction derived from formulating an idea and seeing it through from a blank Notepad++ document to a working, debugged applicati0n.
A couple of months ago I was faced with a project that resurrected my interest in programming.  My team and I have been working steadily toward standardizing our network deployments.  Standardization is a key requirement to effectively managing a large network with a small number of engineers.  Prior to this effort, such things as VLAN numbering and port-level configurations varied between our locations, even when two offices were roughly similar in size.  One of the causes of this was the melding of several different IT organizations when my employer was created.  We also acquired several smaller companies since our genesis in 2004.
To accomplish our switchport standardization, we use the description field to identify the type of device that is connected to a specific switchport.  If a PBX is connected to a port, the description field would be something like:
interface Gigabit1/1
description PBX; Name_of_PBX

and if the port is connected to an end user, we would use:
interface Gigabit1/2
description USR; John Doe – patch-panel 1A

The text after the semi-colon is free-form, and can be defined on a site-by-site basis to be whatever is relevant to the local support team.
PBX ports require a different set of configuration statements than USR ports.  For one example, we need a “DSCP trust” statement on the PBX port, while we remark USR traffic with a specific QoS policy using the “service-policy input USR-POLICY” command.
Our standardization effort is now largely complete.  Our latest challenge is making sure our configurations stay standardized.  VLAN identifiers are easy, since it is quite painful to change them.  Switchport configurations are a very different story.  It is quite easy for a switchport to be configured incorrectly but still work in a suboptimal fashion.  For example, if the wrong QoS marking policy is installed, basic testing will work (ping, etc), but under load there will likely be performance issues.  Even if the proper template is used to activate a port, it can be difficult to prevent that port from being reused for another purpose.
My solution to this issue was to implement an audit process that would take a baseline configuration and compare it to our production switch configurations.  I first reached out to our primary network tools provider, Solarwinds.  Their current feature provides some of the features I need, such as verifying that specific lines exist in the configuration.  But they cannot yet do context-sensitive configuration checking.  Other vendors (such as Netcordia) could perform this task, but I had recently championed a network tools consolidation project, so it would be a bit hypocritical of me to request funding for a new tool.  I decided to learn a scripting language to try and tackle this need.  A friend suggested that Python or Perl would fit the need nicely, so I chose Python (for no particularly good reason) and began learning.
I was quite surprised as how easily I learned the language and was able to solve my problem.  I spent a total of eight hours from the time I settled on Python until I had a working prototype.  The small investment of time is primarily due to the ease of use of the Python language, and not my programming acumen.
The entire script is a few hundred lines, including comments, and it meets all of my needs.  I wouldn’t say it is terribly user friendly, and I have a laundry list of additional features and ‘opportunities for improvement’, but I am happy with the result.  If I can find the time (and there is interest), I’ll clean it up and publish it in separate blog post.  It is generic enough that other organizations can probably use it without a lot of rewriting.


Jay Swan said...

I'd love to get a copy, no matter how user unfriendly. I've been working on something similar and could definitely use the help.

Trem said...

I would very much like to see your script for this. I'm interested to see what it does and your design for it.

Jeremy Filliben said...

I am glad there is some interest in this script. I'll clean it up a bit and publish it. I am hopeful that I can have it up by the end of the week.

Thank you for reading,

verbosemo.de said...

That sounds great. Maybe you also want to have a look at the Python module CiscoConfParse for parsing IOS configs. Here is a short demo:

>>> from ciscoconfparse import CiscoConfParse
>>> config = CiscoConfParse("sw1.txt")

Find interfaces with the default port mode dynamic desirable/auto.

>>> config.find_parents_w_child("^interface", "switchport mode dynamic")
['interface FastEthernet0/13']

Find interfaces without a description.

>>> config.find_parents_wo_child("^interface", "description")
['interface FastEthernet0/3', 'interface FastEthernet0/5']

Test if password-encryption is enabled

>>> config.find_lines("^service password-encryption")

Best Regards,


1) http://www.pennington.net/py/ciscoconfparse/
2) http://pypi.python.org/pypi/ciscoconfparse/0.8.3a

Jeremy Filliben said...


That's a great find. I'll be sure to use that in future versions of this script.

Thank you,