6. Python

6.1. Python Overview

Python is an established programming language that is widely used in systems administration. It has become one of the most prominent languages for network automation.

Python is popular because of its extensive libraries that software developers can import and enhance, and because it offers programming simplicity without diluting the flexibility and scalability offered by other languages.

Note:

This chapter assumes prior knowledge and experience with the Python programming language.

6.2. Python in SR OS

SR OS uses version 2 and version 3 of the Python language.

Python 2 is available only for ESM and Syslog applications. For more information, see Customizing Syslog Messages Using Python 2 and the 7450 ESS, 7750 SR, and VSR Triple Play Service Delivery Architecture Guide, “Python script support for ESM“.

Python 3 is available only for Python applications run in the MD-CLI using the pyexec or alias commands, and for applications executed remotely.

The remainder of this section references the SR OS Python 3 functionality only.

6.2.1. Prerequisites

The SR OS node must be in model-driven management interface configuration mode to run Python 3 applications.

To execute Python 3 applications on a remote device that connects to an SR OS device, the following prerequisites must be met.

  1. On the SR OS node, the NETCONF protocol must be enabled.
  2. The user must have the required permissions to use the NETCONF protocol.
  3. On the remote device (that is, the device that will execute the application), a Python 3 interpreter of version 3.6 or newer is required.

6.2.2. YANG Model Support

The Python 3 and pySROS features support Nokia YANG modules (combined and split) and OpenConfig YANG modules. If the YANG modules are to be obtained from the SR OS device, the YANG module files must be available at the specified schema path. See NETCONF Monitoring for more information.

6.3. Python 3 Interpreter

The Python interpreter is software that compiles and runs applications that developers create. It also handles importing additional libraries and all syntax for the language itself.

SR OS provides the MicroPython interpreter on the SR OS node. This interpreter implements Python 3.4 and is designed to operate using a small memory footprint, which allows SR OS to launch multiple interpreters in parallel.

The Python 3 interpreter is called by the SR OS function that requires it; for example, the MD-CLI. The interpreter is not called directly by the operator.

6.4. Building an Application

Customized applications can be written to run on an SR OS node or remotely.

Developers can create applications using any development environment, including a Python 3-based Integrated Development Environment (IDE) or a text editor.

Python 3 applications written for SR OS are designed to be portable between systems (SR OS and operator devices), provided the libraries and language features used are available on both systems.

6.4.1. Available Libraries

The following table describes the available preinstalled Python libraries that SR OS provides.

Note:

Libraries prefixed by the letter “u” are MicroPython-specific libraries. Importing to a script using the base name is typically possible; for example, import json imports ujson when running on an SR OS device.

Table 30:  Available Libraries 

Library

Description

binutils

Collection of binary utilities

datetime

Manipulation of various formats for date, time, and time zone. The strptime function is not supported.

ubinascii

Bidirectional translation between binary data and various ASCII encodings

ujson

Conversion between Python objects and JSON data format

pysros

Model-driven management API for SR OS (Python for the Service Router Operating System – pySROS)

ucollections

Advanced collection and container types to hold or accumulate various objects

ure

Simple regular expressions

sys

System-specific parameters and functions

uhashlib

Binary data hashing algorithms

ustruct

Pack and unpack primitive data types

ipaddress

IPv4 and IPv6 address manipulation

uio

Input and output streams

utime

Obtain current date and time, measuring intervals, and delays. This function has been updated to provide support for SR OS and is documented in the API documentation.

6.4.2. The pySROS API

Python for the Service Router Operating System (pySROS) libraries provide the programmatic interface to the SR OS model-driven management framework.

The libraries provide a set of methods for developers to obtain, manipulate, and deliver data to and from an SR OS node.

Note:

Nokia recommends reviewing the API documentation provided with the pySROS libraries prior to developing any Python applications.

6.4.2.1. Installing the pySROS Libraries

The pySROS libraries are delivered and preinstalled on SR OS nodes. This libraries can be installed on another device, such as a PC or Unix workstation.

