Avatar

Welcome back to our series of blog posts on network programmability and automation with Cisco Open NX-OS. By now you have become familiar with Vagrant and how to run your own virtual instance of Cisco NX-OS, how to enable NX-API and use the NX-API CLI and NX-API REST. You’ve seen the NX-API Sandbox and how to configure and monitor Cisco Nexus switches using the code generated by the sandbox. You have a considerable set of tools to be able to start automating Cisco Nexus networks at this point. But what if you would like to take network automation to the next level and develop your own NX-OS features? Is that even possible?

Take network automation to the next level

I’m happy to say that YES, you have the option to develop your own NX-OS features, custom CLIs, syslog messages, event and error managers, and whatever custom applications you can think of. In order to do this, Cisco makes available NX-SDK, a C++ abstraction and plugin-library layer that streamlines access to NX-OS backend infrastructure processes. You get the same access to the core components of the Cisco Nexus switches that the Cisco NX-OS developers do when they develop new features and new releases.

Developing your own CLI commands in NX-OS

In this blog post we will explore NX-SDK and how to get started with developing your own CLI commands in NX-OS. The challenge will be to create two new CLI commands: a show command that will display the switch port bandwidth utilization in percentage and a configuration command that will set a port bandwidth utilization threshold that if crossed, a syslog message will be generated.

While you could follow the instructions on Github at to build your own development environment, I chose to use the Docker container. It has all the components and prerequisites included as my development environment. Once you docker pull the image, you can start the container and get access to the bash shell inside the container with the following command:

docker run -it dockercisco/nxsdk:v1.7.5 /bin/bash

This should give you access to the bash shell in the Docker container:

Open NX-OS part 4

Luckily enough a sample NX-OS application that accomplishes exactly the requirements we set initially can be found within the NX-SDK/examples/python folder and it’s called pbwMonitor.

Let’s have a closer look at this Python application

You can either use the vi editor within the Docker container or you can simply git clone the repo on your local machine and open up the /examples/python/pbwMonitor file in your favorite text editor.

This Python application has all the components needed to create the show and config commands for the switch port bandwidth utilization. First and foremost the import nx_sdk_py makes available the nx_sdk_py library within the application. This library will be used to create a hook back into the NX-OS backend processes and to create a new class that extends the NxCmdHandler class. Additional libraries are also included to help with building the application.

The print_port_bw() function takes as input the results of the show interface command, computes the port bandwidth utilization, generates a syslog message if the bandwidth utilization is less or equal to the set threshold and prints to the CLI the bandwidth utilization. On line 66 of the Python application make sure you replace eth_bw = int(value_ascii) with eth_bw = int(value_ascii.split()[0]). This is needed in later versions of NX-OS, including version 9.3.3 that we have running in Vagrant, because the bandwidth output contains also the Kbit word together with the integer value of the bandwidth. The split function applied to the value_ascii string, splits the string into a list of individual strings and eth_bw contains only the first value (index 0) which is the bandwidth value.

Without this modification, when running the application on the switch, you will get the following error message on NX-OS 9.3.3:

Nexus9000v(config)# show pbwMonitor port bw utilization
Port BW Threshold limit: 50

Interface Bw (Rx/Tx Sec Rate) Tx_BW percentage RX_BW percentage
————— ——————– —————— ——————
In method ‘postCliCb’: ValueError: invalid literal for int(): 1000000 Kbit: line 66

The timerThread() function runs every 60 seconds and uses the print_port_bw() function to calculate the bandwidth utilization on all ports and generate the syslog message in case the threshold is crossed.

The pyCmdHandler(nx_sdk_py.NxCmdHandler) class extends the NxCmdHandler class and defines the application callback in the postCliCb() function. The callback handler gets a pointer to the NxCmdHandler and NxCliCmd objects over which the behavior of the two new commands (show_port_bw_util_cmd and port_bw_threshold_cmd) is defined.

