Deploying a Cisco Data Center

Appendix I

NXAPI

NX-API CLI is an enhancement to the Cisco Nexus 9000 Series CLI system, which supports XML output. NX-API CLI also supports JSON output format for specific commands.

On Cisco Nexus devices, command-line interfaces (CLIs) are run only on the device. NX-API CLI improves the accessibility of these CLIs by making them available outside of the switch by using HTTP/HTTPS. NX-API CLI supports show commands, configurations, and Linux Bash. NX-API CLI supports JSON-RPC.

The Python scripts that were available in the lab leveraged NXAPI CLI. As you can see below an script and notice it is very similar to the CLI you may be accustomed to. You can now wrap Python around what you already know. The script below is an example for your reading. The scripts written for this lab and are taken as is. For each lab, a Class file was written and then an execution file that creates an object of the Class.



lab5-mould1.py


        #Config Block 

        from vxlanmultipod import EBGPEVPN

        switchuser = 'admin'
        switchpassword = 'cisco.123'
        pod_spines = ['10.1.0.2']

        print '***** Configuring Multi-Hop eBGP EVPN Peering for VXLAN Multi-Pod *****'
        print ''

        for spine in pod_spines:
            pod = spine[3]
            local_as = '6500' + pod

            url = 'http://' + spine + '/ins'

            eBGPEVPN = EBGPEVPN(url, switchuser, switchpassword, local_as)
            eBGPEVPN.multihop_ebgp_evpn()
        
    


vxlanmultipod.py


        #Config Block 

import requests
import json


class Switches(object):
    def __init__(self, url, switchuser, switchpassword):
        self.url = url
        self.switchuser = switchuser
        self.switchpassword = switchpassword