Note:

A Python 3 interpreter must be already installed on the device.

Use one of the following methods to install the pySROS libraries:

  1. from the Python Package Index (PyPI) using the pip tool (preferred method)
    To do this, execute the pip install pysros command on the device.
  2. from source code delivered from github.com
    To do this, clone the source code repository to your device by executing the git clone https://github.com/nokia/pysros command.
    The source code can then be compiled and installed by executing python3 setup.py install.
  3. from source code delivered from the Nokia online support portal
    To do this, obtain the source code from the Nokia online support portal. This is the same location where the SR OS software resides.
    The source code can then be compiled and installed by executing python3 setup.py install.

6.4.2.2. Importing into Applications

The pySROS libraries must be imported to use the provided API in developed applications.

The libraries may be imported using the import pysros command, or only specific elements of the API may be imported; for example, from pysros.management import connect.

6.4.2.3. API Documentation

This chapter provides a high-level overview about how to connect to the model-driven interfaces of an SR OS device and manipulate simple data structures. Detailed technical documentation for the pySROS API is provided within the source code bundle in the docs directory.

The API documentation is provided as source code and should be built as needed. To compile the API documentation, run the following commands from the docs directory:

  1. pip install -r requirements.txt
  2. make html

The API documentation is compiled into the build/html folder in HTML format.

Note:

Nokia recommends reviewing the API documentation provided with the pySROS libraries prior to developing any Python applications.

6.4.2.4. Connecting to a Model-driven SR OS Device

To enable access to an SR OS device, the user must create a Connection object, which is a Python object that references the application’s connection to a specific SR OS node.

The underlying connection transport protocol is NETCONF.

The connect() method is provided to create this Connection object.

The following example shows the creation of a connection named connection_object to a device with the IP address 192.168.168.1.

from pysros.management import connect
connection_object = connect(host='192.168.168.1', username='admin', password='admin')

The following table describes the arguments available for the connect() method.

Note:

All arguments are ignored when the Python application is executed on an SR OS device.

Table 31:  Connect() Method Arguments 

Argument

Type

Mandatory

Description

host

string

Yes

IP address, hostname, or FQDN of the SR OS device to connect to

username

string

Yes

Username to connect to the SR OS device

password

string

Yes

Password to connect to the SR OS device

If no password is provided, SSH key-based authentication is attempted.

port

integer

No

TCP port on the SR OS node that the connect attempt will be made to

Default: 830

yang_directory

string

No

Directory to read YANG module files from

Default: None

rebuild

Boolean

No

Forces the schema cache to be rebuilt upon connect

Default: False

timeout

integer

No

Maximum time for connection, obtaining YANG modules, and schema generation

Default: 300 seconds

When a Python application makes a connection to an SR OS device using the connect() method, the application performs the following actions.

  1. The device is queried to identify a set of modules required to manage the device. This is performed by identifying the module-set-id (yang-library:1.0) or content-id (yang-libraray:1.1) from the devices advertised capabilities.
  2. The set of modules are queried using /modules-state from the IETF YANG library RFC 8525.
  3. The local schema cache is checked to determine whether a model-driven management schema is already generated for the same set of YANG modules. If no identical local schema cache exists, or if the rebuild argument is set to True, the following occurs.
    1. If the yang_directory argument is not provided to the connect() method, each YANG module listed by the SR OS node is downloaded directly from the node.
    2. If the yang_directory argument is provided to the connect() method, the YANG module files from this directory that correspond to the list of required modules obtained from the router are used.
  4. The YANG modules are compiled into a schema cache for use by the developer and the pySROS libraries.
Note:

The connect method is slower to complete for the first compilation of a specific set of YANG modules. Subsequent connections for that set of YANG modules are significantly faster. A locally cached set of YANG modules is not specific to an individual router.

The local model-driven schema cache is stored in the .pysros directory within the developer’s local home directory. If this directory is deleted or modified, the cache is rebuilt on the next connect() API call.