The sdkThread() function performs all SDK related initializations in one thread. Gaining access to the NXOS infra is done by instantiating a new NxSdk object:

sdk = nx_sdk_py.NxSdk.getSdkInst(len(sys.argv), sys.argv)

The CLI options available for the two new commands are defined here. The show_port_bw_util_cmd command from the callback function becomes show port bw utilization [<port> | hit-threshold] for the users of the CLI and the config mode command port_bw_threshold_cmd from the callback function becomes port bw threshold <threshold> within the CLI of NX-OS. You can also see here how the command options and their help information are being defined so that whenever you do ? in the CLI the exact information as defined here will displayed to the user.

Final initializations are done at the end of the Python application such as defining global variables, initializing a new sdkThread and timer.

The NX-SDK comes with an RPM generator that takes as input source code files and outputs RPM packages that can be installed on the Nexus switches. In order to generate an RPM package from the pbwMonitor application using rpm_gen.py, the following command needs to be executed inside the NX-SDK Docker container:

python NX-SDK/scripts/rpm_gen.py pbwMonitor -s NX-SDK/examples/python/ -u

The output should look similar to the following:

####################################################################################################
Generating rpm package...
Executing(%prep): /bin/sh -e /enxos-sdk/sysroots/x86_64-wrlinuxsdk-linux/var/tmp/rpm-tmp.9625
+ umask 022
+ cd /enxos-sdk/sysroots/x86_64-wrlinuxsdk-linux/usr/lib/rpm/../../src/rpm/BUILD
+ exit 0
Executing(%build): /bin/sh -e /enxos-sdk/sysroots/x86_64-wrlinuxsdk-linux/var/tmp/rpm-tmp.9625
+ umask 022
+ cd /enxos-sdk/sysroots/x86_64-wrlinuxsdk-linux/usr/lib/rpm/../../src/rpm/BUILD
+ exit 0
Executing(%install): /bin/sh -e /enxos-sdk/sysroots/x86_64-wrlinuxsdk-linux/var/tmp/rpm-tmp.21128
+ umask 022
+ cd /enxos-sdk/sysroots/x86_64-wrlinuxsdk-linux/usr/lib/rpm/../../src/rpm/BUILD
+ /bin/rm -rf /enxos-sdk/sysroots/x86_64-wrlinuxsdk-linux/usr/lib/rpm/../../../var/tmp/pbwMonitor-root
+ /bin/mkdir -p /enxos-sdk/sysroots/x86_64-wrlinuxsdk-linux/usr/lib/rpm/../../../var/tmp/pbwMonitor-root
+ rm -rf /enxos-sdk/sysroots/x86_64-wrlinuxsdk-linux/usr/lib/rpm/../../../var/tmp/pbwMonitor-root//isan/bin/nxsdk
+ mkdir -p /enxos-sdk/sysroots/x86_64-wrlinuxsdk-linux/usr/lib/rpm/../../../var/tmp/pbwMonitor-root//isan/bin/nxsdk
+ cp -R /NX-SDK/examples/python/pbwMonitor /enxos-sdk/sysroots/x86_64-wrlinuxsdk-linux/usr/lib/rpm/../../../var/tmp/pbwMonitor-root//isan/bin/nxsdk
+ exit 0
Processing files: pbwMonitor-1.0-1.7.5.x86_64
Checking for unpackaged file(s): /enxos-sdk/sysroots/x86_64-wrlinuxsdk-linux/usr/lib/rpm/check-files /enxos-sdk/sysroots/x86_64-wrlinuxsdk-linux/usr/lib/rpm/../../../var/tmp/pbwMonitor-root
Wrote: /enxos-sdk/sysroots/x86_64-wrlinuxsdk-linux/usr/src/rpm/SRPMS/pbwMonitor-1.0-1.7.5.src.rpm
Wrote: /enxos-sdk/sysroots/x86_64-wrlinuxsdk-linux/usr/src/rpm/RPMS/x86_64/pbwMonitor-1.0-1.7.5.x86_64.rpm
Executing(%clean): /bin/sh -e /enxos-sdk/sysroots/x86_64-wrlinuxsdk-linux/var/tmp/rpm-tmp.21128
+ umask 022
+ cd /enxos-sdk/sysroots/x86_64-wrlinuxsdk-linux/usr/lib/rpm/../../src/rpm/BUILD
+ /bin/rm -rf /enxos-sdk/sysroots/x86_64-wrlinuxsdk-linux/usr/lib/rpm/../../../var/tmp/pbwMonitor-root
RPM package has been built
####################################################################################################

