sponsored

How to Use On-Box Python Scripts for Cisco Devices

As a junior network engineer at a university I wrote a lot of management scripts in Perl.  I had scripts to do things such as check switchport configurations and upgrade switch code. Times have changed a lot since then. The university’s web server now runs in the cloud, rather than on my personal workstation, and Python has surpassed Perl  as the scripting language du jour. Network automation now has a major focus with Python as an extremely important tool.

Today I’m going to show you how to use Python scripts hosted on the box and integrated into IOS. This is far more powerful than my earlier-career scripts, and I have some simple examples for PCI compliance, Dynamic DNS ACL updates, and configuration validation.

As with many things in IT, we seem to be continually oscillating between “centralized” and “distributed.”  On-box hosting of Python scripts is an example of moving back toward distributed. My view on the argument is that it’s never about the extremes, but more about the balance—a bit like a pendulum constantly swinging as technology advances change what’s possible and practical.

cisco9 image1 developer.cisco.com

In terms of technology advances, there have been many articles recently about Cisco's new Intuitive networking announcement. In case you missed it, here is a short article by Jeff McLaughlin that describes some of the new things you can do with the new network, and one by Chris Oggerino on application hosting.

Today I want to demonstrate why Python scripts running on-box can be awesome. I also want to explain how easy it is, based on the application hosting environment we’ve just released.  In addition, I’ll give some examples of how Python is even more powerful when combined with some of the existing IOS infrastructure such as Embedded Event Manager (EEM).

Why on-box Python?

There are three main advantages for Python scripts running on the device itself rather than externally.

  • Scale: If I have a “sanity” script that I need to run regularly and it takes six seconds per device * 1000 devices, that would be 6,000 seconds, or one hour and 40 minutes. I could run them in parallel, but that still consumes resources on my management station, processing the data.  It also potentially transports lots of data back to the management station, only to discard much of it.  An alternative is to distribute the work to the devices and get them to provide an update when they’re done.
  • Security: Instead of having “utility” logins that connect into devices and export information for external processing, you can have the device process its data locally and just export the summary state. Data stays on the device, and less external connections are required.
  • Autonomy: The biggest limitation of centralized processing is that it needs a network connection to the device. There is a set of use cases to modify device behaviour when it loses connectivity to other devices. This can only be done on-box.

What, by example

To illustrate the “what,” I’ve provided some sample scripts and use cases for the three points above. The code is published @  https://github.com/aradford123/on-box-python.git

To get started, we’re going to want to make sure Git is installed on your network device, run the following commands (after you’ve enabled guestshell; see section at the end for details). The reason for using /flash/gs_script is that it’s a persistent directory and will be available on a switch stack switchover.

cisco9 image5a developer.cisco.com

Example 1 - PCI compliance

Here’s an example of a use case that I think you’ll find interesting. One of our customers had a PCI requirement to ensure that any switch ports that were unused for more than seven days were disabled. (This was to prevent people from plugging in unauthorized devices.)

The script  looks at all interfaces on the switch, and those that have been inactive (no traffic send/received) for more than seven days are shutdown. All interfaces that were shut down in a logged in a Cisco sparkroom. The interface description is updated with a message indicating the time/date it was shutdown by the PCI-check application.

cisco9 image4 developer.cisco.com

To run the script, we’ll use the Embedded Event Manager. EEM is a really powerful piece of IOS infrastructure that can be used to schedule the Python script to run. The EEM cron job runs the Python script at 15 minutes past the hour, Monday to Friday.

cisco9 image6a developer.cisco.com

This script can now be run hourly (instead of weekly). It’s an example of scaling using on-box Python.

Example 2 - DNS ACL

Another customer had a requirement to keep an ACL updated with the latest DNS entries. For example, they wanted the ACL to reflect the real IP addresses of www.cisco.com and www.amazon.com.

This script automatically schedules its next execution based on the minimum Time To Live (TTL) of the DNS response. It ensures we don’t attempt to update more often than necessary.

The script logs entries that are added to the ACL via syslog, but that could be Cisco Spark or any other notification mechanism.

cisco9 image7a developer.cisco.com
developer.cisco.com

Here is the resulting ACL. Notice how the remarks are used to indicate the time the ACL changed. The last two entries were added at a later date.

cisco9 image8a developer.cisco.com
developer.cisco.com

