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
- --plugindir $PYBINDPLUGIN - The path to PYANGBIND determined by the export we ran earlier.
- -f pybind - The format specifier to go from .yang to .py
- -o openconfig-interfaces.py - The output .py file to create
Models Used
- ./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
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.