SR OS and Python 3 - 101

Getting started with Python 3 and SR OS

Introduction

This article runs through the basics of making a NETCONF connection to an SR OS device and obtaining the running configuration.  It will cover a few elements:


  • Installing Python 3
  • Creating a Python virtual environment
  • Installing Python modules

  • Making NETCONF connections from Python scripts/programs
  • Obtaining the running configuration


This article is not a detailed article on how to use Python and it does not provide details on the only way to or recommended way to communicate with SR OS devices or write Python programs.  The article will get you going with a way of automating SR OS in Python.


This article assumes that your system is not behind a proxy.


Elements used in this tutorial


Element Version
Linux workstation/server CentOS 7
SR OS device running in Model-Driven mode 19.7.R1
Python 3.6


Installing Python 3

The default Python interpreter for CentOS 7 is currently Python 2.  Python 2 will be end of life in 2020 so this tutorial will use Python 3.


Ensure that the epel-release Yum repository is installed and enabled:


yum install -y epel-release


Now install Python 3.6 and the Python virtual environment package:


yum install -y python36-distro virtualenv


Creating a Python virtual environment

The tools are installed to get started with Python.  Python could be run natively, however, it is safer and more flexible to install and run Python in a virtual environment.  This allows multiple instances of Python to be easily used on the same machine.


Choose a base directory for this tutorial and change to it.  For this tutorial we will use sros-python-101.



mkdir sros-python-101
cd sros-python-101

Create the virtual environment called venv and enter into it with these commands:


virtualenv -p python3 venv
source venv/bin/activate


The prompt will change to include (venv) at the beginning.   If you need to leave the virtual environment at any point you can type:


deactivate


Remain in the virtual environment to continue.


Installing Python libraries

In this example, our program will use two libraries:


  • argparse - Handles command line arguments
  • ncclient - NETCONF client


The argparse library is installed by default with Python so nothing is required for this; however, ncclient does need to be installed into our virtual environment.  Install it now:


pip install -U ncclient

Creating an inventory file

For this tutorial, the SR OS devices that we wish to target will be listed in an inventory file.  Call this file inventory and enter the details of your device hostnames or IP addresses inside.  The following is an example of an inventory file:


172.16.123.1
172.16.123.2
172.16.123.3
172.16.123.4
172.16.123.5
router6


Creating the program


It's time to create the main procedures.  Create the sros-python-101.py file containing the following:


#!./venv/bin/python3

## Import the external libraries required
import argparse
from ncclient import manager
from ncclient.xml_ import *

## create_connection
# In: Hostname and Commandline arguments
# Out: NCClient Connection
def create_connection(host, args):
  conn = manager.connect(host=host,
                           port=args.port,
                           username=args.username,
                           password=args.password,
                           hostkey_verify=False,
                           device_params={'name':'alu'})
  return conn

## read_file
# In: filename
# Out: List containing all non-blank lines from filename
def read_file(filename):
  f = open(filename, 'r')
  output = f.read().splitlines()
  output = [ line for line in output if line ]
  f.close()
  return output

## write_file
# In: filename and contents to be written to the file
# Out: Nothing (returns 0 on completion)
def write_file(filename, contents):
  f = open(filename, 'w+')
  f.write(contents)
  f.close()
  return 0

## get_arguments
# In: Nothing
# Out: The command line arguments
def get_arguments():
  parser = argparse.ArgumentParser()
  parser.add_argument("-i", "--inventory", help="Inventory Filename", required=True)
  parser.add_argument("-u", "--username", help="NETCONF SSH Username", required=False, default='admin')
  parser.add_argument("-w", "--password", help="NETCONF SSH Password", required=False, default='admin')
  parser.add_argument("-p", "--port", help="NETCONF TCP Port", required=False, default=830)
  args = parser.parse_args()
  return args

