Now that we seen how to enable NETCONF/ YANG on the 9800, how to use the Advanced Netconf Explorer to view/ test calls to the controller, lets look at doing this with Python.
So first you need to have Python installed. If you don’t have it installed check out this https://realpython.com/installing-python or one of the many other guides available with a quick Google search.
Now we are going to need to install the “ncclient” package. This is the package that will give us a NETCONF client to use to connect to the 9800.
pip install ncclient
Now we will create the python program (use your favourite text editor, I like Sublime Test). We will call this file “netconf-9800.py”.
At the top of the file we will import the dependencies we will utilise.
'''------------------------------------------------------------------
Filename: netconf-9800.py
author: Haydn Andrews
date: 13/07/2020
desc:
modification history:
what when who why
v1.0 13/07/2020 HA Initial version
-------------------------------------------------------------------'''
#Import Dependencies
from ncclient import manager
from jinja2 import Template
We will then setup the NETCONF Session to the 9800 using the “connect” method from “ncclient”
# NETCONF Connection Manager
m = manager.connect(host='10.0.0.10', port=830, username='admin',
password='P@ssword1', device_params={'name': 'csr'})
So we have see what data we can get from the Advanced Netconf Explorer (ANX) and which Netconf call we need to use. For this example we will use the “http://cisco.com/ns/yang/Cisco-IOS-XE-wireless-access-point-oper” model.
But rather than just getting back all the data, lets do a subset for an AP with a Ethernet MAC address of 70:69:5a:74:8b:5c
# Create a filter
interface_filter = '''
<filter>
<access-point-oper-data xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-wireless-access-point-oper">
<ap-name-mac-map>
<eth-mac>70:69:5a:74:8b:5c</eth-mac>
</ap-name-mac-map>
</access-point-oper-data>
</filter>
'''
# Execute the netconf get
result = m.get(interface_filter)
print(result)
The program returns the XML data for this MAC address (for ease of reading i have formatted the XML)
<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply
xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:80d0a289-b84b-43ee-85d7-72582cc1b5fd"
xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
<data>
<access-point-oper-data
xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-wireless-access-point-oper">
<ap-name-mac-map>
<wtp-name>APname01</wtp-name>
<wtp-mac>f8:0f:6f:15:27:e0</wtp-mac>
<eth-mac>70:69:5a:74:8b:5c</eth-mac>
</ap-name-mac-map>
</access-point-oper-data>
</data>
</rpc-reply>
So now you have successfully made your first NETCONF call to a 9800 from Python now what?
Well first thing is do we want to create a filter for each Ethernet MAC address we want some data for? Secondly the model for some reason uses the wtp-mac address for all smaller calls so lets look at using a Jinja tempalte to allow us to replace variables.
What we are going to do is replace the Ethernet MAC address with a variable. Jinja uses double curly braces syntax to define a variable. So to do this we create a file called EthernetMacfilter.xml
<filter>
<access-point-oper-data
xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-wireless-access-point-oper">
<ap-name-mac-map>
<eth-mac>{{ MAC_ADDRESS}}</eth-mac>
</ap-name-mac-map>
</access-point-oper-data>
</filter>
Now we go back to the python program and update it to use the Jinja template
#Mac Address Variable / Static for the demo but could be called from CSV/ JSON or something else
MACAddress = '70:69:5a:74:8b:5c'
# Render Jinja Template
Ethernetmac_template = Template(open('EthernetMacfilter.xml').read())
Ethernetmac_rendered = Ethernetmac_template.render(
MAC_ADDRESS= MACAddress,
)
# Execute the netconf get
result = m.get(Ethernetmac_rendered)
print(result)
And we get the same output as before:
<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply
xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:d4297f93-aa05-4531-a97f-dc221596331d"
xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
<data>
<access-point-oper-data
xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-wireless-access-point-oper">
<ap-name-mac-map>
<wtp-name>APname01</wtp-name>
<wtp-mac>f8:0f:6f:15:27:e0</wtp-mac>
<eth-mac>70:69:5a:74:8b:5c</eth-mac>
</ap-name-mac-map>
</access-point-oper-data>
</data>
</rpc-reply>
Ok so we have a bunch of XML data coming back what can we do with it? Well as its formatted data, we can extract fields so we could get the AP name for instance.
For this we are going to have to import another dependancy called xml.dom.minidom
import xml.dom.minidom
And then we update our program to extract the AP name from the returned data from the previous call. So we add following to the bottom of the program
#Extract the AP name value from the returned result
xml_doc = xml.dom.minidom.parseString(result.xml)
RadioMAC = xml_doc.getElementsByTagName("wtp-name")
APName = RadioMAC[0].firstChild.nodeValue
print(APName)
This will return the AP name of APname01.
By changing the value of “wtp-name” to “wtp-mac” we could get the radio MAC address. You can then do with that value what you like.
Up next we will look at using NETCONF / YANG to update config on the 9800.
Also worth keeping in mind that these same steps with different models can be applied to other devices like the Cat 9k switches and any other vendor/ device that supports NETCONF/ YANG.
following this step on c9840 wlc, I met an error information:
raise SSHError(“Could not open socket to %s:%s” % (host, port))
ncclient.transport.errors.SSHError: Could not open socket to 10.124.55.34:830
============================================
Through CRT I can ssh with port 830, and :
confd : Running
nesd : Running
syncfd : Running
ncsshd : Running
dmiauthd : Running
nginx : Running
ndbmand : Running
pubd : Running
gnmib : Not Running
Is there something I can check?
LikeLike
Seams this is broken with the newest 9800 fw ,
I just get
ncclient.operations.rpc.RPCError:
and more errors
LikeLike
It doesn’t surprise me that something broke with a the newer versions. When I get some time I will did around and find the fix.
LikeLike