Skip to main content

Python object representing NSO service or device instances.

Project description

Problem Statement

UMnet's goal is to represent our entire network configuration in NSO. As of Nov 2021, our current network configuration lives in rancid backups, TopologyWalker files, Netinfo, Equipdb, and a few other places. We need some way to get this data from all these sources and use it to populate NSO.

After NSO is populated, we will still need ways to create data objects in python that are structured appropriately for NSO to ingest (for example, in Netsplash).

Solution Details

This package contains a set of classes that represent NSO objects designed by UMnet (services, actions, etc). When you import these classes into your python code, you can work with them similar to how you can work with NSO's high level python API. When you're done you can generate XML using the gen_xml() method.

  • types.py has the basic classes that emulate NSO's maagic python api.
  • instances.py has instance classes that represent specific UMnet NCS instances.

When an NCSInstance object is initialized in code, its structure is set via the initializer. __setattr__ has been overloaded for all of the object types such that you can't change the structure of the object or the types post-initialization. What you can do is:

  • Set a Leaf value (value must match the type specificed during initialization)
  • Append a value to a LeafList (same type restriction applies)
  • Set the choice for a Choice object (via the "choose" method)
  • Add an entry to a List as you would to a dict.

You can also read these values after setting them in your code for validation purposes. Just like with the maagic API you can read a Leaf directly. A LeafList behaves like a python list, and a List behaves like a dict.

An Example

Here is how a device instance is represented in instances.py.

class Device(NCSInstance):

    _path = "/config/devices/device"

    _nsmap = {
            "config":"http://tail-f.com/ns/config/1.0",
            "devices":"http://tail-f.com/ns/ncs",
            }

    _xml_munge = {
        r'<ned-id>(.+)</ned-id>':'<ned-id xmlns:\g<1>="http://tail-f.com/ns/ned-id/\g<1>">\g<1></ned-id>'
    }

    def __init__(self):

        self.name = Leaf(str)
        self.address = Leaf(str)
        self.authgroup = Leaf(str, value="default")
        self.state = Container()
        self.state.admin_state = Leaf(str, value="unlocked")
        self.device_type = Choice(['cli','netconf'])
        self.device_type.cli = Container()
        self.device_type.netconf = Container()
        self.device_type.cli.ned_id = Leaf(str)
        self.device_type.netconf.ned_id = Leaf(str)
        self.in_band_mgmt = Container()
        self.in_band_mgmt.set_ns("http://umnet.umich.edu/umnetcommon")
        self.in_band_mgmt.ip_address = Leaf(str)
        self.in_band_mgmt.interface = Leaf(str)

Here is some basic python code that creates a new device.

from umnet_ncs_instances import Device

device = Device()
device.name = "d-ARBL-1"
device.addresss = "198.108.10.4"
device.in_band_mgmt.ip_address = "198.108.10.4"
device.in_band_mgmt.interface = "Loopback0"
device.device_type.choose("cli")
device.device_type.cli.ned_id = "cisco-ios-cli-6.73"
print(device.gen_xml())

When you run the code above, here is what you'll get:

(venv) bash-3.2$ python test.py
<config xmlns="http://tail-f.com/ns/config/1.0">
  <devices xmlns="http://tail-f.com/ns/ncs">
    <device>
      <name>d-ARBL-1</name>
      <address>198.108.10.4</address>
      <authgroup>default</authgroup>
      <state>
        <admin-state>unlocked</admin-state>
      </state>
      <cli>
        <ned-id xmlns:cisco-ios-cli-6.73="http://tail-f.com/ns/ned-id/cisco-ios-cli-6.73">cisco-ios-cli-6.73</ned-id>
      </cli>
      <in-band-mgmt xmlns="http://umnet.umich.edu/umnetcommon">
        <ip-address>198.108.10.4</ip-address>
        <interface>Loopback0</interface>
      </in-band-mgmt>
    </device>
  </devices>
</config>

Why do it this way?

There are many ways to accomplish this task, almost all of which wouldn't require you to manually re-define yang objects as python classes as we're doing here. Our goal with this repo is to create objects representing NSO instances that:

  1. Can be used in code anywhere, without requiring access to an instance of NSO running UMnet packages.
  2. Are easy to understand/manipulate and provide a similar experience as working with service objects generated by NSO's high level python API.
  3. Don't require compiling yang files.
  4. Generate xml that can be used in an RPC call or manually ingested by NSO.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

umnet_ncs_instances-0.0.22.tar.gz (11.3 kB view details)

Uploaded Source

File details

Details for the file umnet_ncs_instances-0.0.22.tar.gz.

File metadata

  • Download URL: umnet_ncs_instances-0.0.22.tar.gz
  • Upload date:
  • Size: 11.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.0 CPython/3.9.1

File hashes

Hashes for umnet_ncs_instances-0.0.22.tar.gz
Algorithm Hash digest
SHA256 fcaa5a50c8140934b5707c22e73f73e35c0462cb242f4b1d2892a0bfff679359
MD5 9cf7a647cc7d5687706f135376eeb960
BLAKE2b-256 19e0ba0c50d170fcc2f7893494e5e81992b1bc32d4b99ec9a61948f8bb7d4a6d

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page