In my earlier blogs, I had covered basics of Netconf and Yang and how to use Netconf to configure Cisco devices. Recently, I came across this Python ncclient library that simplifies the configuration/monitoring of Networking devices that supports Netconf. Using ncclient library, we can programmatically configure and monitor devices using Netconf. I also found out that Cisco Openstack Neutron plugin uses ncclient library to program the Nexus switches.
I have used Cisco Nexus 3k switch and Cisco VIRL NXOS switch for the examples in this blog.
In my earlier blog on configuring Cisco Nexus devices using Netconf, I covered the following netconf requests.
- “get” request using filter to display configuration.
- “edit-config” request to change configuration.
- “exec-command” to execute raw CLI requests.
In this blog, I will cover the above same tests using Python ncclient library. Even though the examples below are tried from Python interactive shell, the same can be executed as a Python program as well.
First step is to import the ncclient library and create a connection:
>$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ncclient import manager
>>> cisco_manager = manager.connect(host='ip',
... port=22,
... username='admin',
... password='pwd',
... hostkey_verify=False,
... device_params={'name': 'nexus'},
... allow_agent=False,
... look_for_keys=True
... )
>>>
Example below illustrates a vlan filter and “ncclient.get” request using the vlan filter. Based on the type of filter, we get the appropriate result and these results can be parsed using xml parser libraries.
>>> vlans_filter = """
...
...
...
...
... """
>>> vlan_list = cisco_manager.get(('subtree', vlans_filter))
>>> vlan_list
1
1
default
active
.
.
105
enet
ce-vlan
Following is an example of modifying configuration using “ncclient.edit-config” to create vlan 107.
>>> cmd_vlan_conf_snippet= """ ... ... ... 107 ... ... ... vlan107 ... ... ... active ... ... ... ... ... ... ... ... """ >>> >>> exec_conf_prefix = """ ... ... ... ... """ >>> >>> exec_conf_postfix = """ ... ... ... ... """ >>> >>> >>> cisco_manager.edit_config(target='running', config=exec_conf_prefix + cmd_vlan_conf_snippet + exec_conf_postfix)
In ncclient 0.4.3 version, “exec-command” option was introduced where we can pass CLI directly and get output in XML format.
Following is an example of “ncclient.exec_command” to show all vlans.
>>> command={"show vlan"}
>>> cisco_manager.exec_command(command)
1
1
default
.
.
105
enet
ce-vlan
Following is an example to create vlan using “ncclient.exec_command”
>>> command1={'configure terminal', 'vlan 109'}
>>> cisco_manager.exec_command(command1)
I found quite a few weird stuff with Netconf and ncclient.
With raw exec-command, I found that more than 2 commands in a line did not work and I had to place the commands in separate lines:
application
invalid-value
error
Syntax error while parsing ' vlan 109; name vlan109'
]]>]]>
configure terminal ; vlan 109
name vlan109
]]>]]>
With “ncclient.exec_command”, more than 2 commands in a line did not work. I could not find a way to workaround this.
configure terminal ; vlan 109; name vlan109
]]>]]>
>>> command1={'configure terminal', 'vlan 109', 'name vlan109'}
>>> cisco_manager.exec_command(command1)
Traceback (most recent call last):
File "", line 1, in
File "/usr/local/lib/python2.7/dist-packages/ncclient/manager.py", line 166, in wrapper
return self.execute(op_cls, *args, **kwds)
File "/usr/local/lib/python2.7/dist-packages/ncclient/manager.py", line 226, in execute
raise_mode=self._raise_mode).request(*args, **kwds)
File "/usr/local/lib/python2.7/dist-packages/ncclient/operations/third_party/nexus/rpc.py", line 13, in request
return self._request(node)
File "/usr/local/lib/python2.7/dist-packages/ncclient/operations/rpc.py", line 308, in _request
raise self._reply.error
ncclient.operations.rpc.RPCError: Syntax error while parsing 'name vlan109'
“ncclient.get_config” failed, I think thats expected because Cisco does not seem to support it.
>>> cisco_manager.get_config(source='running').data_xml
Traceback (most recent call last):
File "", line 1, in
File "/usr/local/lib/python2.7/dist-packages/ncclient/manager.py", line 156, in wrapper
return self.execute(op_cls, *args, **kwds)
File "/usr/local/lib/python2.7/dist-packages/ncclient/manager.py", line 226, in execute
raise_mode=self._raise_mode).request(*args, **kwds)
File "/usr/local/lib/python2.7/dist-packages/ncclient/operations/retrieve.py", line 87, in request
return self._request(node)
File "/usr/local/lib/python2.7/dist-packages/ncclient/operations/rpc.py", line 308, in _request
raise self._reply.error
ncclient.operations.rpc.RPCError: Operation not supported
The power of Netconf comes from the transactional capabilities of the protocol where we need to do Network wide configuration and by using a model to represent configuration. For individual device configuration, I see Netconf adds more programming complexity and NXAPI is much more easier to use when compared to Netconf.
Hi Sreenivas
I am trying to execute one of my router commands via ncclient but following error is thrown. Can you please help on what might be the problem.
Normal on router:
R1:~$ ping 127.0.0.1 count 5
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.050 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.053 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.056 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.056 ms
64 bytes from 127.0.0.1: icmp_seq=5 ttl=64 time=0.061 ms
— 127.0.0.1 ping statistics —
5 packets transmitted, 5 received, 0% packet loss, time 3997ms
rtt min/avg/max/mdev = 0.050/0.055/0.061/0.006 ms
From ncclient:
>>> command={“ping 127.0.0.1 count 5”}
>>> abc.exec_command(command)
Traceback (most recent call last):
File “”, line 1, in
File “/usr/local/lib/python2.7/dist-packages/ncclient/manager.py”, line 258, in _missing
sub_ele(root, arg)
File “/usr/local/lib/python2.7/dist-packages/ncclient/xml_.py”, line 181, in
sub_ele = lambda parent, tag, attrs={}, **extra: etree.SubElement(parent, qualify(tag), attrs, **extra)
File “lxml.etree.pyx”, line 2935, in lxml.etree.SubElement (src/lxml/lxml.etree.c:67055)
File “apihelpers.pxi”, line 181, in lxml.etree._makeSubElement (src/lxml/lxml.etree.c:15299)
File “apihelpers.pxi”, line 1575, in lxml.etree._tagValidOrRaise (src/lxml/lxml.etree.c:28606)
ValueError: Invalid tag name u”set([‘ping 127.0.0.1 count 5’])”
Regards
Phani
does any other exec command like vlan configure work?
is this a Cisco switch?
No Sreenivas, no commands are working. We are using vyatta product.
Thanks for blog, it’s useful.
I found that I can execute conf t commands OK with the below syntax on NX-OS 7.2 using ncclinet 0.4.3:
conn = manager.connect(host=host, port=22, username=uname, password=upass, hostkey_verify=False, device_params={‘name’:’nexus’})
conn.exec_command({‘configure terminal ; vlan 20 ; name PYTHON_TEST’})
But it may vary with other versions / platforms. I will continue to test out different scenarios.
Use the following with exec_command if ncclient will not work as expected with more than 2 arguments:
commando = [‘configure terminal’, ‘interface ethernet 1/7′,’description MICHEL’]
result = m.exec_command(commando)
Hi Yagna/Sreenivas,
I’m hitting the same issue as yours. I’m seeing invalid tag name error when I’m trying to send a netconf edit request using ncclient edit_config API. Can you please share your thoughts and any solution that worked for you. Appreciate your help.
Thanks,
Veena