ncclient
Python

ncclient

In this module, you are going to use a Python library called ncclient to map the L2VNI you created previously to the NVE (VTEP) interface. Coincidentally, the Ansible netconf_config and netconf_get modules that you used in the previous module actually leverage the ncclient library to perform their respective NETCONF tasks.


Step 1 - Create New Python File

Create a new Python file in the nxapilab directory.


cd /home/pod03/workspace/nxapilab
touch /home/pod03/workspace/nxapilab/nx_ncclient_config.py
code-server -r /home/pod03/workspace/nxapilab/nx_ncclient_config.py

    

Step 2 - Import the ncclient Connection Manager

The ncclient library is like any other package in Python; it must be imported, or particular methods must be imported. Below, you are going to import the ncclient connection manager that handles the connections to NETCONF-enabled devices. Either copy or type the import statements below and place them at the top of your Python file.


from ncclient import manager
from ncclient.xml_ import to_ele


Step 3 - Create Main Function

Like the previous Python scripts you have written in this lab, below is the main function of the program. A list of dictionaries is used for the device connectivity information found at line 10. Line 14 uses a loop for iterating over the device list. Lines 16-19 instantiate an ncclient manager object for each device using the information found in the device dictionary. Lines 22-43 are the XML RPC payloads. These are similar to the XML templates created in the previous Ansible NETCONF section, but here configured for a new VLAN 17 / VNI 10017 mapping. The script sends three configuration RPCs: VLAN-to-VNI mapping, NVE interface VNI, and EVPN. Lastly, the edit-config operation is a method provided by the ncclient connection manager object that is created as m. The connection manager object takes two arguments: the RPC payload and the target datastore.


def main():
    """
    Main method that prints netconf capabilities of device.
    """
    # Device dictionary to use
    devices = [
        {"ip": "10.15.3.21", "port": "830", "platform": "nexus",},
        {"ip": "10.15.3.22", "port": "830", "platform": "nexus",}
    ]
    for device in devices:
        # ncclient manager instantiation for nexus
        with manager.connect(host=device['ip'], port=device['port'], username='admin',
                                password='cisco.123', hostkey_verify=False,
                                device_params={'name': device['platform']},
                                look_for_keys=False, allow_agent=False) as m:

            # VLAN VNI Mapping RPC
            vlan_vni_rpc = '''
                    <config>
                    <System xmlns="http://cisco.com/ns/yang/cisco-nx-os-device">
                        <bd-items>
                        <bd-items>
                            <BD-list>
                            <fabEncap>vlan-17</fabEncap>
                            <accEncap>vxlan-10017</accEncap>
                            </BD-list>
                        </bd-items>
                        </bd-items>
                    </System>
                    </config>
                    '''

            # NVE Interface RPC
            nve_rpc = '''
                    <config>
                    <System xmlns="http://cisco.com/ns/yang/cisco-nx-os-device">
                        <eps-items>
                            <epId-items>
                            <Ep-list>
                                <epId>1</epId>
                                <adminSt>enabled</adminSt>
                                <hostReach>bgp</hostReach>
                                <sourceInterface>lo1</sourceInterface>
                                <nws-items>
                                <vni-items>
                                    <Nw-list>
                                    <vni>10017</vni>
                                    <mcastGroup>239.1.1.17</mcastGroup>
                                    </Nw-list>
                                </vni-items>
                                </nws-items>
                            </Ep-list>
                            </epId-items>
                        </eps-items>
                    </System>
                    </config>
                    '''

            # EVPN RPC
            evpn_rpc = '''
                    <config>
                    <System xmlns="http://cisco.com/ns/yang/cisco-nx-os-device">
                        <evpn-items>
                            <adminSt>enabled</adminSt>
                            <bdevi-items>
                            <BDEvi-list>
                                <encap>vxlan-10017</encap>
                                <rd>rd:unknown:0:0</rd>
                                <rttp-items>
                                <RttP-list>
                                    <type>export</type>
                                    <ent-items>
                                    <RttEntry-list>
                                        <rtt>route-target:unknown:0:0</rtt>
                                    </RttEntry-list>
                                    </ent-items>
                                </RttP-list>
                                <RttP-list>
                                    <type>import</type>
                                    <ent-items>
                                    <RttEntry-list>
                                        <rtt>route-target:unknown:0:0</rtt>
                                    </RttEntry-list>
                                    </ent-items>
                                </RttP-list>
                                </rttp-items>
                            </BDEvi-list>
                            </bdevi-items>
                        </evpn-items>
                    </System>
                    </config>
                    '''

            # Edit Config RPCs
            reply = m.edit_config(vlan_vni_rpc, target='running')
            print(reply)
            reply = m.edit_config(nve_rpc, target='running')
            print(reply)
            reply = m.edit_config(evpn_rpc, target='running')
            print(reply)

            # Save RPC
            rpc = '''
                <copy_running_config_src xmlns="http://cisco.com/ns/yang/cisco-nx-os-device">
                        <startup-config/>
                </copy_running_config_src>
                '''
            reply = m.dispatch(to_ele(rpc))
            print(reply)


Step 4 - Setup Call of Main Function

