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.
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
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
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)
The last bit of Python is to call the main function you defined above.
if __name__ == '__main__':
main()
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:
show vlan brief, show nve vni, and show bgp l2vpn evpn summary.Continue to the last bonus section to work with RESTCONF.