pysros
- Model-driven SR OS interface
Library for management of model-driven nodes.
pysros.management
- Connection and data handling
This module contains basic primitives for managing an SR OS node. It contains functions to obtain and manipulate configuration and state data.
- pysros.management.connect(*, host, port=830, username, password=None, yang_directory=None, rebuild=False, transport='netconf', timeout=300, hostkey_verify=True)
Create a
Connection
object. This function is the main entry point for model-driven management of configuration and state for a specific SR OS node using the pySROS library.Note
All parameters to connect are ignored when executed on an SR OS node.
- Parameters:
host (str) – Hostname, Fully Qualified Domain Name (FQDN) or IP address of the SR OS node.
port (int, optional) – TCP port on the SR OS node to connect to. Default 830.
username (str) – User name.
password (str, optional) – User password. If the password is not provided the systems SSH key is used.
yang_directory (str, optional) – Path (absolute or relative to the local machine) to the YANG modules for the specific node. If this argument is used, YANG modules are not downloaded from the SR OS node.
rebuild (bool, optional) – Trigger the rebuild of an already cached YANG schema.
timeout (int, optional) – Timeout of the transport protocol, in seconds. Default 300.
hostkey_verify (bool, optional) – Enables hostkey verification using the SSH known_hosts file. Default True.
- Returns:
Connection object for specific SR OS node.
- Return type:
- Raises:
RuntimeError – Error occurred during creation of connection
ModelProcessingError – Error occurred during compilation of the YANG modules
Note
When executing a Python application using the pySROS libraries on a remote workstation, the initial connection is slower to complete than subsequent connections as the schema is generated from the YANG models and cached.
Warning
hostkey_verify
should be set toTrue
in a live network environment.Example 1 - Connection using YANG models automatically obtained from the SR OS nodefrom pysros.management import connect from pysros.exceptions import ModelProcessingError import sys def get_connection(): try: connection_object = connect(host="192.168.1.1", username="myusername", password="mypassword") except RuntimeError as runtime_error: print("Failed to connect. Error:", runtime_error) sys.exit(-1) except ModelProcessingError as model_proc_error: print("Failed to create model-driven schema. Error:", model_proc_error) sys.exit(-2) return connection_object if __name__ == "__main__": connection_object = get_connection()
Example 2 - Connection using YANG models obtained from a local directoryfrom pysros.management import connect from pysros.exceptions import ModelProcessingError import sys def get_connection(): try: connection_object = connect(host="192.168.1.1", username="myusername", password="mypassword", yang_directory="./YANG") except RuntimeError as runtime_error: print("Failed to connect. Error:", runtime_error) sys.exit(-1) except ModelProcessingError as model_proc_error: print("Failed to create model-driven schema. Error:", model_proc_error) sys.exit(-2) return connection_object if __name__ == "__main__": connection_object = get_connection()
- pysros.management.sros()
Determine whether the execution environment is an SR OS node
- Returns:
True if the application is executed on an SR OS node, False otherwise.
- Return type:
bool
Examplefrom pysros.management import sros def main(): if sros(): print("I'm running on a SR OS device") else: print("I'm not running on a SR OS device") if __name__ == "__main__": main()
- class pysros.management.Connection(*args, yang_directory, rebuild, **kwargs)
Bases:
object
An object representing a connection to an SR OS device. This object is transport agnostic and manages the connection whether the application is run on the SR OS node or remotely.
Warning
You should not create this class directly. Please use
connect()
instead.The underlying transport is NETCONF when executed on a machine that is not running SR OS.
- Variables:
running (.Datastore) – running datastore
intended (.Datastore) – intended datastore
candidate (.Datastore) – candidate datastore
- disconnect()
Disconnect the current transport session. After disconnect, the model-driven interfaces for the SR OS devices are not available.
Examplefrom pysros.management import connect connection_object = connect() connection_object.disconnect()
- cli(command)
Run a single MD-CLI command. A single line of input is allowed. This may include MD-CLI output redirection (such as
no-more
). Some restrictions apply to the commands that may be provided.- Parameters:
command (str) – MD-CLI command
- Returns:
Output as returned from the MD-CLI. The returned data is an unstructured string. An empty string is returned if the command does not have any output (for example, a
clear
command).- Return type:
str
- Raises:
RuntimeError – Error if the connection was lost.
SrosMgmtError – Error when command was not successful.
ActionTerminatedIncompleteError – Error when command terminated with
terminated-incomplete
status.
Examplefrom pysros.management import connect connection_object = connect(host='192.168.1.1', username='myusername', password='mypassword') print(connection_object.cli('show version'))
- action(path, value={})
Perform a YANG-modeled action on SR OS by providing the json-instance-path to the action statement in the chosen operations YANG model, and the pySROS data structure to match the YANG-modeled input for that action. This method provides structured data input and output for available operations.
- Parameters:
path (str) – json-instance-path to the YANG action.
value (pySROS data structure) – pySROS data structure providing the input data for the chosen action.
- Returns:
YANG-modeled, structured data representing the output of the modeled action (operation)
- Return type:
pySROS data structure
Example calling the ping YANG-modeled action (operation)>>> from pysros.management import connect >>> from pysros.pprint import printTree >>> connection_object = connect(host='192.168.1.1', ... username='myusername', password='mypassword') >>> path = '/nokia-oper-global:global-operations/ping' >>> input_data = {'destination': '172.16.100.101'} >>> output = connection_object.action(path, input_data) >>> output Container({'operation-id': Leaf(12), 'start-time': Leaf('2022-09-08T22:21:32.6Z'), 'results': Container({'test-parameters': Container({'destination': Leaf('172.16.100.101'), 'count': Leaf(5), 'output-format': Leaf('detail'), 'do-not-fragment': Leaf(False), 'fc': Leaf('nc'), 'interval': Leaf('1'), 'pattern': Leaf('sequential'), 'router-instance': Leaf('Base'), 'size': Leaf(56), 'timeout': Leaf(5), 'tos': Leaf(0), 'ttl': Leaf(64)}), 'probe': {1: Container({'probe-index': Leaf(1), 'status': Leaf('response-received'), 'round-trip-time': Leaf(2152), 'response-packet': Container({'size': Leaf(64), 'source-address': Leaf('172.16.100.101'), 'icmp-sequence-number': Leaf(1), 'ttl': Leaf(64)})}), 2: Container({'probe-index': Leaf(2), 'status': Leaf('response-received'), 'round-trip-time': Leaf(2097), 'response-packet': Container({'size': Leaf(64), 'source-address': Leaf('172.16.100.101'), 'icmp-sequence-number': Leaf(2), 'ttl': Leaf(64)})}), 3: Container({'probe-index': Leaf(3), 'status': Leaf('response-received'), 'round-trip-time': Leaf(2223), 'response-packet': Container({'size': Leaf(64), 'source-address': Leaf('172.16.100.101'), 'icmp-sequence-number': Leaf(3), 'ttl': Leaf(64)})}), 4: Container({'probe-index': Leaf(4), 'status': Leaf('response-received'), 'round-trip-time': Leaf(2164), 'response-packet': Container({'size': Leaf(64), 'source-address': Leaf('172.16.100.101'), 'icmp-sequence-number': Leaf(4), 'ttl': Leaf(64)})}), 5: Container({'probe-index': Leaf(5), 'status': Leaf('response-received'), 'round-trip-time': Leaf(1690), 'response-packet': Container({'size': Leaf(64), 'source-address': Leaf('172.16.100.101'), 'icmp-sequence-number': Leaf(5), 'ttl': Leaf(64)})})}, 'summary': Container({'statistics': Container({'packets': Container({'sent': Leaf(5), 'received': Leaf(5), 'loss': Leaf('0.0')}), 'round-trip-time': Container({'minimum': Leaf(1690), 'average': Leaf(2065), 'maximum': Leaf(2223), 'standard-deviation': Leaf(191)})})})}), 'status': Leaf('completed'), 'end-time': Leaf('2022-09-08T22:21:36.9Z')}) >>> printTree(output) +-- operation-id: 13 +-- start-time: 2022-09-08T22:23:21.2Z +-- results: | +-- test-parameters: | | +-- destination: 172.16.100.101 | | +-- count: 5 | | +-- output-format: detail | | +-- do-not-fragment: False | | +-- fc: nc | | +-- interval: 1 | | +-- pattern: sequential | | +-- router-instance: Base | | +-- size: 56 | | +-- timeout: 5 | | +-- tos: 0 | | `-- ttl: 64 | +-- probe: | | +-- 1: | | | +-- probe-index: 1 | | | +-- status: response-received | | | +-- round-trip-time: 2159 | | | `-- response-packet: | | | +-- size: 64 | | | +-- source-address: 172.16.100.101 | | | +-- icmp-sequence-number: 1 | | | `-- ttl: 64 | | +-- 2: | | | +-- probe-index: 2 | | | +-- status: response-received | | | +-- round-trip-time: 2118 | | | `-- response-packet: | | | +-- size: 64 | | | +-- source-address: 172.16.100.101 | | | +-- icmp-sequence-number: 2 | | | `-- ttl: 64 | | +-- 3: | | | +-- probe-index: 3 | | | +-- status: response-received | | | +-- round-trip-time: 2098 | | | `-- response-packet: | | | +-- size: 64 | | | +-- source-address: 172.16.100.101 | | | +-- icmp-sequence-number: 3 | | | `-- ttl: 64 | | +-- 4: | | | +-- probe-index: 4 | | | +-- status: response-received | | | +-- round-trip-time: 2084 | | | `-- response-packet: | | | +-- size: 64 | | | +-- source-address: 172.16.100.101 | | | +-- icmp-sequence-number: 4 | | | `-- ttl: 64 | | `-- 5: | | +-- probe-index: 5 | | +-- status: response-received | | +-- round-trip-time: 1735 | | `-- response-packet: | | +-- size: 64 | | +-- source-address: 172.16.100.101 | | +-- icmp-sequence-number: 5 | | `-- ttl: 64 | `-- summary: | `-- statistics: | +-- packets: | | +-- sent: 5 | | +-- received: 5 | | `-- loss: 0.0 | `-- round-trip-time: | +-- minimum: 1735 | +-- average: 2038 | +-- maximum: 2159 | `-- standard-deviation: 153 +-- status: completed `-- end-time: 2022-09-08T22:23:25.4Z
- convert(path, payload, *, source_format, destination_format, pretty_print=False, action_io='output')
Returns converted version of the input data (payload) in the destination format.
The input data must be valid according to the YANG schema for the
Connection
object thatconvert()
is being called against.- Parameters:
path (str) – json-instance-path to the location in the YANG schema that the payload uses as its YANG-modeled root.
payload (pySROS data structure, str) – Input data for conversion. The payload must be valid data according to the YANG schema associated with the
Connection
object and should be in the format as defined in thesource_format
argument. ForpySROS
, the payload must be a pySROS data structure. Forxml
orjson
, the payload must be a string containing valid XML or JSON IETF data.source_format (str) – Format of the input data. Valid options are
xml
,json
, orpysros
.destination_format (str) – Format of the output data. Valid options are
xml
,json
, orpysros
.pretty_print (bool, optional) – Format the output for human consumption.
action_io (str, optional) – When converting the input/output of a YANG-modeled operation (action), it is possible for there to be conflicting fields in the input and output sections of the YANG. This parameter selects whether to consider the payload against the
input
oroutput
section of the YANG. Default:output
.
- Returns:
Data structure of the same format as
destination_format
.- Return type:
pySROS data structure, str
An example of the
convert()
function can be found in the Converting data formats section.Note
Any metadata associated with a YANG node is currently not converted. Metadata includes SR OS configuration comments as well as more general metadata such as insert or delete operations defined in XML attributes. If metadata is provided in the payload in XML or JSON format, it is stripped from the resulting output. Attention should be given to converting the output of the
compare summary netconf-rpc
MD-CLI command.
- list_paths(path='/', *, action_io=None)
Obtain the JSON instance paths supported by a specific
Connection
object. The Modeled paths section describes more details about the JSON instance path format. The method returns the supported schema nodes and does not provide any instance data.YANG-modeled operations (called
action
in YANG) are not returned by default. Use theaction_io
parameter to output YANG-modeled operations. The path to the action statement, or the paths to the actions input or output parameters may be chosen.Note
List keys are shown in the JSON instance path but do not contain the list key’s value as this is instance data.
- Parameters:
path (str) – Path to start the list of the supported paths from. The path is an instance-identifier based on RFC 6020 and RFC 7951. The path can be obtained from an SR OS device using the
pwc json-instance-path
MD-CLI command. The path may point to a YANG Container, List, Leaf or a Leaf-List. The default is to provide all supported JSON instance paths from the root.action_io (str) – Obtain YANG action paths. Supported values are:
action_only
,input
oroutput
.
- Returns:
A
generator
object containing the supported JSON instance paths.- Return type:
generator
- Raises:
KeyError – Unsupported
action_io
option.
Example printing all supported pathsfrom pysros.management import connect connection_object = connect() for path in connection_object.list_paths(): print(path)
Example printing all supported paths that contain the word “openconfig”from pysros.management import connect connection_object = connect() for path in connection_object.list_paths(): if "openconfig" in path: print(path)
Example printing all supported paths in a specific pathfrom pysros.management import connect connection_object = connect() for path in connection_object.list_paths("/nokia-conf:configure/router[router-name]/static-routes"): print(path)
Example printing all input and output parameters to allperform card
operationsfrom pysros.management import connect connection_object = connect() for direction in ["input", "output"]: print("=" * 79) print("%s paramaters" % direction) print("-" * 79) for path in c.list_paths("/nokia-oper-perform:perform/card", action_io=direction): print(path)
- session_id()
Returns the current connections session-id.
- Returns:
Current connections session-id.
- Return type:
int
- class pysros.management.Datastore(connection, target)
Bases:
object
Datastore object that can be used to perform multiple operations on a specified datastore.
- get(path, *, defaults=False, config_only=False, filter=None)
Obtain a pySROS data structure containing the contents of the supplied path. See the The pySROS data model section for more information about the pySROS data structure.
- Parameters:
path (str) –
Path to the requested node in the datastore. The path is an instance-identifier based on RFC 6020 and RFC 7951. The path can be obtained from an SR OS device using the
pwc json-instance-path
MD-CLI command. The path may point to a YANG Container, List, Leaf, Leaf-List or a specific List entry.defaults (bool) – Obtain default values in addition to specifically set values.
config_only (bool) – Obtain configuration data only. Items marked as
config false
in YANG are not returned.filter (dict) – A filter defining one or more of the following: Content node matches that select items whose values are equal to the provided filter or Selection node matches that define which fields to return. See Example using content node matching filters, Example using selection node filters and Example using content node match filters and selection node filters together for examples.
- Returns:
A pySROS data structure. This may be a simple value or a more complicated structure depending on the path requested.
- Return type:
pysros.wrappers.Leaf
,pysros.wrappers.LeafList
,pysros.wrappers.Container
- Raises:
RuntimeError – Error if the connection was lost.
InvalidPathError – Error if the path is malformed.
SrosMgmtError – Error for broader SR OS issues including (non-exhaustive list): passing invalid objects, and setting to an unsupported branch.
TypeError – Error if fields or keys are incorrect.
InternalError – Error if the schema is corrupted.
Note
Any whitespace at the beginning or end of a content match filter is stripped.
Examplefrom pysros.management import connect import sys connection_object = connect() try: oper_name = connection_object.running.get("/nokia-state:state/system/oper-name") except RuntimeError as runtime_error: print("Runtime Error:", runtime_error) sys.exit(100) except InvalidPathError as invalid_path_error: print("Invalid Path Error:", invalid_path_error) sys.exit(101) except SrosMgmtError as sros_mgmt_error: print("SR OS Management Error:", sros_mgmt_error) sys.exit(102) except TypeError as type_error: print("Type Error:", type_error) sys.exit(103) except InternalError as internal_error: print("Internal Error:", internal_error) sys.exit(104)
Example using content node matching filtersfrom pysros.management import connect connection_object = connect() connection_object.running.get( "/nokia-conf:configure/service/vprn", filter={"service-name": "VPRN_42"} )
Example using selection node filtersfrom pysros.management import connect connection_object = connect() connection_object.running.get( "/nokia-conf:configure/service/vprn", filter={"admin-state": {}, "interface": {"interface-name": {}}}, )
Example using content node match filters and selection node filters togetherfrom pysros.management import connect connection_object = connect() connection_object.running.get( "/nokia-conf:configure/service/vprn", filter={'service-name': 'VPRN_42', 'admin-state': {}, 'interface': {'interface-name': {}}}, )
- set(path, value, commit=True, method='default')
Set a pySROS data structure to the supplied path. See the The pySROS data model section for more information about the pySROS data structure.
- Parameters:
path (str) – Path to the target node in the datastore. See the path parameter definition in
pysros.management.Datastore.get()
for details.value – Value to set the node to. When
path
points to a Leaf, the value should be a str (optionally wrapped in apysros.wrappers.Leaf
). Whenpath
points to a Leaf-List, the value should be a list of str (optionally wrapped in apysros.wrappers.LeafList
). Whenpath
points to a Container or list item, the value should be a dict (optionally wrapped in apysros.wrappers.Container
). Valid nested data structures are supported.commit (bool) – Specify whether update and commit should be executed after set. Default True.
method (str) – Specify whether set operation should be
default
ormerge
orreplace
. Defaultdefault
.
- Raises:
RuntimeError – Error if the connection is lost.
InvalidPathError – Error if the path is malformed.
SrosMgmtError – Error for broader SR OS issues, including (non-exhaustive list): passing invalid objects, and setting to an unsupported branch.
TypeError – Error if fields or keys are incorrect.
InternalError – Error if the schema is corrupted.
SrosConfigConflictError – Error if configuration commit failed due to conflicts.
Example 1 - Configuring a leaffrom pysros.management import connect connection_object = connect() payload = "my-router-name" connection_object.candidate.set("/nokia-conf:configure/system/name", payload)
Example 2 - Configuring a more complex structurefrom pysros.management import connect from pysros.wrappers import * connection_object = connect() path = '/nokia-conf:configure/router[router-name="Base"]/interface[interface-name="demo1"]' data = Container({'interface-name': Leaf('demo1'), 'port': Leaf('1/1/c1/1:0'), 'ipv4': Container({'primary': Container({'prefix-length': Leaf(24), 'address': Leaf('192.168.100.1')})}), 'admin-state': Leaf('enable')}) connection_object.candidate.set(path, data)
- delete(path, commit=True, *, annotations_only=False)
Delete a specific path from an SR OS node.
- Parameters:
path (str) – Path to the node in the datastore. See the path parameter definition in
pysros.management.Datastore.get()
for details.commit (bool) – Specify whether commit should be executed after delete. Default True.
annotations_only (bool) – If specified, object where path is pointing is not deleted but only the annotation attached to the object.
- Raises:
RuntimeError – Error if the connection is lost.
InvalidPathError – Error if the path is malformed.
LookupError – Error if path does not exist.
SrosMgmtError – Error for broader SR OS issues, including (non-exhaustive list): passing invalid objects, and setting to an unsupported branch.
TypeError – Error if fields or keys are incorrect.
InternalError – Error if the schema is corrupted.
SrosConfigConflictError – Error if configuration commit failed due to conflicts.
Examplefrom pysros.management import connect connection_object = connect() connection_object.candidate.delete('/nokia-conf:configure/log/log-id[name="33"]')
- exists(path)
Check if a specific node exists.
- Parameters:
path (str) – Path to the node in the datastore. See the path parameter definition in
pysros.management.Datastore.get()
for details.- Return type:
bool
- Raises:
RuntimeError – Error if the connection is lost.
InvalidPathError – Error if the path is malformed.
SrosMgmtError – Error for broader SR OS issues, including (non-exhaustive list): passing invalid objects, and setting to an unsupported branch.
TypeError – Error if fields or keys are incorrect.
InternalError – Error if the schema is corrupted.
Examplefrom pysros.management import connect connection_object = connect() if connection_object.running.exists('/nokia-conf:configure/log/log-id[name="33"]') == True: print("The log with the ID of 33 is present on the SR OS router") else: print("This log ID is not present on the SR OS router")
- get_list_keys(path, defaults=False)
Returns list of key values.
- Parameters:
path (str) – Path to the node in the datastore. See the path parameter definition in
pysros.management.Datastore.get()
for details.defaults (bool) – Obtain default values in addition to specifically set values.
- Return type:
list
- Raises:
RuntimeError – Error if the connection was lost.
InvalidPathError – Error if the path is malformed.
SrosMgmtError – Error for broader SR OS issues, including (non-exhaustive list): passing invalid objects, and setting to an unsupported branch.
TypeError – Error if fields or keys are incorrect.
InternalError – Error if the schema is corrupted.
LookupError – Error if path does not exist.
- lock()
Lock the configuration datastore. Transitions a candidate configuration into an exclusive candidate configuration.
- Raises:
SrosMgmtError – Error if a lock cannot be obtained.
Note
The
lock()
method may only be called against thecandidate
configuration datastore.Note
Only one lock may be obtained per SR OS system. Attempting to obtain another lock raises an exception.
- unlock()
Unlock the configuration datastore. Transitions an exclusive candidate configuration to a candidate configuration. Any changes present in the candidate configuration are retained.
- Raises:
SrosMgmtError – Error if no lock is held.
Note
The
unlock()
method may only be called against thecandidate
configuration datastore.
- commit()
Commit the candidate configuration.
- Raises:
SrosMgmtError – Error if committing the configuration is not possible.
Note
The
commit()
method may only be called against thecandidate
configuration datastore.
- discard()
Discard the current candidate configuration.
- Raises:
SrosMgmtError – Error if discarding the candidate configuration is not possible.
Note
The
discard()
method may only be called against thecandidate
configuration datastore.
- compare(path='', *, output_format)
Perform a comparison of the uncommitted candidate configuration with the baseline configuration. The output can be provided in XML or in MD-CLI format and provided in a format where, if applied to the node, the resulting configuration would be the same as if the candidate configuration is committed.
- Parameters:
output_format (str) – Specify output format of compare command. Supported formats are
xml
andmd-cli
. Themd-cli
output format displays similar output to that of the compare summary command on the MD-CLI. Thexml
output format displays similar output to that of the compare summary netconf-rpc MD-CLI command.path (str) – Specify json-instance-path to the location in the schema that the compare runs from. This is the root of the comparison.
- Returns:
The formatted differences between the configurations.
- Return type:
str
Note
The
compare()
method may only be called against thecandidate
configuration datastore.Example - Compare in XML formatfrom pysros.management import connect connection_object = connect() path = '/nokia-conf:configure/policy-options/policy-statement[name="DEMO"]' output_format = 'xml' print("Current config in", path) print(connection_object.candidate.get(path)) print("Deleting config in", path) connection_object.candidate.delete(path, commit=False) print("Comparing the candidate configuration to the baseline configuration in {} format".format(output_format)) print(connection_object.candidate.compare(output_format=output_format))
- exception pysros.management.SrosMgmtError
Bases:
Exception
Exception raised by the
pysros.management
objects when:data is missing
incorrect combinations of datastore and operation are performed
validation fails when using
pysros.management.Datastore.set()
invalid objects are passed to the operation e.g.
pysros.management.Datastore.set()
- exception pysros.management.InvalidPathError
Bases:
Exception
Exception raised when a path provided by the user:
is empty
fails to parse
does not point to an existing object
is missing list keys that must be provided
- exception pysros.management.ModelProcessingError
Bases:
Exception
Exception raised when an error occurs during processing of the YANG model (schema) when:
a YANG file cannot be found
a YANG file is malformed
- exception pysros.management.InternalError
Bases:
Exception
Exception raised for broader issues when:
schema creation fails and this unfinished schema is utilized
- exception pysros.management.SrosConfigConflictError
Bases:
Exception
Exception raised when a configuration commit failed due to conflicts between the
candidate
datastore and thebaseline
datastore. Retrying the configuration operation usually resolves the situation. If retrying does not resolve the issue, the connection should be closed usingpysros.management.Connection.disconnect()
and the operation restarted to make a new connection.
- exception pysros.management.ActionTerminatedIncompleteError
Bases:
Exception
Exception raised when an operation (also known as an action) completes with a
terminated-incomplete
status.
- exception pysros.management.JsonDecodeError
Bases:
Exception
Exception raised when parsing json input fail.
- exception pysros.management.XmlDecodeError
Bases:
Exception
Exception raised when parsing xml input fail.
- pysros.management.Empty
Define the YANG
empty
type.The YANG
empty
type is not the same as an empty string""
or as theNone
type in Python. It requires specific translation depending on whether it is being used in XML or in JSON IETF encodings.The
Empty
class is used to represent the value of a node that is of the YANG typeempty
.Example - Obtaining YANGempty
type values>>> connection_object.running.get('/nokia-conf:configure/system/grpc/allow-unsecure-connection') Leaf(Empty)
Example - Configuring a YANGempty
type>>> from pysros.management import Empty >>> connection_object.candidate.set('/nokia-conf:configure/system/grpc/allow-unsecure-connection', Empty)
pysros.pprint
- Specialized output formatting
This module contains functions to assist with stylized formatting of data.
- class pysros.pprint.TreePrinter(*, align=False, depth=None)
Bases:
object
Object used to print the result of a call to
pysros.management.Datastore.get()
as an ASCII tree.- Parameters:
align (bool) – Whether to align values of a container in the same column.
depth (None, int) – Maximum tree depth to print.
- Raises:
ValueError – Error if the depth is not positive.
Note
The
pysros.pprint.printTree()
function provides a simple way to use this object.- print(obj)
Print the specified object.
- Parameters:
obj – Object to print.
- pysros.pprint.printTree(obj, **kwargs)
Print the result of a call to
pysros.management.Datastore.get()
as an ASCII tree.See arguments of
TreePrinter
Examplefrom pysros.pprint import printTree from pysros.wrappers import Leaf, Container def main(): data = Container({'auto-config-save': Leaf(True), 'capabilities': Container({'candidate': Leaf(True), 'writable-running': Leaf(False)}), 'admin-state': Leaf('enable')}) printTree(data) if __name__ == "__main__": main()
- class pysros.pprint.Column(width, name=None, align='<', padding=0)
Bases:
object
Column descriptor to be used in
pysros.pprint.Table
andpysros.pprint.KeyValueTable
.- Parameters:
width (int) – Width of the column (number of characters).
name (None, str) – Name of the column. This may be None when column headers are not to be printed. Default None.
align (str) – Alignment of the column: ‘<’ for left, ‘>’ for right and ‘^’ for centered. Defaults to ‘<’.
padding (int) – Number of padding characters, already accounted for in width. Default 0.
- Raises:
ValueError – Error if align is not valid.
- format(value)
Format a value according to the parameters of this column, considering width, alignment, and padding.
- Parameters:
value – Value to format.
- Returns:
Formatted value.
- Return type:
str
- static create(arg)
Static method to create a Column object.
- Parameters:
arg (
pysros.pprint.Column
, tuple) – This can either be apysros.pprint.Column
object or the parameters to pass to the constructor thereof.- Raises:
TypeError – Error if Column is not valid.
- class pysros.pprint.Padding(width)
Bases:
Column
Special type of column which takes no data. It is only used to add empty space into a table.
- Parameters:
width (int) – Width of the (empty) column.
- class pysros.pprint.Table(title, columns, width=79, showCount=None, summary=None)
Bases:
ATable
Class that provides the functionality to display tabulated data in the standard SR OS style.
- Parameters:
title (str) – Title of the table.
columns – List of column descriptions. Elements of the list can be a
pysros.pprint.Column
or a tuple with parameters to be passed topysros.pprint.Column.create()
.width (int) – Width of the table in characters.
showCount – Indicate if a count of rows should be shown in the footer. In case no count is required, pass in None. In case a count is required, pass in the name of the object represented in a row.
summary (str) – Optional block of text to be displayed in the footer.
Example creation of a Table objectfrom pysros.pprint import Table, Padding def simple_table_builder_example(): summary = \ """ This is the text that we would like in our summary sections at the end of the output""" rows = [["row0col0", "row0col1"], ["row1col0", "row1col1"]] cols = [(30, "Column0"), (30, "Column1")] width = sum([col[0] for col in cols]) table = Table("This is my tables title", columns=cols, showCount="CounterName", summary=summary, width=width) return table, rows if __name__ == "__main__": table, rows = simple_table_builder_example()
- print(rows)
Display a complete table when passed in the rows of data. Separate components are displayed as configured during initialization.
- Parameters:
rows – List of tuples containing the data to be displayed. Each tuple in the list is a row and each item in the tuple is the value for a specific column. Padding columns do not need corresponding values in the tuple.
ExampleTable.print()
using the Table defined in this Example creation of a Table object>>> def table_print_example(table, rows): ... table.print(rows) ... >>> table_print_example(table, rows) ============================================================ This is my tables title ============================================================ Column0 Column1 ------------------------------------------------------------ row0col0 row0col1 row1col0 row1col1 ------------------------------------------------------------ No. of CounterName: 2 This is the text that we would like in our summary sections at the end of the output ============================================================
- printRows(rows)
Print rows of data.
- Parameters:
rows – List of tuples containing the data to be displayed. Each tuple in the list is a row and each item in the tuple is the value for a specific column. Padding columns do not need corresponding values in the tuple.
ExampleTable.printRows()
using the Table defined in this Example creation of a Table object>>> def table_printRows_example(table, rows): ... table.printRows(rows) ... >>> table_printRows_example(table, rows) row0col0 row0col1 row1col0 row1col1
- printRow(row)
Print a specific row of data.
- Parameters:
row – Tuple where each item in the tuple is the value for a specific column. Padding columns do not need corresponding values in the tuple.
ExampleTable.printRow()
using the Table defined in this Example creation of a Table object>>> def table_printRow_example(table, row): ... table.printRow(row) ... >>> table_printRow_example(table, rows[0]) row0col0 row0col1
- printColumnHeaders()
Print the column headers and a separator line.
ExampleTable.printColumnHeaders()
using the Table defined in this Example creation of a Table object>>> def table_printColumnHeaders_example(table): ... table.printColumnHeaders() ... >>> table_printColumnHeaders_example(table) Column0 Column1 ------------------------------------------------------------
- printSummary(showLine=True, customSummary=None)
Print a summary. This section contains the count of rows and any optional summary text.
- Parameters:
showLine (bool) – Display a line above the summary section.
customSummary (str) – Custom text to be displayed.
ExampleTable.printSummary()
using the Table defined in this Example creation of a Table object>>> def table_printSummary_example(table): ... table.printSummary(customSummary='This is an optional customized summary') ... >>> table_printSummary_example(table) ------------------------------------------------------------ No. of CounterName: 0 This is an optional customized summary
- class pysros.pprint.KeyValueTable(title, columns, width=79)
Bases:
ATable
Display a list of key and value data in an SR OS table format.
- Parameters:
title (str) – Title of the table.
columns – List of column descriptions. Elements of the list can be
pysros.pprint.Column
or a tuple with parameters to be passed topysros.pprint.Column.create()
. When displaying the data, key and value columns are interleaved. Multiple key-value pairs are allowed on a single row, and the number of columns is even, that is, key and value data always appear on the same row next to each other.width – Width of the table in characters.
- Raises:
ValueError – Error if the number of columns is not valid.
Example table creation usingKeyValueTable
>>> from pysros.pprint import KeyValueTable >>> table = KeyValueTable('Key Value Table Title', [(20, None), (20, None)])
Note
This class defines the KeyValueTable object. The
KeyValueTable.print()
,KeyValueTable.printKV()
orKeyValueTable.printKVs()
methods should be used to output KeyValueTables.- printKV(*kvs)
Print a table of key-value pairs that are passed into this method. This method does not require the data to be structured as a list of 2-tuples. The key-value pairs are displayed in the available columns if the pairs are available in the
KeyValueTable
definition.- Parameters:
args – Interleaved key and value objects.
Example table output usingKeyValueTable
andKeyValueTable.printKV()
.>>> from pysros.pprint import KeyValueTable >>> table = KeyValueTable(None, [(20, None), (20, None)]) >>> table.printKV("k0", "v0", "k1", "v1", "k2", "v2") k0 : v0 >>> table = KeyValueTable(None, [(12,), (12,), (12,), (12,), (12,), (12,)]) >>> table.printKV("k0", "v0", "k1", "v1", "k2", "v2") k0 : v0 k1 : v1 k2 : v2
- printKVs(items)
Print a table of key-value pairs that are passed into this method as a list of 2-tuples.
- Parameters:
data – List of tuples containing the data to be displayed. Each tuple in the list must contain two fields: (key, value). Data is spread over the available columns first, starting a new row when required.
Example table output usingKeyValueTable
andKeyValueTable.printKVs()
.>>> from pysros.pprint import KeyValueTable >>> table = KeyValueTable(None, [(20, None), (20, None)]) >>> table.printKVs([("k0", "v0"), ("k1", "v1"), ("k2", "v2")]) k0 : v0 k1 : v1 k2 : v2 >>> table = KeyValueTable(None, [(12,), (12,), (12,), (12,), (12,), (12,)]) >>> table.printKVs([("k0", "v0"), ("k1", "v1"), ("k2", "v2")]) k0 : v0 k1 : v1 k2 : v2
- print(data)
Display a complete table when passed in the list of key-value pairs. Separate components are displayed as configured during initialization.
- Parameters:
data – List of tuples containing the data to be displayed. Each tuple in the list must contain two fields: (key, value). Data is spread over the available columns first, starting a new row when required.
Example table output usingKeyValueTable
andKeyValueTable.print()
.>>> from pysros.pprint import KeyValueTable >>> data = [('k0','v0'), ('k1','v1'),('k2','v2')] >>> table = KeyValueTable('Two column Key Value Table Title', [(20, None), (20, None)]) >>> table.print(data) =============================================================================== Two column Key Value Table Title =============================================================================== k0 : v0 k1 : v1 k2 : v2 =============================================================================== >>> table = KeyValueTable('Six column Key Value Table Title', ... [(12,), (12,), (12,), (12,), (12,), (12,)]) >>> table.print(data) =============================================================================== Six column Key Value Table Title =============================================================================== k0 : v0 k1 : v1 k2 : v2 ===============================================================================
- printColumnHeaders()
Print the column headers and a separator line.
ExampleKeyValueTable.printColumnHeaders()
using the Table defined in this Example creation of a Table object>>> def table_printColumnHeaders_example(table): ... table.printColumnHeaders() ... >>> table_printColumnHeaders_example(table) Column0 Column1
pysros.wrappers
- Model-driven class wrappers
This module contains wrappers describing the YANG structure and metadata obtained from SR OS.
- class pysros.wrappers.Action(value=None, *, annotations=None)
Bases:
Container
YANG Action data structure node wrapper.
Action in the pySROS data structure behaves as Container, but it it returned by convert action.
- Variables:
data – dictionary containing the fields data
- class pysros.wrappers.Container(value=None, *, annotations=None)
Bases:
Wrapper
YANG container data structure node wrapper.
A YANG container in the pySROS data structure behaves in the same way as a Python dict, where the value of a field can be obtained using the field name.
- Variables:
data – dictionary containing the fields data
- class pysros.wrappers.Leaf(value, annotations=None)
Bases:
Wrapper
YANG leaf data structure node wrapper.
Depending on the base (root) YANG type of the node, this object wraps a str, int, or bool.
- Variables:
data – python object corresponding to the value
- class pysros.wrappers.LeafList(value=None, *, annotations=None)
Bases:
Wrapper
YANG leaf-list data structure node wrapper.
A YANG leaf-list in the pySROS data structure behaves in the same way as a Python list, where the separate values can be obtained using an index.
- Variables:
data – list containing the values
- property annotations
List of YANG annotations (metadata) applied to the LeafList.
Applying YANG annotations to a
LeafList
uses the same constructs detailed in theAnnotations
section. When applied to LeafLists theannotations
property is a Python list. Each entry in the LeafList has an entry in theannotations
list.Each entry in the LeafList may have zero or more annotations. This list of annotations per entry is represented as an instance of the
Annotations
class. Each instance ofAnnotations
has zero or more instances of theAnnotation
.This concept is better illustrated through examples.
Note
The example below will not validate against the Nokia YANG models but is provided to detail the implementation and usage of YANG annotations attached to
LeafList
classes.Consider the following LeafList:
>>> my_leaflist LeafList(['one', 'two', 'three'])
The list of annotations attached to this
LeafList
is stored in theannotations
attribute:>>> my_leaflist.annotations []
This is an empty list as there are no annotations defined against any entry in the
LeafList
. Annotations will now be added to the first entry and the last entry of the list. The first entry will have two annotations and the last one:>>> my_leaflist.annotations = [ ... Annotations([ ... Annotation(key='key1', data='value1'), ... Annotation(key='key2', data='value2') ... ]), ... Annotations([]), ... Annotations([ ... Annotation(key='key3', data='value3') ... ]) ... ] >>> my_leaflist.annotations [ Annotations([ Annotation(key='key1', data='value1'), Annotation(key='key2', data='value2')]), Annotations([]), Annotations([ Annotation(key='key3', data='value3') ]) ]
- class pysros.wrappers.Annotation(key, data=None, *, module=None, namespace=None)
Bases:
object
Wrapper for an individual annotation (YANG metadata) associated with an elements in the data structure. An element in the data structure may have more than one
Annotation
. TheAnnotations
class is used to define this.Allows operator to provide an arbitrary key/value pair to any element in the pySROS data structure. The data in the
Annotation
must exist in the nodes YANG schema for thepysros.management.Datastore.set()
andpysros.management.Connection.convert()
methods to function.- Variables:
key – The name of the YANG annotation statement. This may be in simple form or in namespace qualified form, for example:
comment
ornokia-attr:comment
.data – The value of the annotation.
module – The YANG module name in which the YANG annotation exists.
namespace – The YANG module namespace in which the YANG annotation exists.
- key
The name of the YANG annotation statement. This may be in simple form or in namespace qualified form, for example: comment or nokia-attr:comment.
- data
The value of the annotation.
- module
The YANG module name in which the YANG annotation exists.
- namespace
The YANG module namespace in which the YANG annotation exists.
- property schema
YANG schema supporting information associated with elements in the data structure (Read only).
- class pysros.wrappers.Annotations(initlist=None)
Bases:
UserList
Annotations class provides wrapper for instances of the Annotation class that must be supplied in the same way as Python list.
The annotations (there may be more than one) on a particular YANG node are defined in the
annotations
parameter attached to aLeaf
,Container
orLeafList
. Theannotations
parameter is a class of typeAnnotations
(with an ‘s’). This is a list ofAnnotation
(without an ‘s’) class instances.An
Annotation
in pySROS is treated in a similar way as any other YANG structure such as aLeaf
. AAnnotation
class wrapper encodes the structures required to define and use a YANG-modeled annotation. Unlike other wrappers, because a YANG-modeled annotation can be in a different YANG namespace from the node it is attached to, additional information is needed.The
pysros.management.Connection.convert()
method and thepysros.management.Datastore.set()
method support theAnnotation
class. This means that, as with other data in pySROS, annotations can be entered without providing the details of the YANG module and these methods derive the correct YANG model information using the YANG schema learned from the specific router.Note
Applying annotations to
LeafList
objects requires special consideration. Please refer to theLeafList.annotations
section for more information.The following example obtains a
Leaf
from the device, in this instance the system name, and adds a configuration comment to it which it then sets back to the router using thepysros.management.Datastore.set()
method. The example assumes that apysros.management.Connection
object calledconnection_object
has already been created:Set a configuration comment on the system name obtained from the device>>> from pysros.wrappers import Annotations, Annotation >>> path = '/nokia-conf:configure/system/name' >>> system_name = connection_object.running.get(path) >>> system_name Leaf('sros') >>> system_name.annotations = [Annotation('comment', 'This is my comment')] >>> connection_object.candidate.set(path, system_name)
The following example obtains a
Leaf
from the device and adds a configuration comment to it in the native Python data structure. It then uses thepysros.management.Connection.convert()
method to query the known YANG schema for the given router and add the YANG model information to theAnnotation
. The example assumes that apysros.management.Connection
object calledconnection_object
has already been created:Use convert to identify and complete YANG specific attributes in the object>>> from pysros.wrappers import Annotations, Annotation >>> path = '/nokia-conf:configure/system/name' >>> system_name = connection_object.running.get(path) >>> system_name Leaf('sros') >>> system_name.annotations Annotations([]) >>> system_name.annotations.append(Annotation('comment', 'This is my configuration comment')) >>> system_name.annotations Annotations([Annotation(key='comment', data='This is my configuration comment')]) >>> connection_object.convert(path, ... system_name, ... source_format='pysros', ... destination_format='xml') '<nokia-conf:name xmlns:nokia-conf="urn:nokia.com:sros:ns:yang:sr:conf" xmlns:nokia-attr="urn:nokia.com:sros:ns:yang:sr:attributes" nokia-attr:comment="This is my configuration comment">sros</nokia-conf:name>' >>> connection_object.convert(path, ... system_name, ... source_format='pysros', ... destination_format='json') '{"@nokia-conf:name": {"nokia-attributes:comment": "This is my configuration comment"}, "nokia-conf:name": "sros"}' >>> augmented_system_name = connection_object.convert(path, ... system_name, ... source_format='pysros', ... destination_format='pysros') >>> augmented_system_name.annotations Annotations([Annotation(key='comment', data='This is my configuration comment', module='nokia-attributes', namespace='urn:nokia.com:sros:ns:yang:sr:attributes')])
This next example takes a valid NETCONF RPC encoded in XML that inserts a new item into a user-ordered YANG list. The well-known
operation
annotation. Using theAnnotations
andAnnotation
classes, this RPC can be converted into native the native Python (pySROS) data structure, manipulated if required, and sent to the router. The example assumes that apysros.management.Connection
object calledconnection_object
has already been created.The initial configuration of the user-ordered list is as follows:
Initial state of the user-ordered list(gl)[/configure policy-options policy-statement "example"] A:admin@sros# info entry-type named named-entry "one" { action { action-type accept } } named-entry "three" { action { action-type accept } } default-action { action-type reject }
Convert NETCONF operations using system defined annotations>>> from pysros.wrappers import Annotation, Annotations >>> from pysros.management import connect >>> my_xml = """ ... <configure xmlns="urn:nokia.com:sros:ns:yang:sr:conf" xmlns:yang="urn:ietf:params:xml:ns:yang:1" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"> ... <policy-options> ... <policy-statement> ... <name>example</name> ... <named-entry nc:operation="merge" yang:insert="after" yang:key="[entry-name='one']"> ... <entry-name>two</entry-name> ... <action> ... <action-type>accept</action-type> ... </action> ... </named-entry> ... </policy-statement> ... </policy-options> ... </configure> ... """ >>> my_rpc = connection_object.convert('/', my_xml, source_format='xml', destination_format='pysros') {'configure': Container({'policy-options': Container({'policy-statement': {'example': Container({'name': Leaf('example'), 'named-entry': OrderedDict([('two', Container({'entry-name': Leaf('two'), 'action': Container({'action-type': Leaf('accept')})}, annotations = Annotations([Annotation(key='operation', data='merge', module='ietf-netconf', namespace='urn:ietf:params:xml:ns:netconf:base:1.0'), Annotation(key='insert', data='after', module='yang', namespace='urn:ietf:params:xml:ns:yang:1'), Annotation(key='key', data="[entry-name='one']", module='yang', namespace='urn:ietf:params:xml:ns:yang:1')])))])})}})})} >>> connection_object.candidate.set('/nokia-conf:configure', my_rpc['configure'])
Resulting state of the user-ordered list(gl)[/configure policy-options policy-statement "example"] A:admin@sros# info entry-type named named-entry "one" { action { action-type accept } } named-entry "two" { action { action-type accept } } named-entry "three" { action { action-type accept } } default-action { action-type reject }
The
Annotations
class behaves in a similar way to a native Python list and many of the functions that operate on a Python list will also function on theAnnotations
class. Examples includeindex()
(which returns the numerical location in the list of the requested item),remove()
(which deletes a specific item from a list) andappend()
(which adds an item to the end of a list).Note
When using
index()
andremove()
the exact matchingAnnotation
must be provided including all associated parameters.A number of additional helper methods are provided for searching through
Annotations
and selecting specificAnnotation
entries. These are described below:- index_annotation(key, data=None, *, module=None, namespace=None)
Return the index to searched
Annotation.key
. An exception is raised if theAnnotation
is not found.- Parameters:
key (str) – Name of the
Annotation
. This should match theAnnotation.key
in order to yield a successful match. If more than oneAnnotation
exists with the sameAnnotation.key
other parameters must be provided.data (str, optional) – The value (
Annotation.data
) of theAnnotation
.module (str, optional) – The YANG module name that
Annotation
exists in.namespace (str, optional) – The YANG module namespace that the
Annotation
exists in.
- Raises:
ValueError – A matching
Annotation
is not found.
Note
The example below will not validate against the Nokia YANG models but is provided to detail the implementation and usage of the
Annotations
class.Annotations.index_annotation()
example>>> myleaf.annotations Annotations([Annotation(key='key1', data='data1'), Annotation(key='key2', data='data2'), Annotation(key='key3', data='data3')]) >>> myleaf.annotations.index_annotation('key2') 1
Annotations.index_annotation()
example handling a failed match>>> myleaf.annotations Annotations([Annotation(key='key1', data='data1'), Annotation(key='key2', data='data2'), Annotation(key='key3', data='data3')]) >>> try: ... myleaf.annotations.index_annotation('foo') ... except ValueError as error: ... print("Failed to find Annotation:", error) ... Failed to find Annotation: Annotation not found
- get(annotation)
Return the
Annotation
(without an ‘s’) from theAnnotations
(with an ‘s’) class (list) that matches the providedAnnotation
.The match must be identical, that is, all parameters inside the
Annotation
class must match exactly.- Parameters:
annotation (
Annotation
) – Annotation object to match in theAnnotations
list.- Raises:
ValueError – Error if the requested
Annotation
is not found.
Note
The example below does not validate against the Nokia YANG models but is provided to detail the implementation and usage of the
Annotations
class.Annotations.get()
example>>> myleaf.annotations Annotations([Annotation(key='key1', data='data1'), Annotation(key='key2', data='data2'), Annotation(key='key3', data='data3')]) >>> myleaf.annotations.get(Annotation(key='key3', data='data3')) Annotation(key='key3', data='data3')
Annotations.get()
example handling a failed match>>> myleaf.annotations Annotations([Annotation(key='key1', data='data1'), Annotation(key='key2', data='data2'), Annotation(key='key3', data='data3')]) >>> try: ... myleaf.annotations.get('key1') ... except ValueError as error: ... print("Failed to find Annotation:", error) ... Failed to find Annotation: 'key1' is not in list
- get_annotation(key, data=None, *, module=None, namespace=None)
Return the
Annotation
(without an ‘s’) from theAnnotations
(with an ‘s’) class (list) that matches the providedAnnotation.key
. An exception is raised if theAnnotation
is not found.- Parameters:
key (str) – Name of the
Annotation
. This should match theAnnotation.key
in order to yield a successful match. If more than oneAnnotation
exists with the sameAnnotation.key
other parameters must be provided.data (str, optional) – The value (
Annotation.data
) of theAnnotation
.module (str, optional) – The YANG module name that
Annotation
exists in.namespace (str, optional) – The YANG module namespace that the
Annotation
exists in.
- Raises:
ValueError – A matching
Annotation
is not found.
Note
The example below does not validate against the Nokia YANG models but is provided to detail the implementation and usage of the
Annotations
class.Annotations.get_annotation()
example>>> myleaf.annotations Annotations([Annotation(key='key1', data='data1'), Annotation(key='key2', data='data2'), Annotation(key='key3', data='data3')]) >>> myleaf.annotations.get_annotation('key2') Annotation(key='key2', data='data2')
- remove_annotation(key, data=None, *, module=None, namespace=None)
Remove the
Annotation
object for the searchedAnnotation.key
from theAnnotations
class (list). An exception is raised if theAnnotation
is not found.- Parameters:
key (str) – Name of the
Annotation
. This should match theAnnotation.key
in order to yield a successful match. If more than oneAnnotation
exists with the sameAnnotation.key
other parameters must be provided.data (str, optional) – The value (
Annotation.data
) of theAnnotation
.module (str, optional) – The YANG module name that
Annotation
exists in.namespace (str, optional) – The YANG module namespace that the
Annotation
exists in.
- Raises:
ValueError – A matching
Annotation
is not found.
Note
The example below does not validate against the Nokia YANG models but is provided to detail the implementation and usage of the
Annotations
class.Annotations.remove_annotation()
example>>> myleaf.annotations Annotations([Annotation(key='key1', data='data1'), Annotation(key='key2', data='data2'), Annotation(key='key3', data='data3')]) >>> myleaf.annotations.remove_annotation('key2') >>> myleaf.annotations Annotations([Annotation(key='key1', data='data1'), Annotation(key='key3', data='data3')])
- class pysros.wrappers.Schema(model)
Bases:
object
YANG schema supporting information associated with elements in the data structure.
Note
pysros.wrappers.Schema
metadata is read-only.- property module
YANG module name from which this node originates.
- Return type:
str
- property namespace
YANG module namespace from which this node originates. This is in URN or URL format.
- Return type:
str
- property yang_type
YANG data type. This type is the derived base YANG type, for example, if a YANG node uses a
typedef
, and thattypedef
is auint8
, yang_type returnsuint8
.- Return type:
str,
SchemaType
- property units
The units defined in the YANG module.
- Return type:
str
- property default
The default value as defined in the YANG module.
- Return type:
str, int
- property mandatory
Identifies whether the item is required (mandatory) in the YANG module.
- Return type:
bool
pysros.exceptions
- pySROS specific exceptions
This module contains exceptions for error handling within pySROS.
- exception pysros.exceptions.SrosMgmtError
Bases:
Exception
Exception raised by the
pysros.management
objects when:data is missing
incorrect combinations of datastore and operation are performed
validation fails when using
pysros.management.Datastore.set()
invalid objects are passed to the operation e.g.
pysros.management.Datastore.set()
- exception pysros.exceptions.InvalidPathError
Bases:
Exception
Exception raised when a path provided by the user:
is empty
fails to parse
does not point to an existing object
is missing list keys that must be provided
- exception pysros.exceptions.ModelProcessingError
Bases:
Exception
Exception raised when an error occurs during processing of the YANG model (schema) when:
a YANG file cannot be found
a YANG file is malformed
- exception pysros.exceptions.InternalError
Bases:
Exception
Exception raised for broader issues when:
schema creation fails and this unfinished schema is utilized
- exception pysros.exceptions.SrosConfigConflictError
Bases:
Exception
Exception raised when a configuration commit failed due to conflicts between the
candidate
datastore and thebaseline
datastore. Retrying the configuration operation usually resolves the situation. If retrying does not resolve the issue, the connection should be closed usingpysros.management.Connection.disconnect()
and the operation restarted to make a new connection.
- exception pysros.exceptions.ActionTerminatedIncompleteError
Bases:
Exception
Exception raised when an operation (also known as an action) completes with a
terminated-incomplete
status.
- exception pysros.exceptions.JsonDecodeError
Bases:
Exception
Exception raised when parsing json input fail.
- exception pysros.exceptions.XmlDecodeError
Bases:
Exception
Exception raised when parsing xml input fail.
pysros.ehs
- Functions for the event handling system (EHS)
The pysros.ehs
module provides functionality obtain data from the
specific event that triggered the execution of a Python application from
the event handling system (EHS).
Note
This module is available when executing on SR OS only. On a remote machine, the event handling system (EHS) and its functionality are not supported.
- pysros.ehs.get_event()
The EHS event that triggered the execution of the Python application.
- Returns:
The Event object or None.
- Return type:
pysros.ehs.Event
orNone
- class pysros.ehs.Event
The EHS
pysros.ehs.Event
Class for the event that triggered the execution of the Python application.- name
The name of the event.
- Type:
str
- appid
The name of the application that generated the event.
- Type:
str
- eventid
The event ID number of the application.
- Type:
int
- severity
The severity level of the event.
- Type:
str
- sequence
The sequence number of the event in the syslog collector.
- Type:
int
- Raises:
ValueError – for negative values.
- subject
The subject or affected object of the event.
- Type:
str
- router_name
The name of the SR OS router-instance (For example,
Base
) in which this event was triggered.- Type:
str
- gentime
The time, in ISO 8601 format, that the event was generated.
- type:
str
- timestamp
The timestamp, in seconds, that the event was generated.
- Type:
float
- text
The event specific body, formatted as a string. By default, this is generated from the
eventparameters
.- Type:
str
- eventparameters
The additional parameters specific to the event that caused the Python application to execute.
- Type:
- format_msg()
Return a string representation of the SR OS formatted log message.
- Returns:
SR OS formatted log message.
- Return type:
str
- class pysros.ehs.EventParams
The additional parameters of the specific
pysros.ehs.Event
. This class is read-only. Specific additional parameters may be accessed using standard Python subscript syntax.- keys()
Obtain the additional parameters names.
- Returns:
Additional parameters names for the Event.
- Return type:
tuple(str)
- params[key]
Return the value of the parameter key. If the parameter does not exist, a
KeyError
is raised.
pysros.esm
- Functions for the enhanced subscriber management system (ESM)
The pysros.esm
module provides functionality obtain data from the
specific event that triggered the execution of a Python application from
the SR OS subscriber management system.
Note
This module is available when executing on SR OS only. On a remote machine, subscriber management functionality is not supported.
- pysros.esm.get_event()
The subscriber management event that triggered the execution of the Python application.
- Returns:
The Event object or None.
- Return type:
pysros.esm.Event
orNone
- class pysros.esm.Event
The ESM
pysros.esm.Event
Class for the event that triggered the execution of the Python application.- eventparameters
The additional parameters specific to the event that caused the Python application to execute.
- Type:
- class pysros.esm.EventParams
The additional parameters of the specific
pysros.esm.Event
. This class is read-only. Specific additional parameters may be accessed using standard Python subscript syntax.- keys()
Obtain the additional parameters names.
- Returns:
Additional parameters names for the Event.
- Return type:
tuple(str)
- params[key]
Return the value of the parameter key. If the parameter does not exist, a
KeyError
is raised.
pysros.esm.cryptolib
- Cryptographic functions for the ESM system
The pysros.esm.cryptolib
module provides a set of classes and functions that can be used
to encrypt and decrypt data.
Note
This module is available when executing on SR OS only. On a remote
machine, the pysros.esm.cryptolib
module is not supported.
This module is only available when a Python application is triggered by the Enhanced Subscriber Management (ESM) application on SR OS.
The general principle is to create cipher object of the type of pysros.esm.cryptolib.AES
with which you want to encrypt and decrypt data.
This object is created with all required parameters once, after which it can be used multiple times to either encrypt or decrypt pieces of data.
Note
The cipher object contains all information needed to encrypt and decrypt data. Depending on the block-mode used, this also contains the intermediate state needed to chain multiple blocks of data. For these block-modes, an object can only be used for encryption or decryption, but not both at the same time.
MODE_ECB
is an exception because it does not use chaining, hence this object can be used
for both encryption and decryption at the same time.
Cryptography
- class pysros.esm.cryptolib.AES(key, mode, *, padding=None, iv=None)
Create a new AES cipher object. This object can then be used to encrypt and decrypt data.
- Parameters:
key (bytes) – The secret key to use. It must be 16, 24, or 32 bytes long (respectively for AES-128, AES-192 and AES-256).
mode (One of the constants
MODE_ECB
orMODE_CBC
.) – The chaining mode.padding (string, optional) – The padding algorithm to be automatically applied. When provided, the cleartext will be automatically padded/unpadded. The value of this attribute is the style of padding to use. This method can only be used if the complete data to be encrypted or decrypted is passed in as a whole. In case the data is encrypted in multiple invocations of
pysros.esm.cryptolib.AES.encrypt()
andpysros.esm.cryptolib.AES.decrypt()
, manual (un)padding needs to be applied on the last block. See the documentation forpad()
for the supported values.iv (bytes, optional) – The initial vector. For mode
MODE_ECB
this argument is not valid. For modeMODE_CBC
it must be 16 bytes long. If not provided (but required), a random bytestring is generated. Its value must then be read via theiv
attribute.
- encrypt(plaintext, /, *, output=None)
Encrypt plaintext.
The function either returns the encrypted data or places it in a preallocated buffer passed in via the
output
parameter.- Parameters:
plaintext (bytes) – The plaintext that needs to be encrypted. Should be a multiple of the configured
block_size
, unless automatic padding is configured.output (bytearray) – Preallocated buffer into which the encrypted data is written. The input must be of the correct size (i.e. the same length as the plaintext input). It cannot be used when the object is configured to automatically apply padding, as the size might increase due to an extra padding-block.
- Returns:
The ciphertext or
None
when anoutput
buffer was provided.- Return type:
bytes
Example: Encryptingfrom pysros.esm.cryptolib import AES, MODE_ECB key = b'0123456789abcdef' aes = AES(key, MODE_ECB, padding='pkcs7') aes.encrypt(b'My super-secret message') # b'\xd8V\x01\x08\xb9f\xad\xbe\xa1\xbe\x8c\xe4I0E\xc7J\xf1W\xf9\xa0\xf8\x18Nu\xb5\xbd\xe9L_E\xa7'
- decrypt(ciphertext, /, *, output=None)
Decrypt ciphertext.
The function either returns the plaintext data or places it in a preallocated buffer passed in via the
output
parameter.- Parameters:
ciphertext (bytes) – The ciphertext that needs to be decrypted. Should be a multiple of the configured
block_size
, unless automatic padding is configured.output (bytearray) – Preallocated buffer into which the decrypted plaintext is written. Must be of the correct size (i.e. the same length as the ciphertext input). It cannot be used when the object is configured to automatically apply padding, as the size might decrease due to stripped padding.
- Returns:
The plaintext or
None
when anoutput
buffer was provided.- Return type:
bytes
Example: Decryptingfrom pysros.esm.cryptolib import AES, MODE_ECB key = b'0123456789abcdef' aes = AES(key, MODE_ECB, padding='pkcs7') aes.decrypt(b'\xd8V\x01\x08\xb9f\xad\xbe\xa1\xbe\x8c\xe4I0E\xc7J\xf1W\xf9\xa0\xf8\x18Nu\xb5\xbd\xe9L_E\xa7') #b'My super-secret message'
Note
All places where parameters of type bytes are expected, objects of type bytearray or str can also be provided.
Mode constants
- pysros.esm.cryptolib.MODE_ECB
Electronic Code Book mode.
- pysros.esm.cryptolib.MODE_CBC
Cipher-Block Chaining mode
Utilities
- pysros.esm.cryptolib.pad(data, block_size, /, style='pkcs7')
Apply standard padding.
- Parameters:
data (bytes) – The data that needs to be padded.
block_size (int) – The block size to use. The output is a multiple of
block_size
.style – Padding algorithm. It can be
pkcs7
,iso7816
orx923
. Default:pkcs7
.
- Tyoe style:
str, optional
- Returns:
The original data with appropriate padding added to the end. If the length of
data
is already a multiple ofblock_size
, a whole extra block will be added.- Return type:
bytes
- pysros.esm.cryptolib.unpad(data, block_size, /, style='pkcs7')
Remove standard padding.
- Parameters:
data (bytes) – The data that needs to be stripped of padding.
block_size (int) – The block size to use. The input must be a multiple of
block_size
.style (str, optional) – Padding algorithm. It can be
pkcs7
,iso7816
orx923
. Default:pkcs7
.
- Returns:
The data without the padding bytes.
- Return type:
bytes
- Raises:
ValueError – If the padding is incorrect.
pysros.syslog
- Functions for syslog event handling
The pysros.syslog
module provides functionality for obtaining and
manipulating a syslog event.
Note
This module is available when executing on SR OS only. On a remote machine, the syslog function is not supported.
Important
The pysros.syslog
module is designed to be used
with the SR OS syslog functionality at high processing rates.
It cannot be used with the pysros.management
module, SR OS filesystem access, or the EHS, CRON, or pyexec execution
pathways.
Two methods are available to modify the syslog message being sent:
The
pysros.syslog.get_event()
function retrieves the syslog event that is in the queue to be sent out and allows for its attributes to be modified. When the Python application terminates successfully, the newly modified attributes are reformatted using the default syslog format.The
pysros.syslog.Event.override_payload()
method allows for an entirely new payload to be crafted based on the data from the original event but choosing a customer format and which data to include.
Note
The maximum length of a syslog message on SR OS is 1023 bytes. When modifying the payload to become larger than this maximum value, one of the following occurs:
When using
pysros.syslog.Event.override_payload()
, an exception is raised. The length can be checked prior to executing thepysros.syslog.Event.override_payload()
method.When modifying the event parameters, the resulting payload is truncated as the resulting length cannot be known in advance. When this occurs, the last character is marked with an asterisk (*).
- pysros.syslog.get_event()
Obtain the syslog event queued to be sent out.
- Returns:
The event object or None.
- Return type:
pysros.syslog.Event
orNone
- pysros.syslog.generate_pri(facility, severity)
Converts the event severity into a syslog severity and combines it with the facility to generate the syslog PRI value (See RFC 5424 for details) that can be used when formatting a new syslog payload.
- Parameters:
facility (int) – Syslog facility value.
severity (str) – Event severity name.
- Returns:
Syslog PRI value.
- Return type:
str
- Raises:
ValueError – for invalid facilities, see
pysros.syslog.Event.facility
ValueError – for invalid severities, see
pysros.syslog.Event.severity
- pysros.syslog.severity_to_name(severity)
Converts an event severity name into a syslog severity name.
- Parameters:
severity (str) – Event severity name.
- Returns:
Syslog severity name.
- Return type:
str
- Raises:
ValueError – for invalid severities, see
pysros.syslog.Event.severity
- pysros.syslog.get_system_name()
Retrieves the system name. This function is provided directly as part of the
pysros.syslog
module to provide enhanced performance for the syslog execution pathway.- Returns:
SR OS system name.
- Return type:
str
- class pysros.syslog.Event
The syslog
Event
class provides access to the header-fields of the messages, the individual fields of the event and the syslog-specific attributes.Note
The header-fields can be modified unless stated otherwise.
Any changes are reflected in the actual syslog-packet being sent out.
If a change of message format is required, for example, the ordering or the value of the field needs to change,
override_payload()
should be used to override the complete message. In this case, the actual message first needs to be formatted using theformat_msg()
function before it is passed to theoverride_payload()
function.- name
The name of the event.
- Type:
str
- appid
The name of the application that generated the event.
- Type:
str
- eventid
The event ID number of the application.
- Type:
int
- Raises:
ValueError – for negative values.
- severity
The severity level of the event. Valid values are:
none
cleared
indeterminate
critical
major
minor
warning
- Type:
str
- sequence
The sequence number of the event in the syslog collector.
- Type:
int
- Raises:
ValueError – for negative values.
- subject
The subject or affected object of the event.
- Type:
str
- router_name
The name of the SR OS router-instance (For example,
Base
) in which this event was triggered.- Type:
str
- gentime
The time, in ISO 8601 format, that the event was generated.
Note
Changes to
timestamp
are reflected in this attribute.- Type:
str, read-only
- timestamp
The time, in seconds, that the event was generated.
- Type:
float
- hostname
The hostname field of the syslog message. This can be an IP address, fully-qualified domain name (FQDN), or hostname.
- Type:
str
- log_prefix
The log-prefix inserted into the event message.
- Type:
str
- facility
The syslog facility code. A list of named values is provided in
pysros.syslog.Facility
.- Type:
int
- Raises:
ValueError – for values outside of the valid range [0..31]
- text
The event specific body formatted as a string. By default, this is generated from the
eventparameters
.This attribute can be modified to provide new event text.
This message may include values from the
eventparameters
function.- Type:
str
- eventparameters
The additional parameters specific to the event that caused the Python application to execute.
Note
The parameters returned cannot be modified to alter the generated event text. Instead, a new event text should be generated from the values and assigned to the
text
attribute.- Returns:
Event specific parameters. The parameters in this class are read-only.
- Return type:
- format_msg()
Return a string representation of the SR OS formatted log message.
- Returns:
SR OS formatted log message.
- Return type:
str
- format_syslog_msg()
Return a string representation of the SR OS formatted log message as it appears in the syslog packet. When any of the writable attributes on this event have been modified, the output of this function contains these changes.
- Returns:
SR OS formatted syslog message.
- Return type:
str
- override_payload(payload)
Provide a custom syslog message as it appears in the packet. This includes header information (facility, timestamp, etc.) and body data (the actual message).
Attributes from this event can be used to construct a completely new message format. Any prior changes to the values of these attributes are used.
- Parameters:
payload (str) – New syslog payload.
- Raises:
ValueError – when payload is larger than the maximum of 1023 bytes.
- drop()
Drop the syslog message from the send queue.
- class pysros.syslog.EventParams
The additional parameters of the specific
pysros.syslog.Event
. This class is read-only. Specific additional parameters may be accessed using standard Python subscript syntax.- keys()
Obtain the additional parameter names.
- Returns:
Additional parameter names for the event.
- Return type:
tuple(str)
- params[key]
Return the value of the parameter key. If the parameter does not exist, a
KeyError
is raised. key is of type str.
- iter(params)
Return an iterator for the key value pairs of parameters.
Where an iterator is expected, this object can be passed and the iterator is used implicitly. This can be used to collect all
pysros.syslog.Event.eventparameters
into a standard Python dict.Example use of the iterator for type conversion>>> list(event.eventparameters) [('key1', 'value1'), ('key2', 'value2'), ('key3', 'value3')] >>> params = dict(event.eventparameters) >>> type(params) <class 'dict'> >>> params {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}
- class pysros.syslog.Facility
Class similar to an Enum that defines constants that can be used as values for the
pysros.syslog.Event.facility
attribute.Note
No instances of this class can be instantiated.
- KERNEL = 0
- USER = 1
- MAIL = 2
- SYSTEMD = 3
- AUTH = 4
- SYSLOGD = 5
- PRINTER = 6
- NETNEWS = 7
- UUCP = 8
- CRON = 9
- AUTHPRIV = 10
- FTP = 11
- NTP = 12
- LOGAUDIT = 13
- LOGALERT = 14
- CRON2 = 15
- LOCAL0 = 16
- LOCAL1 = 17
- LOCAL2 = 18
- LOCAL3 = 19
- LOCAL4 = 20
- LOCAL5 = 21
- LOCAL6 = 22
- LOCAL7 = 23