Metadata-Version: 2.1
Name: umnet-ncs-instances
Version: 0.0.9
Summary: Python object representing NSO service or device instances.
Home-page: https://gitlab.umich.edu/its-inf-net/umnet-ncs-instances
Author: University of Michigan
Author-email: amylieb@umich.edu
License: UNKNOWN
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](https://developer.cisco.com/docs/nso/api/#!ncs-maagic/module-ncs-maagic).
        - `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.
        
        
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Requires-Python: >=3.6
Description-Content-Type: text/markdown
