Tutorial

Here are some basic usage examples of ncdiff. They are organized in the sequence of a typical use case - connect device, load models, get or get-config, and edit-config.

connect to a Netconf device

Similar to ncclient, prepare Netconf connection and create an instance of ModelDevice:

>>> from ncdiff import manager
>>> m = manager.connect(host='2.3.4.5', port=830,
                        username='admin', password='admin',
                        hostkey_verify=False, look_for_keys=False)
>>> m
<ncdiff.manager.ModelDevice object at 0xf516316c>
>>> m.raise_mode = 0
>>>

Note

raise_mode is an attribute of ncclient Manager that defines exception raising mode. When raise_mode = 0, RPCError exceptions are not raised if there is an rpc-error in replies.

Set timeout if needed:

>>> m.timeout = 120
>>> m.timeout
120
>>>

Download and scan models:

>>> m.scan_models()
...
>>>

Note

By default, a folder ./yang will be created to accommodate YANG files downloaded.

load models

Find what models are available:

>>> m.models_loadable
['BGP4-MIB', 'BRIDGE-MIB', ...]
>>>

Load multiple models depending on your testing requirement:

>>> m1 = m.load_model('Cisco-IOS-XE-native')
>>> m2 = m.load_model('openconfig-interfaces')
>>> m3 = m.load_model('openconfig-network-instance')
>>>

Print out model tree:

>>> print(m1)
module: Cisco-IOS-XE-native
    +--rw native
       +--rw default
       |  +--rw crypto
       |     +--rw ikev2
       |        +--rw proposal?   empty
       |        +--rw policy?     empty
...
>>>

If you forget what models are loaded, check attribute ‘models_loaded’:

>>> m.models_loaded
['Cisco-IOS-XE-native', 'cisco-ia', 'openconfig-interfaces', 'openconfig-network-instance']
>>>

get

Since ModelDevice is a sub-class of ncclient Manager, it supports get, get-config, edit-config, and all other methods supported by ncclient. On top of that, yang.ncdiff adds a new argument ‘models’ to method get() and get_config():

>>> reply = m.get(models='openconfig-network-instance')
>>> assert(reply.ok)
>>> print(reply)
...
>>>

You can even pull operational data or config from multiple models. For example:

>>> reply = m.get(models=['openconfig-interfaces',
                          'openconfig-network-instance'])
>>> assert(reply.ok)
>>> print(reply)
...
>>>

get-config

Config state can be captured by ModelDevice method extract_config():

>>> reply = m.get_config(models=['openconfig-interfaces',
                                 'openconfig-network-instance'])
>>> assert(reply.ok)
>>> config1 = m.extract_config(reply)
>>> print(config1)
<nc:config xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
  <interfaces xmlns="http://openconfig.net/yang/interfaces">
...
>>>

edit-config

Assume there are two instances of Config: config1 and config2. Make sure they are different:

>>> config1 == config2
False
>>> delta = config2 - config1
>>> print(delta)
<nc:config xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
  <system xmlns="http://openconfig.net/yang/system">
    <aaa>
      <server-groups>
        <server-group>
          <name>ISE1</name>
          <config>
            <name>ISE1</name>
            <type xmlns:oc-aaa="http://openconfig.net/yang/aaa">oc-aaa:RADIUS</type>
          </config>
        </server-group>
      </server-groups>
    </aaa>
  </system>
</nc:config>
>>>

If the current config state is config2, a Netconf transaction to config1 can be achieved by an edit-config ‘-delta’:

>>> reply = m.edit_config(target='running', config=(-delta).nc)
INFO:ncclient.operations.rpc:Requesting 'EditConfig'
>>> assert(reply.ok)
>>>

Hey, check your device, its config should be config1 now!

>>> reply = m.get_config(models='openconfig-system')
INFO:ncclient.operations.rpc:Requesting 'GetConfig'
>>> config = m.extract_config(reply)
>>> config == config1
True
>>>

Want to switch back to config2? No problem! Send ‘delta’:

>>> reply = m.edit_config(target='running', config=delta.nc)
INFO:ncclient.operations.rpc:Requesting 'EditConfig'
>>> assert(reply.ok)
>>>
>>> reply = m.get_config(models='openconfig-system')
INFO:ncclient.operations.rpc:Requesting 'GetConfig'
>>> config = m.extract_config(reply)
>>> config == config2
True
>>>

Section author: Jonathan Yang