### The main procedure.  This is a springboard for the individual functions that
### are to be performed
def main():
  ## Get the commandline arguments
  args = get_arguments() 
  try:
    ## Read in the inventory filename provided on the command line and receive a list
    ## of hosts within it
    inventory = read_file(args.inventory)
  except Exception as error:
    print(error)
  ## For every host in the inventory file perform these actions
  for host in inventory:
    try:
      ## Create a NETCONF connection to the host
      conn = create_connection(host, args)
      ## Issue the get-config RPC over our NETCONF connection and receive the running config
      config = conn.get_config(source='running')
      ## Close the NETCONF connection with the host
      conn.close_session()
      try:
        ## Write the obtained running configuration (from the data/configure xpath) to a file
        write_file(host, to_xml(config.xpath('data/configure')[0]))
      except Exception as error:
        print(error)
      ## Provide an on-screen prompt that the program has processed this host
      print('Processed',host)
    except Exception as error:
      print(host,'Error',error)

### Start here.  If called directly from the command line then run the main procedure
if __name__ == "__main__":
  main()


This is your first Python program to connect to an SR OS model-driven router.  It connects to each router in the inventory file in turn using NETCONF, by providing the username and password supplied.  It obtains the running configuration of the router and saves this into a file with the filename matching that in the inventory.  


Comments are provided within the code as a guide but here is a short explanation of the key elements. 


The program starts with the main procedure.


The first thing the program does is obtain command line arguments using the get_arguments procedure.  The program requires four inputs:


  • Inventory - The filename containing the inventory of SR OS devices (IP address/hostname) that will be targeted
  • Username - The SR OS NETCONF username (this will default to admin)
  • Password - The SR OS NETCONF user password (this will default to admin)
  • Port - The SR OS NETCONF TCP port number (this will default to 830)


Next, the program reads the inventory file that was created earlier.  The try and except statements allow the program to gracefully handle any error conditions.  This returns a list of hosts.


For every host in the list, the program tries to open a NETCONF connection using the create_connection procedure.  It passes to this the command line arguments and the hostname/IP from the inventory file and receives in return a NETCONF connection handler.


Using this connection handler the program executes the <get-config> RPC over NETCONF using the conn.get_config(source='running') command to receive the running configuration.  This is then loaded into the config variable.


The NETCONF connection to the device is then closed. These are independent functions, meaning that multiple RPCs could be issued over the NETCONF connection before it is closed if this is what is desired.


Finally, the configuration is written to a file with the same name as the hostname/IP address provided in the inventory file.  This file is written in XML format.


Executing the program

You can now execute your program directly from the command line; however, to do this we need to change the file permissions to ensure that it is executable.


chmod 0755 sros-python-101.py


If your program is executed with the -h flag, a help screen will be displayed to assist you with the command line arguments.


./sros-python-101.py -h
usage: sros-python-101.py [-h] -i INVENTORY [-u USERNAME] [-w PASSWORD]
                          [-p PORT]

optional arguments:
  -h, --help            show this help message and exit
  -i INVENTORY, --inventory INVENTORY
                        Inventory Filename
  -u USERNAME, --username USERNAME
                        NETCONF SSH Username
  -w PASSWORD, --password PASSWORD
                        NETCONF SSH Password
  -p PORT, --port PORT  NETCONF TCP Port


Now the program can be executed with the command line arguments provided for your environment.  In this case, the NETCONF username is netconf and the NETCONF user password is nokia123


./sros-python-101.py -i inventory -u netconf -w nokia123
Processed 172.16.123.1
Processed 172.16.123.2
Processed 172.16.123.3
Processed 172.16.123.4
172.16.123.5 Error Could not open socket to 172.16.123.5:830
router6 Error [Errno -2] Name or service not known


Any errors are handled gracefully and the error message is returned to the screen.  In this example the IP address 172.16.123.5 is unreachable and the hostname router6 does not resolve in DNS/local hosts file.


Conclusion

We have covered how to install Python 3 and create a virtual Python environment.  We have also covered installing additional Python libraries into this virtual environment.


We created our first Python program in order to obtain the running configuration from a number of devices.