Overview¶
Introduction¶
The pySROS libraries provide a model-driven management interface for Python developers to integrate with supported Nokia routers running the Service Router Operating System (SR OS).
The libraries provide an Application Programming Interface (API) for developers to create applications that can interact with Nokia SR OS devices, whether those applications are executed from a development machine, a remote server, or directly on the router.
When a developer uses only libraries and constructs supported on SR OS, a single application may be executed from a development machine or ported directly to an SR OS node where the application is executed without modification.
Pre-requisites¶
To use the pySROS libraries, the following pre-requisites must be met:
one or more SR OS nodes
Running in model-driven management interface configuration mode
Running SR OS 21.7.R1 or greater (to execute applications on the SR OS device)
With NETCONF enabled and accessible by an authorized user (to execute applications remotely)
a Python 3 interpreter of version 3.10 or newer when using the pySROS libraries to execute applications remotely
All the required software is included and installed automatically on the SR OS node, including the Python 3 interpreter and all supported Python libraries.
YANG modeling¶
It is assumed that the developer has a working knowledge of model-driven management in a networking environment and of YANG models and their constituent parts.
The Nokia YANG models are available for each release of SR OS on GitHub.
Modeled paths¶
At the root of the pySROS libraries is Nokia’s model-driven management concepts built into SR OS.
Communication between applications developed using the pySROS libraries and Nokia SR OS routers is achieved using model-driven paths referencing elements within the Service Router Operating System.
The pySROS libraries accept modeled paths in the JSON instance path format, a path format based on RFC 6020 and RFC 7951. This path format describes the YANG models to which it is referencing, including all YANG lists, YANG list keys, and their key values (although in some instances, these may be omitted).
The JSON instance path can be obtained directly from an SR OS router running
software from release 21.7.R1 by entering pwc json-instance-path
in the MD-CLI in the context to be referenced.
See the following for examples:
SR OS pwc json-instance-path output from services configuration
SR OS pwc json-instance-path output from OpenConfig interfaces
A:myusername@sros# pwc json-instance-path
Present Working Context:
/nokia-conf:configure/service/vprn[service-name="vpn1"]/static-routes/route[ip-prefix="1.1.1.1/32"][route-type="unicast"]/blackhole
[/state router "Base" bgp neighbor "1.1.1.1"]
A:myusername@sros# pwc json-instance-path
Present Working Context:
/nokia-state:state/router[router-name="Base"]/bgp/neighbor[ip-address="1.1.1.1"]
A:myusername@sros# pwc json-instance-path
Present Working Context:
/openconfig-interfaces:interfaces/interface[name="1/1/c2/1"]/subinterfaces/subinterface[index=0]/openconfig-if-ip:ipv4/addresses
Schema aware¶
The pySROS libraries are YANG schema aware. Each element has knowledge of its path, model, and data type in the YANG model.
The YANG schema is automatically obtained by the pySROS libraries by performing one
of the following upon connection (using pysros.management.connect()
).
Download the YANG models from the targeted nodes using YANG library as described in RFC 8525 and get-schema as defined in RFC 6022 (default). For this to work the YANG models must be available from the SR OS device and the schema-path set correctly (for more information, see the SR OS System Management Guide).
Compile a YANG model or set of YANG models located on a file system and referenced by the developer.
Note
When executing a Python application using the pySROS libraries on a remote workstation, the initial connection to a node is slower than subsequent connections as the schema is generated from the YANG models and cached.
pySROS schema cache¶
The pySROS libraries use a model-driven schema which is generated from YANG models. This schema is stored on your local machine 1. The location is dependent on your operating system:
Operating System |
pySROS schema cache location |
---|---|
UNIX |
|
macOS |
|
Windows 10 |
|
- 1
Not applicable when executing a Python application using the pySROS libraries on SR OS
Network communication¶
When executing applications remotely, the pySROS libraries use NETCONF for communication between the remote node and the SR OS node. To facilitate this, the SR OS node must be configured to allow NETCONF access from the location that the application is run.
For more information about configuring SR OS to use NETCONF, see the SR OS System Management Guide.
Installation¶
Multiple installation methods are available:
Note
Nokia recommends using Python virtual environments where appropriate.
PyPI¶
The preferred method of installation of the pySROS libraries is to install
directly from the Python Package Index (PyPI) using the pip
tool.
The pySROS project is located on PyPI.org
The libraries can be downloaded and installed by using the following:
pip install pysros
To upgrade to the latest version of the pySROS libraries, use the following:
pip install --upgrade pysros
Nokia support portal¶
The pySROS libraries are available for download from the portal for registered customers.
The obtained file can be unzipped and subsequently installed using:
python3 setup.py install
GitHub¶
The pySROS libraries are available for download from GitHub.
The obtained file can be installed using the git
tool:
git clone https://github.com/nokia/pysros
python3 setup.py install
The pySROS data model¶
The pySROS libraries provide YANG model-aware Python 3 data structures to the developer that can be manipulated and traversed with Python in the same way as any other Python structure.
YANG-modeled data structures are converted into Python 3 data structures as follows:
Data structure conversions¶
YANG structure |
Python 3 structure |
---|---|
List |
Dict keyed on the YANG list’s key value |
User-ordered List |
OrderedDict keyed on the YANG list’s key value |
Leaf-List |
List |
Leaf |
Value (Type derived as shown in Type conversions) |
Container |
Dict |
Type conversions¶
Base YANG type |
Python 3 type |
---|---|
binary |
string |
bits |
string |
boolean |
boolean |
decimal64 |
string |
empty |
|
enumeration |
string |
identityref |
string 3 |
int8 |
integer |
int16 |
integer |
int32 |
integer |
int64 |
integer |
leafref |
N/A 4 |
string |
string |
uint8 |
integer |
uint16 |
integer |
uint32 |
integer |
uint64 |
integer |
union |
string 5 |
- 2
This specific type is provided by the pySROS libraries. YANG has a specific data type named
empty
. This type is not commonly used in YANG modules but it is important to explain the specific handlingpysros
provides. For more information, seepysros.management.Empty
- 3
Identity references (identityref) require special consideration. See the YANG identity references section.
- 4
A leaf-ref takes the YANG native type of the leaf it is referencing. This type is then converted to Python according to this table.
- 5
A union YANG type may be a union of a variety 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.
YANG identity references¶
Identity references are a YANG construct that provide a way to reference a previously
defined identity
. This identity
may be located in the same, or more commonly, another YANG
module.
Unlike other elements in YANG, the namespace for an identityref is stored as part of the value of a node, rather than the node itself:
<interfaces xmlns="http://openconfig.net/yang/interfaces">
<interface>
<name>1/1/c1/1</name>
<config>
<name>1/1/c1/1</name>
<type xmlns:iana-if-type="urn:ietf:params:xml:ns:yang:iana-if-type">
iana-if-type:ethernetCsmacd
</type>
</config>
</interface>
</interfaces>
In pySROS the namespace portion of an identityref
value must be the YANG module name
of the module where the referenced identity
resides:
>>> path = '/openconfig-interfaces:interfaces/interface[name="1/1/c1/1"]/config'
>>> payload = {'name': '1/1/c1/1', 'type': 'iana-if-type:ethernetCsmacd'}
>>> connection_object.candidate.set(path, payload)
>>> connection_object.running.get(path+'/type')
Leaf('iana-if-type:ethernetCsmacd')
If a YANG module name is omitted when referencing an identity
, pySROS attempts
to determine the module name from the known YANG schema for that device. If pySROS
cannot determine the correct module name an pysros.exceptions.SrosMgmtError
Exception is returned.
Note
Nokia recommends explicitly describing the YANG module name in an identityref
.
Wrappers¶
To assist with data manipulation, data structures obtained from SR OS are wrapped with class identifiers depending on their YANG element structure. This additional information can assist developers when writing Python code to analyze, manipulate, and output modeled data.
YANG containers are wrapped in the pysros.wrappers.Container
class.
YANG leaf-lists are wrapped in the pysros.wrappers.LeafList
class.
YANG leafs are wrapped in the pysros.wrappers.Leaf
class. Use the data
variable to
obtain the value of the leaf without the wrapper, as in the following example: Obtaining the value of an object wrapped in the pysros.wrappers.Leaf class.
Example:
>>> from pysros.wrappers import Leaf
>>> obj = Leaf('example')
>>> print(obj.data)
example
YANG schema information¶
Additional information from the model-driven YANG schema is available to developers for
each element in a data structure obtained from SR OS using the pySROS libraries. This
metadata can be queried on demand by calling the pysros.wrappers.Schema
class
against the element.
YANG schema information currently available includes:
Schema variable |
Description |
---|---|
module |
The YANG module name 6 |
namespace |
The YANG modules namespace. This may be in URI or URL format 6 |
yang_type |
The YANG type. If this is a typedef in YANG, it resolves to the
base type in YANG. If the |
units |
The unit the YANG node is reporting in the YANG module. |
default |
The default value defined in the YANG module. |
mandatory |
Returns True if the node is required in the YANG module. |
range |
The range defined in the YANG module. |
- 6(1,2)
The YANG module name is the root module for the element. The pySROS libraries take into consideration YANG imports, includes, deviations, and augmentations to provide this result.
- 7
If a union resolves to multiple, identical base YANG types, only one of that type is returned.
Example:
>>> name
Leaf('sros')
>>> name.schema.module
'nokia-conf'
>>> name.schema.namespace
'urn:nokia.com:sros:ns:yang:sr:conf'
>>> name.schema.mandatory
False
>>> name.schema.yang_type
string
Annotations and metadata¶
Annotations and metadata are terms often used interchangeably for additional supporting information applied to a node in a YANG tree without being included as part of the actual value of that node and without the need to create a new node to contain the information.
Annotations are defined in YANG and fall into two broad categories:
User defined annotations
Supporting information provided and consumed by the user of pySROS attached to a YANG node. An example is a configuration comment applied to a node in an SR OS configuration using the MD-CLI
annotate
command.System or protocol defined annotations
Defined in a specification for a specific purpose only. These may be added, removed, or edited by a user but they have very specific meanings and perform very specific functions in a protocol. An example is the
operation
attribute of an XML document used with NETCONF when manipulating user-ordered lists.
Annotations (metadata) are defined in RFC 7952 and are supported in XML and JSON (IETF) encodings.
Annotations in pySROS are similar to the pysros.wrappers.Schema
class but, unlike the
pysros.wrappers.Schema
class, the pysros.wrappers.Annotations
is writable.
See the pysros.wrappers.Annotations
class for more details.
Getting Started¶
Making a connection¶
To connect to a device running SR OS, a pysros.management.Connection
object must be
created. The pysros.management.connect()
method creates this object.
The pySROS libraries are designed to provide a level of portability for applications, allowing developers to create applications within a preferred development environment and to execute them locally or transfer them to SR OS for execution.
The pysros.management.connect()
method provides arguments
that allow the developer to specify parameters, such as the authentication credentials
and TCP port. These attributes are ignored when an application is executed from an
SR OS node.
Example:
from pysros.management import connect
from pysros.exceptions import *
import sys
def get_connection():
try:
connection_object = connect(host="192.168.1.1",
username="myusername",
password="mypassword")
except RuntimeError as error1:
print("Failed to connect. Error:", error1)
sys.exit(-1)
except ModelProcessingError as error2:
print("Failed to create model-driven schema. Error:", error2)
sys.exit(-2)
return connection_object
if __name__ == "__main__":
connection_object = get_connection()
Obtaining data¶
Use the pysros.management.Datastore.get()
method to obtain model-driven data from an SR OS device.
This method takes a single JSON instance path (see the Modeled paths section) and returns a data structure.
The pysros.management.Datastore.get()
method can be performed against the running
, intended
or candidate
datastores
when configuration data is required. When state data is required, it can only be performed against the
running
datastore.
Note
When using combined configuration and state schemas, such as OpenConfig, the pysros.management.Datastore.get()
method obtains both configuration and state information, unless the config_only=True
flag is provided.
Example:
>>> from pysros.management import connect
>>> connection_object = connect()
>>> connection_object.running.get('/nokia-conf:configure/router[router-name="Base"]/bgp')
Container({'group': {'mesh': Container({'group-name': Leaf('mesh'), 'admin-state': Leaf('enable'),
'peer-as': Leaf(65535)})}, 'neighbor': {'192.168.100.2': Container({'group': Leaf('mesh'),
'import': Container({'policy': LeafList(['demo', 'example-policy-statement'])}),
'ip-address': Leaf('192.168.100.2'), 'family': Container({'ipv6': Leaf(True),
'vpn-ipv4': Leaf(True), 'ipv4': Leaf(True), 'vpn-ipv6': Leaf(True)}),
'add-paths': Container({'ipv4': Container({'receive': Leaf(True), 'send': Leaf('multipaths')})}),
'admin-state': Leaf('enable')})}, 'admin-state': Leaf('enable')})
Configuring SR OS routers¶
Configuration of SR OS devices is achieved using an atomic pysros.management.Datastore.set()
method. This method takes
two inputs: the first is a JSON instance path (see the Modeled paths section) and the second is the payload in
the pySROS data structure format.
The pysros.management.Datastore.set()
method can be performed against the candidate
datastore only and state
data cannot be set.
For example, to enable the gRPC interface and gNMI on a device, the configuration elements for
these settings are located in the /nokia-conf:configure/system/grpc
path.
The configuration settings in the MD-CLI are:
/configure system grpc admin-state enable
/configure system grpc allow-unsecure-connection
/configure system grpc gnmi { }
/configure system grpc gnmi { admin-state enable }
The pySROS data structure format for this configuration is as shown:
Container({'allow-unsecure-connection': Leaf(Empty),
'admin-state': Leaf('enable'),
'gnmi': Container({'admin-state': Leaf('enable')})})
To configure the SR OS device, use the pysros.management.Datastore.set()
method as follows:
from pysros.management import connect, Empty
from pysros.wrappers import Leaf, Container
connection_object = connect()
path = '/nokia-conf:configure/system/grpc'
payload = Container({'allow-unsecure-connection': Leaf(Empty),
'admin-state': Leaf('enable'),
'gnmi': Container({'admin-state': Leaf('enable')})})
connection_object.candidate.set(path, payload)
The pysros.management.Datastore.set()
method creates a private candidate configuration on the SR OS device,
makes the required configuration changes, validates the changes, performs an update of the baseline configuration
datastore, and commits the changes before releasing the private candidate. The operation is atomic, that is,
all configuration changes must be made successfully or the configuration remains unchanged.
Objects obtained using pysros.management.Datastore.get()
may be returned directly to
pysros.management.Datastore.set()
if no state information is included.
from pysros.management import connect, Empty
from pysros.wrappers import Leaf, Container
connection_object = connect()
path = '/nokia-conf:configure/system/grpc'
payload = connection_object.running.get(path)
connection_object.candidate.set(path, payload)
The pysros.management.Datastore.set()
method also accepts payloads that do not include the pySROS wrapper information.
This enables the developer to simply structure their own data.
from pysros.management import connect, Empty
from pysros.wrappers import Leaf, Container
connection_object = connect()
path = '/nokia-conf:configure/system/grpc'
payload = {'allow-unsecure-connection': Empty, 'admin-state': 'enable', 'gnmi': {'admin-state': 'enable'}}
connection_object.candidate.set(path, payload)
Performing operations¶
An operation refers to the execution of an activity on the SR OS node that is not that of obtaining data or configuring the device. The method of performing operations on the SR OS node through the pySROS libraries is using YANG modeled actions.
This approach allows for YANG modeled and structured data to be used on both input and output. Both input and output are represented as pySROS data structures.
To execute a YANG modeled operation, the pysros.management.Connection.action()
method should be used.
The pysros.management.Connection.action()
method uses the YANG schema obtained as
part of the creation of the pysros.management.Connection
object. As an input, the
path to the YANG action
statement should be provided in json-instance-path format along
with the YANG input
parameters in pySROS data structure format.
For example, consider the following YANG module:
module example {
yang-version "1.1";
namespace "urn:nokia.com:example";
prefix "nokia-example";
revision "2022-09-09";
container mycontainer {
action do-something {
input {
leaf myinput-string {
type string;
mandatory true;
}
leaf myinput-int {
type uint8;
mandatory true;
}
}
output {
leaf working {
type boolean;
}
}
}
}
}
The json-instance-path to the YANG action statement in the above model is
/example:mycontainer/do-something
. The input to this YANG action takes two
mandatory fields; myinput-string
and myinput-int
.
If the do-something
action was called with the input variables myinput-string
and
myinput-int
being provided as mystring
and 2
respectively to method call would
look like this:
>>> from pysros.management import connect
>>> connection_object = connect()
>>> path = '/example:mycontainer/do-something'
>>> input_parameters = {'myintput-string': 'mystring', 'myinput-int': 2}
>>> output = connection_object.action(path, input_parameters)
>>> output
Container({'working': Leaf(True)})
>>> output['working'].data
True
As can be seen in the example above, the output provided is a pySROS data structure that can be accessed in the same way as other pySROS data structures native to Python.
Feedback, Support and Assistance¶
All feedback, issues, errors, improvements, and suggestions may be submitted via the Nokia support portal or through your Nokia representative.