Sommario

Introduzione

Prerequisiti

Configurazione

Esempio di rete

Procedura di configurazione

1. Recupera token-id

2. Creare VRF

3. Spostamento dell'interfaccia in un VRF

4. Assegna indirizzo IP all'interfaccia

5. Creare bgp con riconoscimento VRF

6. Definire il sistema BGP adiacente nella famiglia di indirizzi VRF

Riferimenti

Acronimi usati:

Introduzione

Questo documento dimostra l'uso della programmazione Python per effettuare il provisioning di una VPN MPLS L3VPN su un router Service Provider Edge (PE) utilizzando l'API REST. In questo esempio vengono utilizzati i router Cisco CSR1000v (IOS-XE) come router PE.

Contributo di: Anuradha Perera

Modificato da: Kumar Sridhar

Prerequisiti

- Accesso di gestione dell'API REST ai router CSR1000v (fare riferimento ai riferimenti alla fine di questo documento).

- Python (versione 2.x o 3.x) e libreria Python "Richieste" installata sul computer utilizzato per la configurazione dei router.

- Alcune nozioni di base sulla programmazione Python.

Configurazione

Esempio di rete

In questo esempio viene descritta la configurazione dei parametri del servizio MPLS L3VPN richiesti sul router PE-1, evidenziati in rosa.

Procedura di configurazione

L'attività Configurazione è suddivisa in più sottoattività e ogni sottoattività è implementata in una funzione definita dall'utente. In questo modo le funzioni possono essere riutilizzate quando necessario.

Tutte le funzioni utilizzano la libreria "Requests" per accedere alle API REST sul router e il formato dei dati è JSON. Nelle richieste HTTP il parametro "verify" è impostato su "False" per ignorare la convalida del certificato SSL.

1. Recupera token-id

Prima di procedere con la configurazione su un router, è necessario avere un token-id valido ottenuto dal router. Questa funzione avvia una richiesta HTTP per autenticare e ottenere un token ID in modo che possa richiamare altre API utilizzando questo token. La risposta a questa richiesta include un token-id.

N.—

def getToken (ip, porta, nome utente, password):

richieste di importazione

importa base64

url = "https://" + ip + ":"+ porta + "/api/v1/auth/token-services"

