What You’ll Learn

What You’ll Need

Cisco NSO is a powerful configuration engine, but it also has the capability to send operational commands to the network devices it manages. This is often very helpful when you are building services or scripts to include some verification steps or to gather additional data about the state of the network to feed into your decision-making logic in your code.

NSO’s features are equally accessible across all the APIs (aka “feature parity”), which is uncommon in a lot of network automation tools, so you can explore the functions of NSO in a more interactive way in the CLI or GUI first before using the API. Because the CLI structure is modeled after the same YANG application data model as the API, the naming conventions and logical hierarchy in the CLI will be present in the API. This will give you a mental picture of what to expect when you see the Python code after using the NSO CLI.

Sending a Show Command Using the NSO CLI

After your NSO Sandbox reservation is up, log into the 10.10.20.49 system install server. It already has a populated device list and a running instance. The device we will be working with is an IOS XE device called dist-rtr01.

Issue the ncs_cli command in the Linux shell prompt to enter into the NSO CLI, and then view the device list with the show devices list command:

[developer@nso ~]$ ncs_cli

User developer last logged in 2022-07-26T10:23:16.057236-07:00, to nso, from 10.10.20.49 using rest-https
developer connected from 192.168.254.11 using ssh on nso
developer@ncs# show devices list
NAME             ADDRESS       DESCRIPTION  NED ID                ADMIN STATE
-----------------------------------------------------------------------------
core-rtr01       10.10.20.173  -            cisco-iosxr-cli-7.32  unlocked
core-rtr02       10.10.20.174  -            cisco-iosxr-cli-7.32  unlocked
dist-rtr01       10.10.20.175  -            cisco-ios-cli-6.67    unlocked
dist-rtr02       10.10.20.176  -            cisco-ios-cli-6.67    unlocked
dist-sw01        10.10.20.177  -            cisco-nx-cli-5.20     unlocked
dist-sw02        10.10.20.178  -            cisco-nx-cli-5.20     unlocked
edge-firewall01  10.10.20.171  -            cisco-asa-cli-6.12    unlocked
edge-sw01        10.10.20.172  -            cisco-ios-cli-6.67    unlocked
internet-rtr01   10.10.20.181  -            cisco-ios-cli-6.67    unlocked
developer@ncs#

Now if you want to see the capabilities of what NSO can do with a device outside of configuration mode, use the ? to see the options (where live-status will show up):

developer@ncs# devices device dist-rtr01 ?
Possible completions:
  add-capability          This action adds a capability to the
                          list of capabilities.
  capability              A list of capabilities supported by
                          the device
  check-sync              Check if the NCS config is in sync
                          with the device
  check-yang-modules      Check if NCS and the device have
                          compatible YANG modules
  compare-config          Compare the actual device config with
                          the NCS copy
  config                  NCS copy of the device configuration
  connect                 Connect to the device
  copy-capabilities       Note: this action overwrites existing
                          list of capabilities.
  delete-config           Delete the config in NCS without
                          deleting it on the device
  disconnect              Close all sessions to the device
  find-capabilities       This action overwrites existing list
                          of capabilities.
  live-status             Status data fetched from the device
  live-status-protocol    Additional protocols for the
                          live-tree (read-only)
  migrate                 Migrate the device to a new NED type
  netconf-notifications   NETCONF notifications from the device
  ping                    ICMP ping the device
  scp-from                Secure copy file to the device
  scp-to                  Secure copy file to the device
  ssh                     SSH connection configuration
  sync-from               Synchronize the config by pulling
                          from the device
  sync-to                 Synchronize the config by pushing to
                          the device
developer@ncs# devices device dist-rtr01

After selecting live-status, the only option after that is exec, and then see what the options are at that point:

developer@ncs# devices device dist-rtr01 live-status ?
Possible completions:
  exec   Execute commands on device
developer@ncs# devices device dist-rtr01 live-status exec ?
Possible completions:
  any          Execute any command(s) on device.
  any-hidden   Execute any command(s) on device, nothing will
               be logged.
  clear        Reset functions.
  copy         Copy from one file to another.
  license      Smart licensing Commands.
  ping         Send echo messages.
  reload       Halt and perform a cold restart.
  show         Execute show commands.
  traceroute   Trace route to destination.
  verify       Verify a file.
developer@ncs# devices device dist-rtr01 live-status exec

At this point, you could use the show option, but the any option will also allow us to send show commands. Type in any and the command you want to be sent (show ip interface brief), such as devices device dist-rtr01 live-status exec any show ip interface brief:

developer@ncs# devices device dist-rtr01 live-status exec any show ip interface brief
result
Interface              IP-Address      OK? Method Status                Protocol
GigabitEthernet1       10.10.20.175    YES NVRAM  up                    up
GigabitEthernet2       172.16.252.21   YES NVRAM  up                    up
GigabitEthernet3       172.16.252.25   YES NVRAM  up                    up
GigabitEthernet4       172.16.252.2    YES NVRAM  up                    up
GigabitEthernet5       172.16.252.10   YES NVRAM  up                    up
GigabitEthernet6       172.16.252.17   YES NVRAM  up                    up
Loopback0              unassigned      YES unset  administratively down down
dist-rtr01#
developer@ncs#