6.4.2.5. Obtaining Modeled Data

Use the get() method to obtain modeled data from an SR OS device.

The get() method accepts as inputs a JSON instance identifier path and a datastore. The method returns a Python data structure, which uses the pySROS format to provide modeled data to the developer. See The pySROS Data Structure for more information.

A JSON instance path is obtained from an SR OS node using the pwc json-instance-path command. See the 7450 ESS, 7750 SR, 7950 XRS, and VSR MD-CLI User Guide for more information.

The following example obtains data from an SR OS node Connection object.

my_data = connection_object.running.get('/nokia-state:state/system/oper-name')
Note:

State information is obtained from the running the datastore when using the pySROS libraries.

6.4.2.6. Executing MD-CLI Commands

Nokia recommends using the pySROS API when interacting with SR OS using model-driven interfaces. However, some cases may require an unmodeled MD-CLI command, which the developer can get by manipulating the resulting string output.

The cli() API method allows developers to pass a single line string containing a single MD-CLI command (including output modifiers, if required) to an existing SR OS Connection object. This command is executed immediately and the output is returned as a string. See NETCONF Operations Using the md-cli-raw-command Request for more information about supported commands.

The following example executes an MD-CLI command from the pySROS API.

output_string = connection_object.cli('show system time')
print(output_string)
===============================================================================
Date & Time
===============================================================================
Current Date & Time : 2021/09/15 20:27:27    DST Active            : no
Current Zone        : UTC                    Offset from UTC       : 00:00
-------------------------------------------------------------------------------
Non-DST Zone        : UTC                    Offset from UTC       : 00:00
Zone type           : standard
-------------------------------------------------------------------------------
No DST zone configured.
-------------------------------------------------------------------------------
Prefer Local Time   : NO
===============================================================================

6.4.2.7. Editing Configuration

Python data structures, in pySROS format, and specific values within the data structures can be configured on an SR OS device.

The set() method is provided to configure a node. The set() method aggregates several model-driven transactional operations into a single method:

  1. configuration of the node (performed in private candidate configuration mode)
  2. update, validate, and commit

The set() method accepts as input a JSON instance path, a datastore, and a payload. The payload may be a single value, a key and value pair, a crafted Python data structure following the pySROS data-structure format, or a pySROS data structure object received from a get() method call.

The following examples show how to set the system name to “hostname”.

connection_object.candidate.set("/nokia-conf:configure/system/name", "hostname")
connection_object.candidate.set("/nokia-conf:configure/system", {‘name’:‘hostname’})
connection_object.candidate.set("/nokia-conf:configure", {‘system’: {‘name’: ‘hostname’}})

6.4.3. The pySROS Data Structure

The key to efficient Python programs for network management is the ability to manipulate data in a consumable format.

The pySROS libraries ensure that the YANG modeled data from SR OS is supplied in native Python data structures that are simple to understand and handle in code.

When data is obtained from an SR OS node, it is returned in a specific data structure format, a pySROS data structure.

Table 32 shows the pySROS conversion from model-driven YANG-based data structures to native Python data structures.

Table 32:  Model-driven to Python Data Structure Conversion Rules  

Yang Structure

Python 3 Structure

Container

Dict

Leaf

Value (Type derived as shown in YANG Types)

Leaf-list

List

List

Dict

User-ordered List

OrderedDict keyed on the YANG list’s key value

The pySROS libraries provides Python class wrappers around each node type to assist with data manipulation. This information can be used with some of the features built into the pySROS API, such as pretty-printing.

Containers are wrapped in a Container() class.

Leafs are wrapped in a Leaf() class. The following example shows how to obtain the value of the leaf that is wrapped in a Leaf() class by calling the .data function on the leaf.

from pysros.wrappers import Leaf
obj = Leaf('example')
print(obj.data)

Leaf-lists are wrapped in a LeafList() class.

All pySROS class wrappers for YANG nodes are provided by pysros.wrappers.

