Introduction
Este documento demonstra o uso da programação Python para provisionar um MPLS L3VPN em um roteador PE (Provider Edge) usando a API REST. Este exemplo usa roteadores Cisco CSR1000v (IOS-XE) como roteadores PE.
Contribuição de: Anuradha Perera
Editado por: Kumar Sridhar
Prerequisites
- Acesso de gerenciamento da API REST aos roteadores CSR1000v (consulte as referências no final deste documento).
- Python (Versão 2.x ou 3.x) e a biblioteca Python "Requests" instalados no computador usado para configurar os roteadores.
- Alguns conhecimentos básicos de programação Python.
Configuração
Diagrama de Rede
Neste exemplo, concentre-se na configuração dos parâmetros de serviço L3VPN MPLS necessários no roteador PE-1, que são destacados na cor rosa.
Procedimento de configuração
A tarefa Configuração é dividida em várias subtarefas e cada subtarefa é implementada em uma função definida pelo usuário. Dessa forma, as funções podem ser reutilizadas quando necessário.
Todas as funções usam a biblioteca "Requests" para acessar APIs REST no roteador e o formato de dados é JSON. Nas solicitações HTTP, o parâmetro "verify" é definido como "False" para ignorar a validação do certificado SSL.
1. Recuperar token-id
Antes de prosseguir com qualquer configuração em um roteador, você precisa ter um token-id válido obtido do roteador. Essa função inicia uma solicitação HTTP para autenticar e obter uma ID de token para que possa invocar outras APIs usando esse token. A resposta desta solicitação inclui um token-id.
#-----------------------------------
def getToken (ip, port, username, password):
solicitações de importação
importar base64
url = "https://" + ip + ":"+ port + "/api/v1/auth/token-services"
cabeçalhos = {
"tipo de conteúdo": "aplicação/json",
'authorization': "Basic " + base64.b64encode((username + ":" + password).encode('UTF-8')).decode('ascii')),
'cache-control': "no-cache"
}
response = requests.request("POST", url, cabeçalhos=cabeçalhos, verify=False )
if response.status_code == 200:
return response.json()['token-id']
else :
retorno "failed"
#-----------------------------------
2. Criar VRF
Essa função criará o VRF no roteador PE com o diferenciador de rota (RD) e destinos de rota de importação/exportação (RT) necessários
#-----------------------------------
def createVRF (ip, porta, tokenID, vrfName, RD, importRT, exportRT):
solicitações de importação
url = "https://" + ip + ":"+ porta + "/api/v1/vrf"
cabeçalhos = {
'tipo de conteúdo': "aplicativo/json",
'X-auth-token': tokenID,
'cache-control': "no-cache"
}
dados = {
'name': vrfName,
'rd': RD,
'route-target' : [
{
"ação" : "importação",
'comunidade' : importRT
},
{
"ação" : "exportação",
'comunidade' : exportRT
}
]
}
response = requests.request("POST", url, cabeçalhos=cabeçalhos, json=dados, verify=False )
if response.status_code == 201:
retorno "bem-sucedido"
else :
retorno "failed"
#-----------------------------------
3. Mover a interface para um VRF
Essa função moverá uma determinada interface para um VRF.
#-----------------------------------
def addInterfacetoVRF (ip, porta, tokenID, vrfName, interfaceName, RD, importRT, exportRT):
solicitações de importação
url = "https://" + ip + ":"+ porta + "/api/v1/vrf/" + vrfName
cabeçalhos = {
'tipo de conteúdo': "aplicativo/json",
'X-auth-token': tokenID,
'cache-control': "no-cache"
}
dados = {
'rd': RD,
'forwarding': [ interfaceName ],
'route-target' : [
{
'ação' : "importação",
'comunidade' : importRT
},
{
"ação" : "exportação",
'comunidade' : exportRT
}
]
}
response = requests.request("PUT", url, cabeçalhos=cabeçalhos, json=dados, verify=False )
if response.status_code == 204:
retorno "bem-sucedido"
else :
retorno "failed"
#-----------------------------------
4. Atribuir um endereço IP à interface
Essa função atribuirá um endereço IP à interface.
#-----------------------------------
def assignInterfaceIP (ip, port, tokenID, interfaceName, interfaceIP, interfaceSubnet):
solicitações de importação
url = "https://" + ip + ":"+ porta + "/api/v1/interfaces/" + interfaceName
cabeçalhos = {
'tipo de conteúdo': "aplicativo/json",
'X-auth-token': tokenID,
'cache-control': "no-cache"
}
dados = {
'type': "ethernet",
'if-name': interfaceName,
'ip-address': interfaceIP,
'subnet-mask': interfaceSubnet
}
response = requests.request("PUT", url, cabeçalhos=cabeçalhos, json=dados, verify=False )
if response.status_code == 204:
return "successful"
else :
return "failed"
#-----------------------------------
5. Criar bgp sensível a VRF
Isso ativará a família de endereços VRF ipv4.
#-----------------------------------
def createVrfBGP (ip, porta, tokenID, vrfName, ASN):
solicitações de importação
url = "https://" + ip + ":"+ porta + "/api/v1/vrf/" + vrfName + "/routing-svc/bgp"
cabeçalhos = {
'tipo de conteúdo': "aplicativo/json",
'X-auth-token': tokenID,
'cache-control': "no-cache"
}
dados = {
'routing-protocol-id': ASN
}
response = requests.request("POST", url, cabeçalhos=cabeçalhos, json=dados, verify=False )
if response.status_code == 201:
retorno "bem-sucedido"
else :
retorno "failed"
#-----------------------------------
6. Defina o vizinho BGP na família de endereços VRF
Essa função definirá o vizinho BGP na família de endereços VRF IPV4.
#-----------------------------------
def defineVrfBGPNeighbor (ip, porta, tokenID, vrfName, ASN, neighborIP, remoteAS):
solicitações de importação
url = "https://" + ip + ":"+ porta + "/api/v1/vrf/" + vrfName + "/routing-svc/bgp/" + ASN +"/neighbors"
cabeçalhos = {
'tipo de conteúdo': "aplicativo/json",
'X-auth-token': tokenID,
'cache-control': "no-cache"
}
dados = {
'routing-protocol-id': ASN,
'address': neighborIP,
'remote-as': remoteAS
}
response = requests.request("POST", url, cabeçalhos=cabeçalhos, json=dados, verify=False )
if response.status_code == 201:
retorno "bem-sucedido"
else :
retorno "failed"
#-----------------------------------
Descrição e valores dos parâmetros de entrada
ip = "10.0.0.1" # endereço ip do roteador
porta = "55443" # Porta API REST no roteador
nome de usuário = "cisco" # nome de usuário para login. Deve ser configurado com nível de privilégio 15.
senha = "cisco" # senha associada ao nome de usuário
tokenID = <valor retornado> # Token ID obtido do roteador com a função getToken
vrfName = "VRF-A" # nome do VRF
RD = "3:3" # Distinguidor de rota para VRF
importRT = "34:34" # Destino da rota de importação
exportRT = "34:34" #export Route Target
interfaceName = "GigabitEthernet3" # nome da interface voltada para a borda do cliente (CE)
interfaceIP = "192.168.13.3" # Endereço IP da interface voltada para o CE
interfaceSubnet = "255.255.255.0" # sub-rede da interface voltada para o CE
ASN = "34" # BGP AS número do roteador PE
neighborIP = "192.168.13.1" # BGP peering IP do roteador CE
remoteAS = "11" # AS número do roteador CE
Em todas as funções acima, APIs dedicadas foram chamadas para cada etapa da configuração. O exemplo abaixo demonstra como passar a CLI do IOS-XE, em geral, no corpo da chamada à API REST. Isso pode ser usado como uma solução alternativa para automatizar se uma API específica não estiver disponível. Nas funções acima, 'content-type' está definido como 'application/json', mas no exemplo abaixo, 'content-type' está definido como 'text/plain', pois está analisando a entrada CLI padrão.
Este exemplo define a descrição da interface para a interface GigabitEthernet3. A configuração pode ser personalizada alterando o parâmetro "cliInput".
#-----------------------------------
def passCLIInput (ip, porta, tokenID):
solicitações de importação
url = "https://" + ip + ":"+ port + "/api/v1/global/running-config"
cabeçalhos = {
'content-type': "text/plain",
'X-auth-token': tokenID,
'cache-control': "no-cache"
}
line1 = "Interface GigabitEthernet 3"
line2 = "description Customer Facing Interface"
cliInput = linha1 + "\r\n" + linha2
response = requests.request("PUT", url, cabeçalhos=cabeçalhos, data=cliInput, verify=False )
print(response.text)
if response.status_code == 204:
retorno "bem-sucedido"
else :
retorno "failed"
#-----------------------------------
Referências
- Guia de configuração de software do roteador de serviços em nuvem Cisco CSR 1000v Series
https://www.cisco.com/c/en/us/td/docs/routers/csr1000/software/configuration/b_CSR1000v_Configuration_Guide /b_CSR1000v_Configuration_Guide_chapter_01101.html
- Guia de referência de gerenciamento da API REST do Cisco IOS XE
https://www.cisco.com/c/en/us/td/docs/routers/csr1000/software/restapi/restapi.html
Acrônimos utilizados:
MPLS - Multi Protocol Label Switching (MPLS - Comutação de rótulo multiprotocolo)
L3 - Camada 3
VPN - Rede virtual privada
VRF - Encaminhamento de rota virtual
BGP - Protocolo de gateway de borda
REST - Transferência de Estado Representacional
API - Interface de programa de aplicativo
JSON - Notação de Objeto de Script Java
HTTP - Hyper Text Transfer Protocol (Protocolo de Transferência de Hipertexto)