This script uses a different type of EEM trigger, a countdown timer. The script self-updates the trigger based on the TTL of the DNS response. In the case below, it will fire in the next 557 seconds.

develoeveloper.cisco.com
cisco9 image9a developer.cisco.com

This is an example of security using on-box Python. No external access to the device is required

Example 3 - Configuration change

This example uses an EEM event to look for a syslog message and execute a Python script. In this case, it looks for a configuration event, and fires the script.

This script will do two things:

  • A sanity check. This example is a simple test to see if an IP address is reachable, but it could be more sophisticated. If the sanity check fails, then the configuration is rolled back.
  • Log the changes to the configuration in a spark room.

This screenshow shows the configuration diff posted to a spark room.

cisco9 image9 developer.cisco.com

Here’s an example of the sanity check:  I have a very simple sanitiy check that is looking for connectivity to 1.1.1.1. While this example is trivial, the sanity check could be much more sophisticated (checking for OSPF neighours, number of connected hosts, etc.). 

I shut down the loopback address 1.1.1.1, which is being checked by the sanity function. The sanity function fails, triggering configuration rollback, and the current (working) configuration is restored.

cisco9 image10a developer.cisco.com

There are lots of other options for this script, including checking into a git repository and more enhanced sanity checks.

This Python script uses EEM in a different way. The first line of the script embeds an EEM registration. If there is a syslog message with pattern "CONFIG_I" in it, the script will be executed. (NOTE: This is actually a Python script, and the normal Python code is after this.)

cisco9 image11a developer.cisco.com
developer.cisco.com

I then tell EEM to look for the registration in the config_check.py script.

cisco9 image12a developer.cisco.com
developer.cisco.com

This is an example of autonomy; if the configuration is changed, a sanity check is run to make sure the device is still functioning (and connected) to the network. If the sanity check fails, the configuration is rolled back.

Upgrade sanity check

It’s pretty simple to extend the use case above to check the status of the device before downloading and installing new software. Once the new code is installed, it will re-run the sanity check and either remove the old version of code or roll back depending on the status of the sanity check.

This is another example of autonomy using on-box Python.

How does this really work?

Python runs in a guestshell on the device. The guestshell is CentOS or Montevista shell running as an application on the device. In order to enable application hosting you need to use the application hosting framework IOX. To enable IOX is quite easy:

cisco9 image13a developer.cisco.com
eveloper.cisco.com

You then need to enable guestshell. This will take a few seconds.

cisco9 image14a developer.cisco.com
developer.cisco.com

Once it has started, you can either run a command or get an interactive shell session.

cisco9 image15a developer.cisco.com
developer.cisco.com

The very first thing you will do is update the DNS settings. You can use vi, or just a simple echo statement.

cisco9 image16b developer.cisco.com
eveloper.cisco.com
veloper.cisco.com

Now to install some Python modules. This is pretty simple. Just use pip install. I am using the “-E” option as my switch needs a proxy to get to the internet. 

cisco9 image17a developer.cisco.com

DevOps

The next question you’re asking is how do I keep the scripts on the device updated? It would be a pain to have to copy/install new scripts all the time. 

The solution is pretty simple. Store the scripts in a git repository (so you have full version control), then use an EEM script to “git pull” regularly to keep them updated. 

Here’s a simple git update script:

cisco9 image18a developer.cisco.com
developer.cisco.com

All that’s required is another EEM cron job to keep the device updated with the latest git repository.

picture2 developer.cisco.com
developer.cisco.com

Conclusion

This blog post looked at some simple use cases for running Python scripts on-box in IOS-XE. It builds on earlier posts that discussed the importance of application hosting and device programmability.

I highlighted three categories of use case, namely:

  1. Scale: due to distributed execution.
  2. Security: as “management” accounts aren’t required to “log in” to a device to perform tasks.
  3. Autonomy: as the device can react to losing network connectivity.

The Embedded Event Manager is a powerful IOS tool that aids the execution of the Python scripts. I showed three different execution models:

  1. “Cron” or pre-scheduled. This is for scripts that need to run at a certain time of day, hour, week etc.
  2. Countdown timer. This is for scripts that need to run at a certain time into the future
  3. Event based. A script that runs when a certain event occurs.

I’ll be putting more details about the mechanics of the scripts on my blog site.

You can learn more about on-box Python and Guestshell on the Cisco DevNet Python Network Automation site.