Network Automation using YANG Models across XE, XR, & NX

Bonus Content - Python YANG Models with PyangBind

PyangBind is an addon to the Pyang family of tools that allow developers to create usable Python classes from source YANG datamodels. It is very similar to YDK in that you can take source YANG models and programattically generage usable Python classes to interact with those models. A full overview of the project can be found on the PyangBind GitHub page.

Install PyangBind

You may see some additional dependencies installed as part of the pyangbind installation.

        
            pip3.6 install pyangbind
        
    

Observe the installation:

        
[root@cfa2c7b31323 workspace]# pip3.6 install pyangbind
Collecting pyangbind
  Downloading https://files.pythonhosted.org/packages/2e/20/7b3f2de320d120e845bce141148a23522fccb089b76ae0c76b5d5623d515/pyangbind-0.8.1.tar.gz (48kB)
    100% |################################| 51kB 2.1MB/s
Requirement already satisfied: pyang in /usr/lib/python3.6/site-packages (from pyangbind) (1.7.5)
Collecting bitarray (from pyangbind)
  Downloading https://files.pythonhosted.org/packages/0a/da/9f61d28a20c42b4963334efacfd257c85150ede96d0cd2509b37da69da47/bitarray-0.8.1.tar.gz (46kB)
    100% |################################| 51kB 4.4MB/s
Requirement already satisfied: lxml in /usr/lib64/python3.6/site-packages (from pyangbind) (4.2.1)
Collecting regex (from pyangbind)
  Downloading https://files.pythonhosted.org/packages/a2/51/c39562cfed3272592c60cfd229e5464d715b78537e332eac2b695422dc49/regex-2018.02.21.tar.gz (620kB)
    100% |################################| 624kB 3.3MB/s
Requirement already satisfied: six in /usr/lib/python3.6/site-packages (from pyangbind) (1.11.0)
Collecting enum34 (from pyangbind)
  Downloading https://files.pythonhosted.org/packages/af/42/cb9355df32c69b553e72a2e28daee25d1611d2c0d9c272aa1d34204205b2/enum34-1.1.6-py3-none-any.whl
Installing collected packages: bitarray, regex, enum34, pyangbind
  Running setup.py install for bitarray ... done
  Running setup.py install for regex ... done
  Running setup.py install for pyangbind ... done
Successfully installed bitarray-0.8.1 enum34-1.1.6 pyangbind-0.8.1 regex-2018.2.21
[root@cfa2c7b31323 workspace]#
        
    

Environment Setup

After downloading and installing pyangbind with pip, we now need to setup some special environment variables that pyangbind needs so it knows the correct version of Python to use.

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

Clone the Openconfig Repository

For this exercise, we are going to clone the openconfig repository and attempt to build Python based classes from some of the interface models.

    
    git clone https://github.com/openconfig/public.git
    

This clones the open source Repository for publishing OpenConfig models, documentation, and other material for the community. We will use the raw .yang models inside here to create a usable Python class.

Python Class Generation

With the environment setup, we can now use pyangbind to programmatically generate Python classes based on a collection of YANG models. For this exercise, we want to generate a Python class that could later be used by NETCONF or other transport layer tooling to interact with the device using the YANG models similar to how we used YDK earlier in the lab.

Arguments

  1. --plugindir $PYBINDPLUGIN - The path to PYANGBIND determined by the export we ran earlier.
  2. -f pybind - The format specifier to go from .yang to .py
  3. -o openconfig-interfaces.py - The output .py file to create
We want to create an interfaces model, but in order to do that, we also need to include the dependencies used by the openconfig-interfaces model. Note that the ordering matters. If for example openconfig-interfaces.yang depends on openconfig-types.yang, then openconfig-types.yang must be supplied before openconfig-interfaces.yang.

Models Used
  1. ./public/release/models/openconfig-extensions.yang
  2. ./public/release/models/types/openconfig-yang-types.yang
  3. ./public/release/models/types/openconfig-types.yang
  4. ./public/release/models/interfaces/openconfig-interfaces.yang

Generate openconfig_interfaces.py

    
     pyang --plugindir $PYBINDPLUGIN -f pybind -o openconfig_interfaces.py ./public/release/models/openconfig-extensions.yang
    ./public/release/models/types/openconfig-yang-types.yang ./public/release/models/types/openconfig-types.yang ./public/release/models/interfaces/openconfig-interfaces.yang
    

It should take about 2 seconds to run and result in openconfig_interfaces.py placed in your current working directory.

Inspecting the Generated Class

The resultant openconfig_interfaces.py results in approximately 5000 lines of well documented and properly formatted Python. This is definately not something you would want to have to write by hand. As with YDK-Gen, pyangbind affords developers quick Python class and method generation mapping back to the source YANG models. A sample snippet of code relating to operating on an interfaces containers from our newly generated openconfig_interfaces.py:

        
        def _set_interfaces(self, v, load=False):
            """
            Setter method for interfaces, mapped from YANG variable /interfaces (container)
            If this variable is read-only (config: false) in the
            source YANG file, then _set_interfaces is considered as a private
            method. Backends looking to populate this variable should
            do so via calling thisObj._set_interfaces() directly.

            YANG Description: Top level container for interfaces, including configuration
        and state data.
            """
            if hasattr(v, "_utype"):
            v = v._utype(v)
            try:
            t = YANGDynClass(v,base=yc_interfaces_openconfig_interfaces__interfaces, is_container='container', yang_name="interfaces", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/interfaces', defining_module='openconfig-interfaces', yang_type='container', is_config=True)
            except (TypeError, ValueError):
            raise ValueError({
                'error-string': """interfaces must be of a type compatible with container""",
                'defined-type': "container",
                'generated-type': """YANGDynClass(base=yc_interfaces_openconfig_interfaces__interfaces, is_container='container', yang_name="interfaces", parent=self, path_helper=self._path_helper, extmethods=self._extmethods, register_paths=True, extensions=None, namespace='http://openconfig.net/yang/interfaces', defining_module='openconfig-interfaces', yang_type='container', is_config=True)""",
                })

            self.__interfaces = t
            if hasattr(self, '_set'):
            self._set()
        
    
A quick check with grep shows this file contains around 600 additional functions and getter/setter methods wrapping the YANG model contents. For additional details on using pyangbind in conjunction with NETCONF via ncclient, check out networkop.co.uk's simple guide.