headers = {

'content-type': "application/json",

'authorization': "Basic" + base64.b64encode((username + ":" + password).encode('UTF-8').decode('ascii'),

'cache-control': "no-cache"

}

response = request.request("POST", url, headers=headers, verify=False )

if response.status_code == 200:

return response.json()['token-id']

Altrimenti:

ritorno "non riuscito"

N.—

2. Creare VRF

Questa funzione crea il VRF sul router PE con il necessario identificatore di percorso (RD) e gli oggetti di percorso di importazione/esportazione (RT)

N.—

def createVRF (ip, porta, tokenID, vrfName, RD, importRT, exportRT):

richieste di importazione

url = "https://" + ip + ":"+ porta + "/api/v1/vrf"

headers = {

'content-type': "application/json",

'X-auth-token': tokenID,

'cache-control': "no-cache"

}

dati = {

'name': vrfName

'rd': RD

'route-target': [

{

'azione' : "importazione",

'community': importRT

},

{

'azione' : "esportazione",

'community': exportRT

}

]

}

response = request.request("POST", url, headers=headers, json=data, verify=False )

if response.status_code == 201:

ritorno "riuscito"

Altrimenti:

ritorno "non riuscito"

N.—

3. Spostamento dell'interfaccia in un VRF

Questa funzione sposta una determinata interfaccia in un VRF.

N.—

def addInterfaceVRF (ip, port, tokenID, vrfName, interfaceName, RD, importRT, exportRT):

richieste di importazione

url = "https://" + ip + ":"+ porta + "/api/v1/vrf/" + vrfName

headers = {

'content-type': "application/json",

'X-auth-token': tokenID,

'cache-control': "no-cache"

}

dati = {

'rd': RD

'forwarding': [ nomeInterfaccia ],

'route-target': [

{

"azione" : "importazione",

'community': importRT

},

{

"azione" : "esportazione",

'community': exportRT

}

]

}

response = request.request("PUT", url, headers=headers, json=data, verify=False )

if response.status_code == 204:

ritorno "riuscito"

Altrimenti:

ritorno "non riuscito"

N.—

4. Assegna indirizzo IP all'interfaccia

Questa funzione assegna l'indirizzo IP all'interfaccia.

N.—

def assignInterfaceIP (ip, port, tokenID, interfaceName, interfaceIP, interfaceSubnet):

richieste di importazione

url = "https://" + ip + ":"+ porta + "/api/v1/interfaces/" + interfaceName

headers = {

'content-type': "application/json",

'X-auth-token': tokenID,

'cache-control': "no-cache"

}

dati = {

'tipo': "ethernet",

'if-name': interfaceName;

'ip-address': interfaceIP,

'subnet-mask': interfaceSubnet

}

response = request.request("PUT", url, headers=headers, json=data, verify=False )

if response.status_code == 204:

restituisci "riuscito"

Altrimenti:

restituisci "non riuscito"

N.—

5. Creare bgp con riconoscimento VRF

In questo modo verrà abilitata la famiglia di indirizzi VRF ipv4.

N.—

def createVrfBGP (ip, porta, tokenID, vrfName, ASN):

richieste di importazione

url = "https://" + ip + ":"+ porta + "/api/v1/vrf/" + vrfName + "/routing-svc/bgp"

headers = {

'content-type': "application/json",

'X-auth-token': tokenID,

'cache-control': "no-cache"

}

dati = {

'routing-protocol-id': ASN

}

response = request.request("POST", url, headers=headers, json=data, verify=False )

if response.status_code == 201:

ritorno "riuscito"

Altrimenti:

ritorno "non riuscito"

N.—

6. Definire il sistema BGP adiacente nella famiglia di indirizzi VRF

Questa funzione definirà il router adiacente BGP nella famiglia di indirizzi VRF IPV4.

N.—

def defineVrfBGPNighbor (ip, porta, tokenID, vrfName, ASN, neighbourIP, remoteAS):

richieste di importazione

url = "https://" + ip + ":"+ porta + "/api/v1/vrf/" + vrfName + "/routing-svc/bgp/" + ASN +"/neighbors"

headers = {

'content-type': "application/json",

'X-auth-token': tokenID,

'cache-control': "no-cache"

}

dati = {

'routing-protocol-id': ASN,

'indirizzo': neighborsIP,

'remote-as': remoteAS

}

response = request.request("POST", url, headers=headers, json=data, verify=False )

if response.status_code == 201:

ritorno "riuscito"

Altrimenti:

ritorno "non riuscito"

N.—

Descrizione e valori dei parametri input

ip = "10.0.0.1 "                                       # indirizzo ip del router

port = porta "55443"                                        # Porta API REST su router

username = "cisco"                                # nome utente per l'accesso.Deve essere configurato con il livello di privilegio 15.

password = "cisco"                                 # password associata al nome utente

tokenID = <valore restituito> # Token ID ottenuto dal router tramite la funzione getToken

vrfName = "VRF-A" # nome del VRF

RD = "3:3" # Distintore di route per VRF

importRT = "34:34" # Destinazione route di importazione

exportRT = "34:34" # destinazione route di esportazione

interfaceName = "Gigabit Ethernet3" # nome dell'interfaccia lato cliente (CE)

interfaceIP = "192.168.13.3" # indirizzo IP dell'interfaccia CE

interfaceSubnet = "255.255.255.0" # subnet dell'interfaccia di sfacciatura CE

ASN = "34" # BGP AS numero di router PE

neighbourIP = "192.168.13.1" # IP di peering BGP del router CE

remoteAS = "11" # Numero AS del router CE

In tutte le funzioni precedenti, sono state chiamate API dedicate per ogni configurazione. L'esempio seguente mostra come passare la CLI di IOS-XE, in generale, nel corpo della chiamata API REST. Questa opzione può essere utilizzata come soluzione per automatizzare il processo nel caso in cui una particolare API non sia disponibile. Nelle funzioni precedenti 'content-type' è impostato su 'application/json', ma nell'esempio seguente 'content-type' è impostato su 'text/plain' come viene analizzato l'input CLI standard.

Nell'esempio viene definita la descrizione dell'interfaccia per l'interfaccia Gigabit Ethernet3. La configurazione può essere personalizzata modificando il parametro "cliInput".

N.—

def passCLIInput (ip, porta, tokenID):

richieste di importazione

url = "https://" + ip + ":"+ porta + "/api/v1/global/running-config"

headers = {

'tipo di contenuto': "testo/semplice",

'X-auth-token': tokenID,

'cache-control': "no-cache"

}

line1 = "Interfaccia Gigabit Ethernet 3"

line2 = "description Interfaccia a faccia cliente"

cliInput = riga1 + "\r\n" + riga2

response = request.request("PUT", url, headers=headers, data=cliInput, verify=False )

stampa(response.text)

if response.status_code == 204:

ritorno "riuscito"

Altrimenti:

ritorno "non riuscito"

N.—

Riferimenti

- Guida alla configurazione di Cisco CSR serie 1000v Cloud Services Router

https://www.cisco.com/c/en/us/td/docs/routers/csr1000/software/configuration/b_CSR1000v_Configuration_Guide /b_CSR1000v_Configuration_Guide_chapter_01101.html

- Guida di riferimento per la gestione dell'API REST Cisco IOS XE

https://www.cisco.com/c/en/us/td/docs/routers/csr1000/software/restapi/restapi.html

Acronimi usati:

MPLS - Multi Protocol Label Switching

L3 - Layer 3

VPN - Rete privata virtuale

VRF - Inoltro route virtuale

BGP - Border Gateway Protocol

REST - Trasferimento stato di rappresentanza

API - Interfaccia del programma applicativo

JSON - Notazione oggetto script Java

HTTP - Protocollo di trasferimento Hyper-Text