How to Configure a Cisco CSR using NETCONF/YANG

Introduction

Within this tutorial we will use NETCONF and YANG to configure an interface upon a Cisco CSR router using a combination of Python and the BASH CLI.

Furthermore we will use 2 main tools – Pyang and Pyangbind. Before we start lets have a quick overview on what these tools do,

Pyang is a YANG validator, transformator and code generator, written in python. It can be used to validate YANG modules for correctness, to transform YANG modules into other formats, and to generate code from the modules.
https://github.com/mbj4668/pyang

PyangBind is a plugin for Pyang that generates a Python class hierarchy from a YANG data model. The resulting classes can be directly interacted with in Python.
https://github.com/robshakir/pyangbind

Environment

Before we start there are a few things we need to cover.

Enable NETCONF/YANG

First of all NETCONF and YANG must be enabled. To do so, simply enter the following,

csr1000v(config)# netconf-yang

Dependencies

The following Python modules will also need to be installed.

sudo pip install ncclient pyang pyangbind
sudo pip install git+https://github.com/rickd3/commontools.git

Steps

We will now guide you through the various steps required in updating the CSR using NETCONF/YANG. To summarize the steps,

  1. First the capabilities of the device are confirmed. In other words we clarify what models and YANG operations are supported by the device.
  2. A NETCONF session is established to the device (via the ncclient module).
  3. The capabilities of the device retrieved.
  4. The YANG model that we will be using is reviewed for any imports. All YANG models are then saved as individual files.
  5. Pyangbind is then used to create a Python binding file to provide a Python (class) representation of the model within Python (when imported).
  6. The Pybind file is then imported into Python and worked upon. Applying the required changes to our model. The model is then saved to file as JSON.
  7. The JSON file is reconverted to XML, then applied to the device via NETCONF.
  8. Finally, the changes are confirmed.

Confirm Capabilities

The first thing in the workflow of NETCONF and YANG is to confirm the device capabilities and supported YANG models.

from file import read_file, write_file
from ncclient import manager

m = manager.connect(host='10.29.1.110', port=830, username='cisco',
                    password='cisco', device_params={'name': 'csr'})

for c in m.server_capabilities:
    print c

...
urn:ietf:params:xml:ns:yang:smiv2:SNMP-FRAMEWORK-MIB?module=SNMP-FRAMEWORK-MIB&revision=2002-10-14

urn:ietf:params:xml:ns:yang:cisco-policy-target?module=cisco-policy-target&revision=2016-03-30
urn:ietf:params:xml:ns:yang:smiv2:CISCO-CBP-TARGET-TC-MIB?module=CISCO-CBP-TARGET-TC-MIB&revision=2006-03-24
urn:ietf:params:netconf:capability:notification

Gather YANG Models

Confirm Imports

The model that we will use to config the interface will be ietf-ip.  However we must also check for any imports. What is an import? As defined by RFC 6020, it is,

The “import” statement makes definitions from one module available inside another module or submodule.

We can do this by printing the YANG modules schema. Like so,

print m.get_schema('ietf-ip') 

...

import ietf-interfaces {
   prefix if;
 }
 import ietf-inet-types {
   prefix inet;
 }
 import ietf-yang-types {
   prefix yang;
 }

Save YANG Models

After confirming all of the YANG models that are required, we save each model to a file.

yang_models = ["ietf-interfaces", "ietf-inet-types", "ietf-yang-types"]

for model in yang_models:
    schema = m.get_schema(model)
    write_file(schema.data, "{}.yang".format(model))

Build Python Binding

We will now build the Python YANG binding, which is done via the PyandBind plugin for pyang. PyangBind is a plugin for Pyang that generates a Python class hierarchy from a YANG data model. Interaction to resulting classes can then be performed within Python.

First, let us define the path of PyangBind as an environment variable.

$ export PYBINDPLUGIN=`/usr/bin/env python -c \
	'import pyangbind; import os; print "%s/plugin" % os.path.dirname(pyangbind.__file__)'`
$ echo $PYBINDPLUGIN