YANG schema metadata can be obtained on a specific data object by calling the schema function. The YANG metadata that is available within the pySROS data structure (data is the specific pySROS formatted data object) is the data.schema.module. This is the YANG module name the element comes from. If this element in the YANG schema is imported or included from another YANG modules, the root YANG module is displayed. If the YANG modules where the element is found is an augment to another module, the augment module is shown.

YANG types are also converted into native Python types. Table 33 describes the rules for this conversion.

Table 33:  YANG Types  

Base YANG Type

Python 3 Type

binary

String

bits

String

boolean

Boolean

decimal64

String

empty

(see note  1)

enumeration

String

identityref

String

int8

Integer

int16

Integer

int32

Integer

int64

Integer

leafref

(not applicable  2)

string

String

uint8

Integer

uint16

Integer

uint32

Integer

uint64

Integer

union

String  3

    Notes:

  1. The specific type is provided by the pySROS libraries.
  2. A leafref takes the YANG native type of the leaf it is referencing. This type is converted to Python according to the table.
  3. A union YANG type may be a union of different YANG types, for example, a union of a string and a Boolean. As it is not possible to identify the intention at the time of obtaining the data, automatic type selection is not performed. Every union is treated as a string, allowing the developer to cast the element into a specified type.

6.5. Provisioning and Precompiling Python Applications

Python applications can be configured and executed in the MD-CLI. This allows administrators to provide specific Python applications to users.

Python applications can be referenced in configuration statements, such as MD-CLI aliases.

Python applications are configured in the configure python context. The following is a sample Python application configuration.

(ex)[/configure python]
A:admin@sros# info
    python-script "my_example" {
        admin-state enable
        urls ["cf3:\example.py" "ftp://user:password@192.168.168.254/example.py"]
        version python3
    }

After a Python application is configured and committed, the SR OS node attempts to load the files specified in the urls field in the order they are listed. If the first URL location can be reached and a file containing valid Python code is found, the system stores this source code ready for use.

If the first URL cannot be reached or the file does not contain valid source code, the system moves to the next URL in the list. If no URL locations contain valid Python source code, the oper-state leaf for the configured application is set to down in the state python python-script application_name context.

6.5.1. Refreshing Configured Python Scripts

When defined in the SR OS configuration, Python scripts are stored in memory on the SR OS node. The URLs defined in the configuration are not rechecked, unless it is specifically requested by an operator.

If a new version of the script is placed in the URL reference location, whether locally on the SR OS nodes storage card or remotely, the tools perform python-script reload application_name command must be run to use the new version.

6.6. Execution Pathways

This section describes the methods that are provided to execute Python applications.

6.6.1. Running a Python Application Remotely

The pySROS libraries provide the ability to interface with one or more SR OS devices from a device that has a Python interpreter installed. This execution pathway is not specific to SR OS (beyond the use of the pySROS libraries) and is not described further in this guide.

6.6.2. Running a Python Application from the Command Line

The MD-CLI provides the ability to execute a Python application directly from the command line.

The pyexec command takes as a parameter either the name of a Python application from the SR OS configuration (configure python python-script application_name) or the URL to the location (local/remote) of a Python application.