SPEC file: /NX-SDK/rpm/SPECS/pbwMonitor.spec
RPM file : /NX-SDK/rpm/RPMS/pbwMonitor-1.0-1.7.5.x86_64.rpm

The RPM file that was generated can be found in the /NX-SDK/rpm/RPMS folder and is called pbwMonitor-1.0-1.7.5.x86_64.rpm. As we’ve done before in this series of blog posts, we will use the NX-OS Vagrant instance we have setup previously. First, we copy the RPM package on the local machine and then from the local machine to the Vagrant NX-OS instance.

We will use docker cp to copy files between the Docker container and the local machine:

docker cp 6aff2f444633:/NX-SDK/rpm/RPMS/pbwMonitor-1.0-1.7.5.x86_64.rpm .

where 6aff2f444633 is to container ID and in your case it will have a different value (use docker ps to find the ID of your Docker container).

Next let’s use vagrant scp to copy the RPM from the local machine to the NX-OS vagrant instance. Make sure you install the vagrant-scp plugin if you haven’t already done so:

vagrant plugin install vagrant-scp

In the CLI of the Vagrant NX-OS box, make sure you enable the scp-server and the nxsdk features in configuration mode. The scp-server feature will enable the SCP server on NX-OS and the nxsdk feature will enable NXSDK and provide the commands to install the RPM application:

feature scp-server
feature nxsdk

Using vagrant scp, copy the RPM file from the local machine to the Vagrant NX-OS instance:

vagrant scp pbwMonitor-1.0-1.7.5.x86_64.rpm febea94:/

where febea94 is the vagrant box id for the nxos9.3.3.box (you can find the vagrant box id by issuing the vagrant global-status command). If the RPM file copy from the local machine to the vagrant box went well you should see an output similar to the following one:

Warning: Permanently added ‘[127.0.0.1]:2222’ (RSA) to the list of known hosts.
User Access Verification
pbwMonitor-1.0-1.7.5.x86_64.rpm 100% 6737 1.4MB/s 00:00

Make sure the RPM is indeed on the bootflash of the vagrant box by issuing dir bootflash: at the CLI of the Nexus 9000v instance:

Open NX-OS part 4

Now that the RPM is in the bootflash of the switch, you can install and activate the application. The following config mode commands will accomplish this:

install add bootflash:pbwMonitor-1.0-1.7.5.x86_64.rpm
install activate pbwMonitor-1.0-1.7.5.x86_64
nxsdk service-name pbwMonitor

Open NX-OS part 4

Now that the application has been successfully installed on the switch, you can run the brand new CLI commands:

show pbwMonitor port bw utilization
pbwMonitor port bw threshold <1-100>

Open NX-OS part 4.4

As you’ve seen so far with Vagrant for Nexus 9000v and Docker for NX-SDK, you can very easily build a developer environment on your personal laptop. Let me know in the comments if you have any questions and if you were successful in running your first applications on Cisco Nexus switches.

In the next blog post of this series we will go over CML, and how you can extend your network simulations from one virtual switch to a full blown network.

Please visit the DevNet NX-OS Dev Center for learning tracks and developer resources related to NX-OS. And, if you have questions or comments, please leave me a comment in the space below. I would welcome hearing from you.