Netconf Python ncclient

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.

  1. “get” request using filter to display configuration.
  2. “edit-config” request to change configuration.
  3. “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.

References:

Advertisements

6 thoughts on “Netconf Python ncclient

  1. 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

  2. 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.

  3. 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)

  4. 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

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s