Thursday, 14 July 2016

Python for Network Engineers - Part 5 - Using Junos NETCONF interface

In previous blog articles, we focused on using python to interact with REST APIs.  In the next few blog posts, we’ll look at NETCONF interfaces.  In this article, we’ll look at interacting with Juniper Junos devices using the ncclient Python module.

Blog Series

Python for Network Engineers - Part 1 - Introduction
Python for Network Engineers - Part 2 - Making REST calls
Python for Network Engineers - Part 3 - Using Cisco Nexus NX-API
Python for Network Engineers - Part 4 - Using Arista EOS eAPI
Python for Network Engineers - Part 5 - Using Junos NETCONF interface
Python for Network Engineers - Part 6 - Using Cisco Nexus NETCONF interface
Python for Network Engineers - Part 7 - Using Palo Alto Networks XML API


NETCONF background

The purpose of these articles is to get you automating very quickly with Python so I’m not going to go into a lot of depth here.  However, NETCONF is an IETF standard and is documented in RFC 6241.

Many vendors have implemented NETCONF interfaces including Cisco, Juniper, HP and Huawei.  There are standardised YANG data models from the IETF, OpenConfig and OpenDaylight as well as vendor-specific data models.  Please see the github site in the references section to get a copy of these data models.

In terms of NETCONF “controllers” then we can use ncclient inside python, OpenDaylight and a commercial offering from tail-f.  It should be noted that Tail-f was bought by Cisco and is at the heart of their Network Services Orchestrator (NSO) and Virtual Topology System (VTS) products.  This gives you an idea of how powerful NETCONF can be.

Specific to Juniper then there was some excellent blog articles written by Jeremy Schulman (Automaniac) and a “Junos EZ” Python module.  However much of the development in Junos EZ has been incorporated into ncclient so we will just use this library for this blog post.  The good thing about using Junos with NETCONF is that it is supported across all Junos devices (SRX, MX, EX, J Series) with the same data models so it’s very easy to use.

Junos NETCONF interface


For this example, I’m using a Junos vSRX and Ubuntu Linux with Python.   Please see the references section at the bottom for a link to vSRX download.

Junos Setup
On the Juniper device then all you need to do is enable the one command below.  You may also wish to make a dedicated user for accessing the device whilst scripting.
set system services netconf ssh
commit

We can test our Junos device is NETCONF capable by doing a simple SSH command from the Linux prompt:
james@ubuntu:~$ ssh root@192.168.229.11 netconf
root@192.168.229.11's password:
<!-- No zombies were killed during the creation of this user interface -->
<!-- user root, class super-user -->
<hello>
  <capabilities>
    <capability>urn:ietf:params:xml:ns:netconf:base:1.0</capability>
    <capability>urn:ietf:params:xml:ns:netconf:capability:candidate:1.0</capability>
    <capability>urn:ietf:params:xml:ns:netconf:capability:confirmed-commit:1.0</capability>
    <capability>urn:ietf:params:xml:ns:netconf:capability:validate:1.0</capability>
    <capability>urn:ietf:params:xml:ns:netconf:capability:url:1.0?protocol=http,ftp,file</capability>
    <capability>http://xml.juniper.net/netconf/junos/1.0</capability>
    <capability>http://xml.juniper.net/dmi/system/1.0</capability>
  </capabilities>
  <session-id>1336</session-id>
</hello>
]]>]]>

Once we get to this stage then our Junos device is ready to use NETCONF.

Python Setup
The first thing to do is to install the ncclient module and any dependencies.  From Ubuntu 16.04 then the following should be enough to get it up and running:
apt-get install python-pip
apt-get install libssl-dev libxml2-dev libxslt1-dev
pip install ncclient

We can then check ncclient is installed and check the version number at the bottom of the help page (this blogs is based on using ncclient version 0.5.2)
james@ubuntu:~$ python
Python 2.7.11+ (default, Apr 17 2016, 14:00:29)
[GCC 5.3.1 20160413] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import ncclient
>>> help(ncclient)


Example 1
In this first example we’re just going to create a session to the Junos device and grab the configuration into a string called “xml”.  From the Python interactive prompt:

from ncclient import manager
host = '192.168.229.11'
uname='root'
upass='root_password'
s = manager.connect(host=host, port=22, username=uname, password=upass, hostkey_verify=False, device_params={'name':'junos'})
xml = s.get_config(source='running').data_xml
print xml

The first thing we notice is that the data we get back is in XML format.  If we install “xmltodict” with pip then we can work with the data in an easier way within Python.
import xmltodict, json
d = xmltodict.parse(xml)
print json.dumps(d, indent=2)

Now we have the same data in a dictionary object called "d".  To show we you a few examples of what we can do, next we will drill down to see all the keys under the configuration section, print that section and then pull out a specific value from the output.
d['rpc-reply']['data']['configuration'].keys()
print json.dumps(d['rpc-reply']['data']['configuration'], indent=2)
print d['rpc-reply']['data']['configuration']['system']['host-name']

Example 2
In the last example, we used a standard NETCONF function “get-config” which is part of the IETF data model and documented in the RFC.  However, for this example, we’re going to use some Junos specific calls to run operational mode commands (i.e. same command you would run on a Junos command prompt).  By specifying the device_params parameter we tell ncclient that it’s a Junos device and to enable this functionality.

We will use “s” as our session object and reply data will be stored in “r”:
from ncclient import manager
import xmltodict, json
host = '192.168.229.11'
uname='root'
upass='root_password'
s = manager.connect(host=host, port=22, username=uname, password=upass, hostkey_verify=False, device_params={'name':'junos'})
r = s.command(command='show system users')
d = xmltodict.parse(r.tostring)['rpc-reply']
print json.dumps(d, indent=2)

We can then repeat this for any operational level commands we want and parse the output however we wish.  For example:
r = s.command(command='show version')
print json.dumps(xmltodict.parse(r.tostring), indent=2)
r = s.command(command='show interfaces')
print json.dumps(xmltodict.parse(r.tostring), indent=2)

Example 3
In this last example, we will make changes to the configuration and commit them.  We will assume you have already connected to the Junos device and created your session object “s” as per the last example.
commandList = ['set interfaces lo0 unit 99 family inet address 100.64.0.1/32']
commandList += ['set routing-instances RED instance-type vrf']
commandList += ['set routing-instances RED interface lo0.99']
s.lock()
s.load_configuration(action='set', config=commandList)
s.commit()
s.unlock()

If we are doing this in a script then we want to capture the output of each of the last four commands and check they completed correctly.  However for this blog article we are running it interactively so we can see if any errors are generated and we can just check the configuration on the Junos device and see easily if the configuration was applied correctly or not.

Next Article
In the next article, we’ll see how you can use NETCONF on Cisco Nexus devices.  Similarly to Junos, we will be able to just send show and configuration level commands with ease!

Resources


NETCONF RFC

Githib for Python NETCONF module and YANG models

Juniper vSRX download

Juniper NETCONF resources

About the Author

The author of this blog works for Vanguard IT who provide a range of professional services and managed services

For more information go to https://vanguard-it.net

No comments:

Post a Comment