Introduction
This document demonstrates the use of Python programming to provision a MPLS L3VPN on a service Provider Edge (PE) router using REST API. This example uses Cisco CSR1000v (IOS-XE) routers as PE routers.
Contributed by: Anuradha Perera
Edited by: Kumar Sridhar
Prerequisites
- REST API management access to CSR1000v routers (pleae refer to the References at the end of this document).
- Python (Version 2.x or 3.x) and "Requests" Python library installed on the computer used for configuring the routers.
- Some basic knowledge Python programming.
Configuration
Network Diagram
In this example focus is on configuring required MPLS L3VPN service parameters on PE-1 router, which are highlighted in pink color.
Configuration Procedure
The Configuration task is divided in to a number of sub-tasks and each sub-task is implemented under a user defined function. In this way functions can be re-used when required.
All the functions use "Requests" library to access REST APIs on the router and data format is JSON. In HTTP requests “verify” parameter is set to “False” to ignore validating SSL certificate.
1. Retrieve token-id
Before proceeding with any configuration on a router you need to have a valid token-id obtained from the router. This function initiates HTTP request to authenticate and obtain a token-id so that it can invoke other APIs using this token. Response of this request includes a token-id.
#-----------------------------------
def getToken (ip, port, username, password):
import requests
import base64
url = "https://" + ip + ":"+ port + "/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 = requests.request("POST", url, headers=headers, verify=False )
if response.status_code == 200:
return response.json()['token-id']
else:
return "failed"
#-----------------------------------
2. Create VRF
This function will create the VRF on PE router with required route distinguisher (RD) and import/export route targets (RT)
#-----------------------------------
def createVRF (ip, port, tokenID, vrfName, RD, importRT, exportRT):
import requests
url = "https://" + ip + ":"+ port + "/api/v1/vrf"
headers = {
'content-type': "application/json",
'X-auth-token': tokenID,
'cache-control': "no-cache"
}
data = {
'name': vrfName,
'rd': RD,
'route-target' : [
{
'action' : "import",
'community' : importRT
},
{
'action' : "export",
'community' : exportRT
}
]
}
response = requests.request("POST", url, headers=headers, json=data, verify=False )
if response.status_code == 201:
return "successful"
else:
return "failed"
#-----------------------------------
3. Move interface into a VRF
This function will move a given interface into a VRF.
#-----------------------------------
def addInterfacetoVRF (ip, port, tokenID, vrfName, interfaceName, RD, importRT, exportRT):
import requests
url = "https://" + ip + ":"+ port + "/api/v1/vrf/" + vrfName
headers = {
'content-type': "application/json",
'X-auth-token': tokenID,
'cache-control': "no-cache"
}
data = {
'rd': RD,
'forwarding': [ interfaceName ],
'route-target' : [
{
'action' : "import",
'community' : importRT
},
{
'action' : "export",
'community' : exportRT
}
]
}
response = requests.request("PUT", url, headers=headers, json=data, verify=False )
if response.status_code == 204:
return "successful"
else:
return "failed"
#-----------------------------------
4. Assign IP address to interface
This function will assign ip address to the interface.
#-----------------------------------
def assignInterfaceIP (ip, port, tokenID, interfaceName, interfaceIP, interfaceSubnet):
import requests
url = "https://" + ip + ":"+ port + "/api/v1/interfaces/" + interfaceName
headers = {
'content-type': "application/json",
'X-auth-token': tokenID,
'cache-control': "no-cache"
}
data = {
'type': "ethernet",
'if-name': interfaceName,
'ip-address': interfaceIP,
'subnet-mask': interfaceSubnet
}
response = requests.request("PUT", url, headers=headers, json=data, verify=False )
if response.status_code == 204:
return "successful"
else:
return "failed"
#-----------------------------------
5. Create VRF aware bgp
This will enable VRF address family ipv4.
#-----------------------------------
def createVrfBGP (ip, port, tokenID, vrfName, ASN):
import requests
url = "https://" + ip + ":"+ port + "/api/v1/vrf/" + vrfName + "/routing-svc/bgp"
headers = {
'content-type': "application/json",
'X-auth-token': tokenID,
'cache-control': "no-cache"
}
data = {
'routing-protocol-id': ASN
}
response = requests.request("POST", url, headers=headers, json=data, verify=False )
if response.status_code == 201:
return "successful"
else:
return "failed"
#-----------------------------------
6. Define BGP neighbor under VRF address family
This function will define BGP neighbor under VRF address family IPV4.
#-----------------------------------
def defineVrfBGPNeighbour (ip, port, tokenID, vrfName, ASN, neighbourIP, remoteAS):
import requests
url = "https://" + ip + ":"+ port + "/api/v1/vrf/" + vrfName + "/routing-svc/bgp/" + ASN +"/neighbors"
headers = {
'content-type': "application/json",
'X-auth-token': tokenID,
'cache-control': "no-cache"
}
data = {
'routing-protocol-id': ASN,
'address': neighbourIP,
'remote-as': remoteAS
}
response = requests.request("POST", url, headers=headers, json=data, verify=False )
if response.status_code == 201:
return "successful"
else:
return "failed"
#-----------------------------------
Description and values of input parameters
ip = "10.0.0.1" # ip address of the router
port = "55443" # REST API port on router
username = "cisco" # username to login.This should be configured with privilege level 15.
password = "cisco" # password associated with username
tokenID = <value returned> # Token ID obtained from router using getToken function
vrfName = "VRF-A" # name of the VRF
RD = "3:3" # Route Distinguisher for VRF
importRT = "34:34" # Import Route Target
exportRT = "34:34" # export Route Target
interfaceName = "GigabitEthernet3" # name of the customer edge (CE) facing interface
interfaceIP = "192.168.13.3" # IP address of CE facing interface
interfaceSubnet = "255.255.255.0" # subnet of CE facing interface
ASN = "34" # BGP AS number of PE router
neighbourIP = "192.168.13.1" # BGP peering IP of CE router
remoteAS = "11" # AS number of CE router
In all the above functions, dedicated APIs were called for each configuation setp. The example below demonstrates how to pass IOS-XE CLI, in general, in the body of REST API call. This can be used as a workaround to automate if particular API is not available. In the above functions 'content-type' is set to 'application/json', but in the below example, 'content-type' is set to 'text/plain' as it is parsing standard CLI input.
This exmaple defines interface description for interface GigabitEthernet3. Configuration can be customized by changing the "cliInput" parameter.
#-----------------------------------
def passCLIInput (ip, port, tokenID):
import requests
url = "https://" + ip + ":"+ port + "/api/v1/global/running-config"
headers = {
'content-type': "text/plain",
'X-auth-token': tokenID,
'cache-control': "no-cache"
}
line1 = "Interface GigabitEthernet 3"
line2 = "description Customer Facing Interface"
cliInput = line1 + "\r\n" + line2
response = requests.request("PUT", url, headers=headers, data=cliInput, verify=False )
print(response.text)
if response.status_code == 204:
return "sucessful"
else:
return "failed"
#-----------------------------------
References
- Cisco CSR 1000v Series Cloud Services Router Software Configuration Guide
https://www.cisco.com/c/en/us/td/docs/routers/csr1000/software/configuration/b_CSR1000v_Configuration_Guide /b_CSR1000v_Configuration_Guide_chapter_01101.html
- Cisco IOS XE REST API Management Reference Guide
https://www.cisco.com/c/en/us/td/docs/routers/csr1000/software/restapi/restapi.html
Acronyms Used:
MPLS - Multi Protocol Label Switching
L3 - Layer 3
VPN - Virtual Private Network
VRF - Virtual Route Forwarding
BGP - Border Gateway Protocol
REST - Representational State Transfer
API - Application Program Interface
JSON - Java Script Object Notation
HTTP - Hyper Text Transfer Protocol