One trick to note is that at this point, you can also save the output using the | save option appended at the end of your command. It will save the file in the directory where you initiated the NSO CLI, such as devices device dist-rtr01 live-status exec any show ip interface brief | save sh-ip-br.txt:

developer@ncs# devices device dist-rtr01 live-status exec any show ip interface brief | save sh-ip-br.txt
developer@ncs# exit
[developer@nso ~]$ ls
Desktop    shutdown.sh
Downloads  sh-ip-br.txt
[developer@nso ~]$ cat sh-ip-br.txt
result
Interface              IP-Address      OK? Method Status                Protocol
GigabitEthernet1       10.10.20.175    YES NVRAM  up                    up
GigabitEthernet2       172.16.252.21   YES NVRAM  up                    up
GigabitEthernet3       172.16.252.25   YES NVRAM  up                    up
GigabitEthernet4       172.16.252.2    YES NVRAM  up                    up
GigabitEthernet5       172.16.252.10   YES NVRAM  up                    up
GigabitEthernet6       172.16.252.17   YES NVRAM  up                    up
Loopback0              unassigned      YES unset  administratively down down
dist-rtr01#
[developer@nso ~]$

Now that you have some familiarity with the live-status feature, let’s see it in action in the Python API.

The Python library for NSO is not something you can install. It automatically is inserted into the Python path for the Linux host where NSO is installed. The library can only be run on the same host as the NSO instance. It is called ncs, and recent releases only allow it to be used with Python 3.

Using the NSO Python Library

First, create a file called nso_show_commands.py in the current working directory. I used VS Code Remote Explorer, but you can use vim or nano as well:

[developer@nso ~]$ ls
Desktop    nso_show_commands.py  shutdown.sh
Downloads  sh-ip-br.txt
[developer@nso ~]$

In that file, import the NSO ncs Python library and start with the following statement:

import ncs

with ncs.maapi.single_read_trans('admin', 'python', groups=['ncsadmin']) as t:

That first statement basically opens a transaction into NSO using the object t as the transaction handler. Even though we are not going to make any configuration changes to the device, we still need to get access to the NSO application to send the show commands.

Now let’s add two more lines to the script:

import ncs

with ncs.maapi.single_read_trans('admin', 'python', groups=['ncsadmin']) as t:
    root = ncs.maagic.get_root(t)
    device_cdb = root.devices.device["dist-rtr01"]

We pass the t transaction object into the get_root method to get to the root of the NSO application data model. Think of this as getting to the base of the NSO CLI prompt and saving that place in the hierarchy into root. Now that we have access to NSO and are at the root, we can navigate to certain parts of the application hierarchy and save variable names as shortcuts that make it easier to read. The device_cdb is basically a device object that looks at the device list and then looks up the particular device dist-rtr01. We used the name device_cdb as a shorthand to remind us that this is an object in the NSO CDB referring to a device.

We are at this point in the CLI:

developer@ncs# devices device dist-rtr01 ?

So now we need to access the live-status feature and feed in the inputs. I am not going to explain all the details at this point for the sake of brevity, but you can refer to the CLI portion and compare it to the Python lines:

developer@ncs# devices device dist-rtr01 live-status exec any show ip interface brief 

Finish the script with the following lines:

import ncs

with ncs.maapi.single_read_trans('admin', 'python', groups=['ncsadmin']) as t:
    root = ncs.maagic.get_root(t)
    device_cdb = root.devices.device["dist-rtr01"]
    input1 = device_cdb.live_status.ios_stats__exec.any.get_input()
    input1.args = ["show ip interface brief"]
    show_command = device_cdb.live_status.ios_stats__exec.any(input1).result
    print (show_command)

Run the script with python3 nso_show_commands.py, and you can see the output:

[developer@nso ~]$ python3 nso_show_commands.py

Interface              IP-Address      OK? Method Status                Protocol
GigabitEthernet1       10.10.20.175    YES NVRAM  up                    up
GigabitEthernet2       172.16.252.21   YES NVRAM  up                    up
GigabitEthernet3       172.16.252.25   YES NVRAM  up                    up
GigabitEthernet4       172.16.252.2    YES NVRAM  up                    up
GigabitEthernet5       172.16.252.10   YES NVRAM  up                    up
GigabitEthernet6       172.16.252.17   YES NVRAM  up                    up
Loopback0              unassigned      YES unset  administratively down down
dist-rtr01#
[developer@nso ~]$

Once you have that output, you can then put it through other industry-standard parsing engines to get structured data from the show command output (example: TextFSM or Genie and others).

You can also include similar code within your Python service code or put them in NSO actions.

Learn More