We then run Pyang, using the Pyangbind module. Within the command we set the file type, the output filename and the YANG models we are ingesting.

$ pyang --plugindir $PYBINDPLUGIN -f pybind -o ietf_ip_binding.py ietf-ip.yang ietf-interfaces.yang ietf-inet-types.yang

Model Changes

Now that we have our Python binding, we can import this and work upon the model using the standard Python features.

First we import the binding,

from ietf_ip_binding import ietf_interfaces
from pprint import pprint

model = ietf_interfaces()
model.get()

...

{'interfaces-state': {'interface': OrderedDict()}, 'interfaces': {'interface': OrderedDict()}}

Lets add an interface to the model,

interface_ge3 = model.interfaces.interface.add('GigabitEthernet3')
pprint(interface_ge3.get())

...

{'description': u'',
 'enabled': True,
 'ipv4': {'address': OrderedDict(),
          'enabled': True,
          'forwarding': False,
          'mtu': 0,
          'neighbor': OrderedDict()},
 'ipv6': {'address': OrderedDict(),
          'autoconf': {'create-global-addresses': True,
                       'create-temporary-addresses': False,
                       'temporary-preferred-lifetime': 86400L,
                       'temporary-valid-lifetime': 604800L},
          'dup-addr-detect-transmits': 1L,
          'enabled': True,
          'forwarding': False,
          'mtu': 0L,
          'neighbor': OrderedDict()},
 'link-up-down-trap-enable': u'',
 'name': u'GigabitEthernet3',
 'type': u''}

Great. Lets make some changes to the interface (add ip/mask and admin down),

interface_ge3.enabled = False
interface_ge3_addr = interface_ge3.ipv4.address.add('2.2.2.2')
interface_ge3_addr.netmask = '255.255.0.0'

pprint(interface_ge3.get())

...

{'description': u'',
  'enabled': False,
  'ipv4': {'address': OrderedDict([('2.2.2.2', {'ip': u'2.2.2.2', 'netmask': u'255.255.0.0', 'prefix-length': 0})]),
           'enabled': False,
           'forwarding': False,
           'mtu': 1460,

This model is then saved back into a file. Please note : Pyang currently only supports JSON as a data type for export.

import pyangbind.lib.pybindJSON as pybindJSON
from file import read_file, write_file

json_data = pybindJSON.dumps(model, mode='ietf')
write_file(json_data, "interface_ge3.json")

Apply Changes

Before we apply the changes, we must convert our JSON YANG model back to XML. Like so,

pyang -f jtox -o interface.jtox ietf-ip.yang ietf-interfaces.yang ietf-inet-types.yang ietf-yang-types.yang
json2xml -t config -o interface_ge3.xml interface.jtox interface_ge3.json

Now that we have the YANG model as XML, we use NETCONF to perform the <edit-config> operation upon the device, which will apply the changes into our requested datastore (running).

from file import read_file, write_file
from ncclient import manager

m = manager.connect(host='10.29.1.110', port=830, username='cisco',
                    password='cisco', device_params={'name': 'csr'})

xml = read_file("interface_ge3.xml")
if m.edit_config(target='running', config=xml):
    print "success"
else:
    print "unsuccessful"

m.close_session()

Confirm Changes

To confirm our changes have been made we can go onto the device and issue a show run against the interface.

csr1000v#show run interface GigabitEthernet3
Building configuration...

Current configuration : 147 bytes
!
interface GigabitEthernet3
 description to iosv-1
 ip address 2.2.2.2 255.255.0.0
 shutdown
 negotiation auto
 no mop enabled
 no mop sysid
end

References

http://networkop.co.uk/blog/2017/01/25/netconf-intro/

Rick Donato

Want to become a networking expert?

Here is our hand-picked selection of the best courses you can find online:
Cisco CCNA 200-301 Certification Gold Bootcamp
Complete Cyber Security Course – Network Security
Internet Security Deep Dive course
Python Pro Bootcamp
and our recommended certification practice exams:
AlphaPrep Practice Tests - Free Trial