A linguagem Python é muito popular, ocupando o rank de 1º lugar a partir de meados de 2018 conforme o PYPL (PopularitY of Programing Language). Na infraestrutura de TI, podemos ver a sua crescente adoção na área de automação.
Muitos equipamentos de rede passaram a suportar Rest API utilizando o formato de JSON (JavaScript Object Notation), já amplamente utilizado nos serviços Web, como por exemplo, em aplicações SPA (Single Page Application), os quais utilizam Rest API para obter dados do backend e atualizar a página dinamicamente.
Deve-se observar a similaridade entre um objeto na linguagem de programação e um dado formatado para transporte, para isso, apresentamos um objeto criado em javascript, outro em python e um dado em JSON. Isso nos ajuda a entender, a facilidade de utilizar JSON para o transporte de objetos criados na linguagem de programação.
var mySwitch = { vendor: "Cisco", model: "Nexus 9300v” };
class mySwitch: vendor = "Cisco" model = "nexus 9300v" sw = mySwitch()
{ “vendor”: “cisco”, “model”: “nexus 9300v” }
A linha Cisco Nexus permite a automação através do NX-API. Para isso, basta ativar a feature. Utilizando um simulador, configuramos o seu ip de gerenciamento na interface mgmt0 e ativamos a feature através do comando "feature nxapi".
nexus9000v# conf t
Enter configuration commands, one per line. End with CNTL/Z.
nexus9000v(config)# feature nxapi
nexus9000v(config)#
Agora com python, já podemos acessar o switch via API através da interface de gerenciamento mgmt0 via https. Vamos começar configurando as seguintes variáveis:
- Endereço IP
- URL
- Usuário e senha, o mesmo utilizado para o acesso remoto (exemplo: local, tacacs)
- Headers para indicar o formato json
- Payload conforme indicado na documentação do equipamento
Neste exemplo, vamos solicitar o comando "show ip int brief vrf all", adicionando este comando como o valor do "input" no payload.
>>> # Troque as variáveis de acordo com o seu equipamento
>>> switch_ip = '192.168.208.10'
>>> url = 'https://' + switch_ip + '/ins/'
>>> sw_user='admin'
>>> sw_pwd='<sua senha>'
>>> headers={'content-type':'application/json'}
>>> payload={
"ins_api":{
"version": "1.0",
"type": "cli_show",
"chunk": "0",
"sid": "1",
"input": "show ip int brief vrf all",
"output_format": "json"
}
}
Para enviar as requisições HTTPS em Python, iremos utilizar a biblioteca requests, e também a biblioteca json, para a formatação de dados.
Um request HTTP possui alguns métodos, sendo os mais comuns GET e POST. Neste cenário iremos utilizar apenas o método POST, sendo o parâmetro do request as variáveis configuradas anteriormente. Como o certificado do switch virtual não é um certificado válido, iremos desabilitar a verificação do certificado através do parâmetro verify = False, de modo que o comando receba um warning de certificado mas continue sendo executado.
>>> import requests
>>> import json
>>> response = requests.post(url, data=json.dumps(payload), headers=headers,auth=( sw_user,sw_pwd),verify=False).json()
/usr/lib/python3/dist-packages/urllib3/connectionpool.py:999: InsecureRequestWarning: Unverified HTTPS request is being made to host '192.168.208.10'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
>>> output = json.dumps(response, indent=4, sort_keys=True)
>>> print (output)
{
"ins_api": {
"outputs": {
"output": {
"body": {
"TABLE_intf": {
"ROW_intf": [
{
"admin-state": "down",
"intf-name": "Eth1/1",
"iod": 5,
"ip-disabled": "FALSE",
"link-state": "down",
"prefix": "10.1.1.1",
"proto-state": "down",
"vrf-name-out": "default"
},
{
"admin-state": "up",
"intf-name": "mgmt0",
"iod": 2,
"ip-disabled": "FALSE",
"link-state": "up",
"prefix": "192.168.208.10",
"proto-state": "up",
"vrf-name-out": "management"
}
]
}
},
"code": "200",
"input": "show ip int brief vrf all",
"msg": "Success"
}
},
"sid": "eoc",
"type": "cli_show",
"version": "1.0"
}
}
Para extrair o dado, basta acessar o dado através da estrutura da resposta obtida. Neste exemplo, temos 2 interfaces, dentro da chave "ROW_intf". Essas podem ser acessadas através de um loop for, conforme a seguir.
>>> for interface in response['ins_api']['outputs']['output']['body']['TABLE_intf']['ROW_intf']:
... print(interface['intf-name'] + ':' + interface['prefix'])
...
Eth1/1:10.1.1.1
mgmt0:192.168.208.10
Note que o resultado dos dados é estruturado em JSON, o que torna muito fácil para estruturar os dados obtidos para um objeto Python, onde poderemos trabalhar com uma lógica personalizada, ou até mesmo salvar as informações numa base dados através de um servidor backend, com Django, por exemplo.
Esse procedimento torna fácil o acesso a configuração do switch via API, porém, temos casos em que o switch não possui a funcionalidade de API. Isso não significa que não podemos fazer automação através deles também, já que também podemos executar comandos via SSH. Nesses casos, temos algumas bibliotecas em Python para nos ajudar.
- Paramiko: Implementação Python para SSH para uso geral
- Netmiko: Simplificação do Paramiko para equipamentos de rede
- Napalm: Implementa diversas funções criando uma camada de abstração para equipamentos de rede multivendor
- Nornir: Framework de automação baseado em Napalm e Netmiko
- Ansible: Framework escrito em Python, baseado em playbooks para automação de equipamentos
Vamos explorar esse outro cenário numa próxima publicação. Até breve!