The last bit of Python is to call the main function you defined above.


if __name__ == '__main__':
    main()


Step 5 - Run Python Script

Once you have finished with your code, execute your ncclient Python script:


python nx_ncclient_config.py

    

Upon a successful execution, you should see eight rpc-reply messages (four per device) with an ok as the reply return — one for each of the three config RPCs (VLAN/VNI, NVE, EVPN) and one for the save operation.


        <?xml version="1.0" encoding="UTF-8"?>
        <rpc-reply xmlns:nxos="http://www.cisco.com/nxos:1.0" xmlns:if="http://www.cisco.com/nxos:1.0:if_manager" xmlns:nfcli="http://www.cisco.com/nxos:1.0:nfcli" xmlns:vlan_mgr_cli="http://www.cisco.com/nxos:1.0:vlan_mgr_cli" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:86b079cc-c1f4-482b-8e4a-04a6372b5d2c">
            <ok/>
        </rpc-reply>

        <?xml version="1.0" encoding="UTF-8"?>
        <rpc-reply xmlns:nxos="http://www.cisco.com/nxos:1.0" xmlns:if="http://www.cisco.com/nxos:1.0:if_manager" xmlns:nfcli="http://www.cisco.com/nxos:1.0:nfcli" xmlns:vlan_mgr_cli="http://www.cisco.com/nxos:1.0:vlan_mgr_cli" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:46afcc4f-49f9-41c9-a9f5-68f02f46f129">
            <ok/>
        </rpc-reply>

        <?xml version="1.0" encoding="UTF-8"?>
        <rpc-reply xmlns:nxos="http://www.cisco.com/nxos:1.0" xmlns:if="http://www.cisco.com/nxos:1.0:if_manager" xmlns:nfcli="http://www.cisco.com/nxos:1.0:nfcli" xmlns:vlan_mgr_cli="http://www.cisco.com/nxos:1.0:vlan_mgr_cli" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:46d1c231-4075-4cdf-a521-c32a09b3ea18">
            <ok/>
        </rpc-reply>

        <?xml version="1.0" encoding="UTF-8"?>
        <rpc-reply xmlns:nxos="http://www.cisco.com/nxos:1.0" xmlns:if="http://www.cisco.com/nxos:1.0:if_manager" xmlns:nfcli="http://www.cisco.com/nxos:1.0:nfcli" xmlns:vlan_mgr_cli="http://www.cisco.com/nxos:1.0:vlan_mgr_cli" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:222085be-412a-4742-b678-82d42fc38a9e">
            <ok/>
        </rpc-reply>

        <?xml version="1.0" encoding="UTF-8"?>
        <rpc-reply xmlns:nxos="http://www.cisco.com/nxos:1.0" xmlns:if="http://www.cisco.com/nxos:1.0:if_manager" xmlns:nfcli="http://www.cisco.com/nxos:1.0:nfcli" xmlns:vlan_mgr_cli="http://www.cisco.com/nxos:1.0:vlan_mgr_cli" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:472adf70-557b-42ff-9417-31551cfb018c">
            <ok/>
        </rpc-reply>

        <?xml version="1.0" encoding="UTF-8"?>
        <rpc-reply xmlns:nxos="http://www.cisco.com/nxos:1.0" xmlns:if="http://www.cisco.com/nxos:1.0:if_manager" xmlns:nfcli="http://www.cisco.com/nxos:1.0:nfcli" xmlns:vlan_mgr_cli="http://www.cisco.com/nxos:1.0:vlan_mgr_cli" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:5ffb1915-8bc6-468a-bbe2-63c2d5204822">
            <ok/>
        </rpc-reply>

        <?xml version="1.0" encoding="UTF-8"?>
        <rpc-reply xmlns:nxos="http://www.cisco.com/nxos:1.0" xmlns:if="http://www.cisco.com/nxos:1.0:if_manager" xmlns:nfcli="http://www.cisco.com/nxos:1.0:nfcli" xmlns:vlan_mgr_cli="http://www.cisco.com/nxos:1.0:vlan_mgr_cli" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:3d93eb63-64d8-4e6f-8351-579f33523a2e">
            <ok/>
        </rpc-reply>

        <?xml version="1.0" encoding="UTF-8"?>
        <rpc-reply xmlns:nxos="http://www.cisco.com/nxos:1.0" xmlns:if="http://www.cisco.com/nxos:1.0:if_manager" xmlns:nfcli="http://www.cisco.com/nxos:1.0:nfcli" xmlns:vlan_mgr_cli="http://www.cisco.com/nxos:1.0:vlan_mgr_cli" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:77a03cf5-349d-4c2b-be17-7cda387f6f0d">
            <ok/>
        </rpc-reply>

    

Upon successful execution of this Python code, VLAN 17 will be mapped to VNI 10017, the VNI will be added to the NVE interface, and EVPN will be configured for your leaf switches. You can confirm this two ways:

  1. The output with the rpc-reply containing "ok" confirming a successful operation, or
  2. Log in to the leaf switches and verify with show vlan brief, show nve vni, and show bgp l2vpn evpn summary.

Continue to the last bonus section to work with RESTCONF.