Skip to main content

Python Crumbs for Cisco routers - Part I

In this series I want to show you how to use Python to solve some common tasks related to Cisco router scripting.

Update, 2018.06 : I compiled a short training video that will teach you the basic Python scripting in PGT. If you prefer watching a video over reading the article, this is exactly for you : PrettyGoodTerminal - Using Python Scripts

This tutorial will focus only on - so to say - applied Python language and won't go into details with Python syntax or language elements itself for one very good reason : at the beginning you probably want to have results quickly without reading hundreds of pages about the language. I always affirmed that learning something new is much easier when you get  a grasp on it on a practical way.

The most common task I came across is getting some basic information of  a router or switch, like system uptime, version, interface status, etc. Of course, you don't need Python for simple queries, but when you need to do some text processing, a script language gets necessary.

As I pointed out in my earlier post, using Pretty Good Terminal (PGT) makes stuff like these very easy because you don't have to mess with telnet or ssh connenction setup / teardown, it is managed automatically by PGT itself.

So let's say you have a couple of routers given by  and you need to theirs management address and you want to get IOS version, router HW version and system uptime.

If you were entering CLI commands using your favorite terminal program, you would issue a single commands "sh version" then you would search for the various elements in the output or use grep like syntax to filter the output. Let's do this with Python now.

As PGT will manage all the telnet/ssh connections for you, the script do not have to take care about it. When the script gets invoked for a particular device connection will have already been established, so you only need to send the desired command and process the result.

Let's stop for a while here. In order to connect to routers/switches, PGT obviously needs to know the username and password used for connection. So the very first thing you need to do is go to Tools/Options and set your credentials :


To interact programmatically with the router, PGT provides an object named Terminal which encapsulates the functionality of a terminal emulation program. You can send a command and get the command result back by simply using the ExecCommand function. So using Python syntax, this would be as simple as:

Terminal.ExecCommand("sh version")

You also need to store the command result text to process it later, so let's change the above line like this :

commandResult = Terminal.ExecCommand("sh version")

Now commandResult is the variable you use to store the result in text format. It is now a string type variable. The next step is to pick the information needed out of this text. This is simple text processing, and your good friends will be the following  string functions:
- splitlines() : as the value returned by the "sh version" command (which is now stored in commandResult variable) is a multi-line text, you need to transform to a string list for easier processing; Each elemend of the list will correspond to a line.
- strip() : use this function to remove specific leading and trailing characters from text
- find() : use this function to get the starting index of a substring in a string

Before going further, lets get to this point at least with your script and have the text returned. So open a new Python Interactive window from the action menu, and enter the following script :


The next step would be to execute this script and check the returned value. To do so, give a name you want to the script at the bottom of the form and click Register as Custom Action ID, like this:

With the above action, you basically named your script.

To construct a device list on which the script will operate, select Generate Script from the action menu. Enter some device ip into the Device List field (one by line) you want to connect to, then click Add Command and select the name of your script you just have set from the Custom Action ID drop down list:


Click Ok then Generate script. You should have a similar view now:

 This "Script 0" tells PGT to connect to 10.10.10.2 then run the script named "test". Let's click on "Execute Now" in the Script menu. PGT will then connect to the router and switch to the Python Interactive window once connected. Notice the form title is now showing connected to 10.10.10.2:, as well as the status bar displays "Acting as Custom Action Handler":


Now you are ready to start the Python script. Click Run or press F5 to invoke the script. If you arranged the windows in a way that you can see the terminal output, you can observe the command was executed. If you move the mouse pointer above the commandResult variable, it will show its current value :


You can edit the script as you need, then run the script as many times as you want.

Now, let's select all lines that starts with the string "Cisco". Python is great at working with lists and you can express this task with quite a brief statement. However, I want to go step by step, so I will show you the ugly way, then the effective Pythonic approach.

Let's first split the text to lines using splitlines() function, and store it in another variable :

resultLines = commandResult.splitlines()

To examine the contents of resultLines, you can also use the print() function and check the output :

print(resultLines)

To see the difference between commandResult and resultLines, let's print both, like this:
# get version information
commandResult = Terminal.ExecCommand("sh version")
# split the text to lines
resultLines = commandResult.splitlines()
# print out what we got
print ("resultLines are:")
print(resultLines)
# also print commandResult and compare the outputs
print ("commandResult is:")
print(commandResult)

Here is what you should see now :

If you study the output closely, you can see that resultLines is a list of strings separated by colons, while commandResult is a contiguous text. List is better in a way that you can index its elements easily, like resultLines[5]. This would mean the 5th line.
Using this approach you can iterate through all lines, and pick those starting with the word "Cisco". To do so, you will be using the for iterator, like this:

for line in resultLines :
  if line.startswith("Cisco") :
    print(line)

Let's runt the script  :

Success ! You selected what you wanted. A small problem still, that we need to process further the result, so let's store it another variable, preferably in a list. To do so, create an empty list, then add the selected lines to it. Then run the script ans check the result:

And finally you have it !

Now you can bundle all these actions to a single, brief statement, exactly producing the same result:

versions = [line for line in commandResult.splitlines() if line.startswith("Cisco")]

One could read the above statement in human language as : select the line variable from the list produced by commandResult.splitlines() function only if that line starts with the string "Cisco" and then construct a list from the lines selected this way.

It is worth mentioning that if you work longer with a script, it can happen that the underlying telnst/ssh connection times out. If this happens and you try to run your script, you will see an error message returned by ExecCommand:

Anyway, by now you have successfully filtered the text returned by the command "show version". Let's parse it further to select the IOS and HW version. 
Using the nice list transformation expression introduced  above, use the first line of the versions list variable (vsrions[0]) and split it to words at each comma (split(",")) and also strip the leading and trailing spaces (strip(" ")) constructing a new list :

# First line contains IOS Version
CiscoVersionInfo = [ v.strip(" ")  for v in versions[0].split(",")]

This variable will contain the following now:

Following the above logic, parse this variable further to get IOS version substrings. There is one more magic to play with : regex ! Regex is very powerful for searching strings and Python of course supports it. The only extra thing you need to do is to use the library (named module in Python) that deals with regex processing. It is  named "re" and you will need to import this module at the beginning of the script with the statement :

import re

Afterwords you can refer to any functions in this module by prepending the function name with "re.". You can effectively use the findall() function to process the version info string like "12.4(15)T14" and to split it to a list of  strings like ["12","4","15","T14"] like the below example shows:

# Calculate IOS version numbers
_IOSVersion = CiscoVersionInfo[2]
_IOSVersionNumber = _IOSVersion.split(" ")[1]
_IOSSubVersionNumbers = re.findall(r"[\w']+", _IOSVersionNumber)
IOSMajorRelease = _IOSSubVersionNumbers[0]
IOSMinorRelease = _IOSSubVersionNumbers[1]
IOSMaintenanceNumber = _IOSSubVersionNumbers[2]
IOSTrainID = _IOSSubVersionNumbers[3]

Followig the same logic you can also process the HW version :
# Calculate Router HW version
HWVersionInfo = [ v for v in versions[1].strip(" ").split(" ")]
HWPlatform = HWVersionInfo[0] + " " + HWVersionInfo[1]

To be continued...

Comments

  1. Dear ,

    can we download this tool from any place ?

    regards
    mostafa

    ReplyDelete
  2. Hello Mostafa, you can obtain PGT from http://www.prettygoodterminal.com

    ReplyDelete
  3. Hi,

    Can i know where do I enter the username/password for my Cisco device?

    ReplyDelete
  4. Hi,

    How/where do I enter the username/password of the Cisco device?

    ReplyDelete
    Replies
    1. Hi,

      you do that normally in tools/options dialog box. Set the device username / password / enable password strings for the current profile.
      You also have the option to specify individual credentials for devices when you specify a password file.

      Just let me know if you need further assistance.

      Laszlo

      Delete

Post a Comment

Popular posts from this blog

Python scripting lesson for Juniper switches

Collecting comprehensive switch interface information When working with Juniper EX / QFX switches it is often required to collect comprehensive interface status data. Not any single show command will provide all the details and merging the output of several commands is quite time consuming.  On top of this, it can be tricky to find free ports on switches, because unconfigured ports are simply not shown in many commands and the only way to find out available ports is examining the chassis hardware components. In the following article I would like to show you an easy way of collecting such information quickly by using Pretty Good Termina l.    PGT is completely free for private use so you don’t need to worry about any costs involved. What the script does As part of the standard installation, PGT contains a sample Visual Script designed for Juniper EX /QFX switches to collect switch interface information. The script will issue the following CLI commands and m

Using Python to script Cisco routers

A year ago or so I posted an article on LinkedIn,  How to configure 50000+ CPE routers .  Now I want to go a step further in scripting and share you my way of using Python for scripting Cisco routers. I show you the software and its usage for large scale scripting deployment because I do believe it is an extremely powerful network scripting tool, and all who face similar challenges might find it a good friend. It is not a commercial, I do use the software every day and I develop  Pretty Good Terminal  as needed to achieve my goals quicker and simpler in a more & more elegant way. In this article I do not wan to dive deep into scripting details but rather just flash some cool features of PGT worth highlighting. Should you be interested in details, you will find quite detailed descriptions about these features on the website of the software. A Visual Script using Python The software I developed for router mass-configuration has evolved a lot since its first publication an