For example, if the pyexec application_name command is executed, the SR OS performs the following steps.

  1. The SR OS device searches for a configuration element configure python python-script application_name. If a configuration element is found, the system attempts to compile and execute this script. A failure ends the execution.
  2. The SR OS device treats the application_name as a URL. As application_name does not have a URL identifier (such as cf3:\ or ftp://) attached to it, SR OS prepends the present working directory of the system (which is cf3:\ by default on most systems).
  3. SR OS attempts to read from the derived URL; for example, cf3:\application_name. If this URL is successfully located, SR OS compiles and runs the application. A failure ends the execution.
    Each time pyexec is invoked, a new Python interpreter is spawned.

6.6.2.1. pyexec and Input Parameters

The pyexec command can accept a maximum of ten input arguments provided using the MD-CLI command line. The the Python application developer must handle these as standard input (STDIN) arguments.

6.6.2.2. Running a Python Application as an Output Modifier

Python applications can be entered as an output modifier to MD-CLI commands.

The following is a sample output from an info command that is processed by a Python application, which capitalizes the output.

(ex)[/]
A:admin@node-2# file show cf3:\capitals.py
File: capitals.py
-------------------------------------------------------------------------------
import sys
def main():
  for line in sys.stdin:
    print(line.upper(), end="")
main()
===============================================================================
(ex)[/]
A:admin@node-2# show version | pyexec capitals.py
TIMOS-B-21.7.B1-9 BOTH/X86_64 NOKIA 7750 SR COPYRIGHT (C) 2000-2021 NOKIA.
ALL RIGHTS RESERVED. ALL USE SUBJECT TO APPLICABLE LICENSE AGREEMENTS.
BUILT ON THU JUN 12 18:35:55 PDT 2021 BY BUILDER IN /BUILDS/C/217B/B1-9/PANOS/MAIN/SROS

6.6.2.3. Chaining Python Applications

The pyexec command supports chaining multiple applications on the command line. Python applications called with the pyexec command can produce data on the standard output (STDOUT) stream and consume data on the standard input (STDIN) stream. Multiple Python applications can then be chained together.

Note:

A maximum of three pyexec commands may be chained together.

6.6.2.4. Python Applications and the MD-CLI Pager

Python applications executed using the pyexec command use the built-in MD-CLI pager to display the output one page at a time. This behavior can be disabled per Python application using the no-more output modifier, or globally by setting the MD-CLI environment more parameter to false, as required.

When the MD-CLI display output is paused by the pager while executing a Python application, pressing q closes the pager and resumes executing the Python application. Pressing Ctrl-c closes the pager and terminates the Python application.

6.6.3. Running Python Applications Using Aliased MD-CLI

Python applications can be executed from a configured alias in MD-CLI. See 7450 ESS, 7750 SR, 7950 XRS, and VSR MD-CLI User Guide, “Command Aliases” for more information about how to configure an alias in the MD-CLI.

Aliases may call a configured (named) Python application or the pyexec command.

There are specific AAA considerations for each method. See Authentication, Authorization, and Accounting for more information.

Each time an alias that references a Python application is executed, a new Python interpreter is spawned.

6.7. Security

SR OS ensures that the routing, forwarding, and management functions of a device are protected and prioritized.

6.7.1. Python Authentication and Authorization

Python applications are dependent on authentication, authorization, and accounting in the same way as any other feature of SR OS. See Authentication, Authorization, and Accounting for more information.

6.7.1.1. Authentication

To make a connection to the model-driven interface of an SR OS device, user authentication is required.

User authentication is deemed to have already occurred if the Python application is executed directly on the SR OS node.

If the Python application is executed remotely, user credentials must be provided to the connect() API call.

6.7.1.2. Authorization

To successfully use a Python application, the authenticated user must have authorization to both execute the application and perform each of the model-driven operations contained within the Python application.

6.7.2. Other Restrictions

To protect the integrity of an SR OS system, a number of facilities are disabled in Python while executing an application on SR OS. These include, but are not limited to the following:

  1. importing additional libraries outside of the supported list
  2. creating, reading, writing, or otherwise manipulating network sockets
  3. garbage collection
  4. debugging libraries

6.7.3. Memory Management

SR OS does not allow a Python application to start if there is insufficient memory available at the point of execution, or if too many Python applications are running concurrently.

When a Python 3 application is spawned, SR OS confirms that the minimum percentage of sufficient free system memory is available. The percentage value for minimum available system memory is configurable within the MD-CLI environment settings.

The Python 3 application then reserves the specified memory for the application. The amount of memory reserved is configurable within the MD-CLI environment settings.

6.7.4. Performance and Scale

The ability to execute Python applications conveys no expectation of a specific performance or scale level.

Note:

Nokia recommends using smaller data sets, where possible, when executing a Python application on an SR OS device. For larger data sets, Nokia recommends executing Python applications remotely.