class EBGPEVPN(Switches):
    def __init__(self, url, switchuser, switchpassword, asn):
        Switches.__init__(self, url, switchuser, switchpassword)
        self.asn = asn

    def multihop_ebgp_evpn(self):
        myheaders = {'content-type': 'application/json-rpc'}
        payload = [
            {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'conf', "version": 1}, "id": 1},
            {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'route-map permit-all permit', "version": 1}, "id": 2},
            {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'set ip next-hop unchanged', "version": 1}, "id": 3}
        ]
        requests.post(self.url, data=json.dumps(payload), headers=myheaders, auth=(self.switchuser,
                                                                                   self.switchpassword)).json()
        for i in payload:
            print i["params"]["cmd"]
        print ''
        print 'Route-map configured to prevent next-hop from changing. Next-hop must always be tunnel endpoint address.'
        print ''

        myheaders = {'content-type': 'application/json-rpc'}
        payload = [
            {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'conf', "version": 1}, "id": 1},
            {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'router bgp ' + self.asn, "version": 1}, "id": 2},
            {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'template peer eBGP-EVPN', "version": 1}, "id": 3},
            {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'ebgp-multihop 5', "version": 1}, "id": 4},
            {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'update-source loopback0', "version": 1}, "id": 5},
            {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'address-family l2vpn evpn', "version": 1}, "id": 6},
            {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'send-community extended', "version": 1}, "id": 7},
            #{"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'rewrite-evpn-rt-asn', "version": 1}, "id": 8},
            {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'route-map permit-all out', "version": 1}, "id": 8},
            #{"jsonrpc": "2.0", "method": "cli", "params": {"cmd": '', "version": 1}, "id": 4},
        ]
        requests.post(self.url, data=json.dumps(payload), headers=myheaders, auth=(self.switchuser,
                                                                                   self.switchpassword)).json()
        for i in payload:
            print i["params"]["cmd"]
        print ''
        print 'eBGP EVPN peer template configured!'
        print ''

        for remotePOD in range(1, 10):
            remote_pod = str(remotePOD)
            remote_asn = '6500' + remote_pod
            local_pod = self.asn[4]
            myheaders = {'content-type': 'application/json-rpc'}
            if remote_pod != local_pod:
                payload = [
                    {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'conf', "version": 1}, "id": 1},
                    {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'router bgp ' + self.asn, "version": 1}, "id": 2},
                    {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'neighbor ' + remote_pod + '.' + remote_pod + '.' + remote_pod + '.' + '1 remote-as ' + remote_asn, "version": 1}, "id": 3},
                    {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'inherit peer eBGP-EVPN', "version": 1}, "id": 4},
                    {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'address-family l2vpn evpn', "version": 1}, "id": 5},
                    {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'rewrite-evpn-rt-asn', "version": 1}, "id": 6},
                    {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'neighbor ' + remote_pod + '.' + remote_pod + '.' + remote_pod + '.' + '2 remote-as ' + remote_asn, "version": 1}, "id": 7},
                    {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'inherit peer eBGP-EVPN', "version": 1}, "id": 8},
                    {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'address-family l2vpn evpn', "version": 1}, "id": 9},
                    {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'rewrite-evpn-rt-asn', "version": 1}, "id": 10}
                    # {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": '', "version": 1}, "id": 4},
                ]
                requests.post(self.url, data=json.dumps(payload), headers=myheaders, auth=(self.switchuser,
                                                                                           self.switchpassword)).json()
                for i in payload:
                    print i["params"]["cmd"]
                print ''
                print 'Multi-Hop eBGP Peering to POD-%s Configured!' % remote_pod
                print ''
        print 'Transit Spine eBGP EVPN neighbors configured!'
        print ''

        print 'Saving Spine Switch Configuration'
        print ''
        myheaders = {'content-type': 'application/json-rpc'}
        payload = [
            {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'wr', "version": 1}, "id": 1},
        ]
        requests.post(self.url, data=json.dumps(payload), headers=myheaders, auth=(self.switchuser,
                                                                                   self.switchpassword)).json()
        print 'Done!'
        print ''

    def remove_multihop_ebgp_evpn(self):
        myheaders = {'content-type': 'application/json-rpc'}
        payload = [
            {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'conf', "version": 1}, "id": 1},
            {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'no route-map permit-all permit', "version": 1},
             "id": 2},
        ]
        requests.post(self.url, data=json.dumps(payload), headers=myheaders, auth=(self.switchuser,
                                                                                   self.switchpassword)).json()

        myheaders = {'content-type': 'application/json-rpc'}
        payload = [
            {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'conf', "version": 1}, "id": 1},
            {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'router bgp ' + self.asn, "version": 1}, "id": 2},
            {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'no template peer eBGP-EVPN', "version": 1}, "id": 3},
        ]
        requests.post(self.url, data=json.dumps(payload), headers=myheaders, auth=(self.switchuser,
                                                                                   self.switchpassword)).json()
        print 'eBGP EVPN peer template unconfigured!'
        print ''

        for remotePOD in range(1, 10):
            remote_pod = str(remotePOD)
            remote_asn = '6500' + remote_pod
            local_pod = self.asn[4]
            myheaders = {'content-type': 'application/json-rpc'}
            if remote_pod != local_pod:
                payload = [
                    {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'conf', "version": 1}, "id": 1},
                    {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'router bgp ' + self.asn, "version": 1}, "id": 2},
                    {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'no neighbor ' + remote_pod + '.' + remote_pod + '.' + remote_pod + '.' + '1 remote-as ' + remote_asn, "version": 1}, "id": 3},
                    {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'no neighbor ' + remote_pod + '.' + remote_pod + '.' + remote_pod + '.' + '2 remote-as ' + remote_asn, "version": 1}, "id": 4},
                ]
                requests.post(self.url, data=json.dumps(payload), headers=myheaders, auth=(self.switchuser,
                                                                                           self.switchpassword)).json()
                print 'Multi-Hop eBGP Peering to POD-%s Unconfigured!' % remote_pod
                print ''
        print 'Transit Spine eBGP EVPN neighbors unconfigured!'
        print ''

        print 'Saving Spine Switch Configuration'
        print ''
        myheaders = {'content-type': 'application/json-rpc'}
        payload = [
            {"jsonrpc": "2.0", "method": "cli", "params": {"cmd": 'wr', "version": 1}, "id": 1},
        ]
        requests.post(self.url, data=json.dumps(payload), headers=myheaders, auth=(self.switchuser,
                                                                                   self.switchpassword)).json()
        print 'Done!'
        print ''