Python para automatizar métodos REST
Devnet é a palavra do momento.
Até hoje, nós, profissionais da área de infraestrutura, não precisávamos saber programar. Ok, o conhecimento em linguagens de programação sempre foi muito útil para automatizarmos criação de scripts e rotinas de teste, mas nunca foi um grande requisito no currículo de um CCIE.
Hoje em dia as coisas estão mudando, e conhecimentos básicos de desenvolvimento de código estão se tornando tão importante quanto entender tabelas de roteamento, fluxo de uma chamada SIP ou criação de ACLs.
No entanto, sou da opinião que ninguém aqui precisa devorar o livro do Cormen, se tornar o guru da lógica de programação, e saber implementar o melhor algoritmo de ordenação do mundo (aquelas coisas que a gente via na faculdade). Na realidade, entendo que até a lógica de programação em si vai ser o de menos para as coisas que vamos começar a desenvolver (e nesse momento, começo a receber pedrada dos desenvolvedores… hehehe).
Posso estar muito enganado quanto ao futuro, mas para esse momento, esse exato momento que você lê este artigo, imagino que os códigos que passaremos a desenvolver num futuro imediato são estruturas básicas de loops e condicionais, leitura de arquivos de entrada, etc. Coisas relativamente simples se comparado com o desenvolvimento de uma grande aplicação de fato.
Resolvi escrever esse artigo para te ajudar a dar os primeiros passos nisso. Apesar de eu utilizar o Communications Manager como exemplo, o conhecimento será útil para qualquer um que trabalha hoje com algum produto que aceite REST APIs, que hoje em dia é basicamente todos.
A proposta desse artigo é dar um exemplo de código que automatiza o envio de algum método REST. Por exemplo, o POST. Vou usar como estudo de caso uma situação real que tive em um cliente. Precisávamos alterar mais de 700 devices no CUCM, atribuindo o “Owner User ID”. Para quem mexe com CUCM sabe que não é possível criar uma rotina dessa nativa na aplicação com o Bulk Administration, a não ser que se crie um arquivo de import de telefones, e rodar o job sobrescrevendo tudo, o que é no mínimo arriscado.
Bom, a primeira coisa que você vai precisar saber é qual evento REST faz o que você precisa na aplicação que você está mexendo. Confesso que é aqui que mora a parte mais complexa do negócio, e justamente isso eu não vou poder te ajudar, porque cada caso é um caso. Mas nessas horas, o Google é um grande amigo, e o site developer.cisco.com é a sua melhor referência.
No meu caso, procurando na Internet, descobri que para alterar o Owner User ID de um device no CUCM, bastava eu enviar um POST para https://<CUCM>:8443/axl/ com o seguinte conteúdo, substituindo o userID e deviceID:
<SOAP-ENV:Envelope xmlns:SOAP-ENV=”http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd=”http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Body>
<axl:updatePhone xmlns:axl=”http://www.cisco.com/AXL/API/1.0" sequence=”12055">
<ownerUserName>userID</ownerUserName>
<name>deviceID</name>
</axl:updatePhone>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
O primeiro passo é testar isso manualmente. Para isso, eu utilizo uma aplicação chamada Postman. Nela, é possível mandar um método GET, POST, PUT, e ver se funciona. A carinha dele é assim, bem intuitiva:
Legal, agora eu já sabia como alterar manualmente o Owner User ID de um device. Só assim pelo Postman, mesmo fazendo um por um, seria muito mais rápido do que usando a interface Web do CUCM. Mas a ideia era melhorar ainda mais. Eu queria criar um arquivo CSV com os userIDs e deviceIDs, e automatizar essa operação.
Agora vem a parte do Python! \o/
Antes de mais nada, precisamos baixar o Python e um IDE de desenvolvimento, que no meu caso escolhi o PyCharm (Community Edition). A instalação de ambos é basicamente Next, Next, Finish, sem segredo nenhum. Só recomendo na instalação do Python você marcar o checkbox “Add Python to PATH”, para você pode invocar o Python do prompt de comando do Windows.
Faremos tudo de dentro do PyCharm, porque de lá já é possível compilar e executar o código. Então primeiramente iremos em File > New Project, e criaremos um novo projeto. Dentro da pasta do projeto, criaremos um novo arquivo Python:
Já vamos aproveitar e criar o nosso arquivo CSV, selecionando a opção “File”. O conteúdo do nosso CSV, nesse estudo de caso, será assim:
darth.vader,SEPAAAABBBBCCCC
luke.skywalker,SEPBBBBCCCCDDDD
yoda.master,SEPCCCCDDDDEEEE
Neste exemplo, estou listando o User ID e o Device Name, que servirão de input no nosso código.
Legal, agora que temos a nossa estrutura formada, vamos pensar um pouquinho na lógica. Basicamente o que precisamos que a nossa aplicação faça é:
- Abrir o arquivo CSV
- Ler a primeira linha, guardando o userID e o Device
- Rodar o POST substituindo essas variáveis
- Retornar uma mensagem se deu certo ou não
- Ler a próxima linha e repetir o processo até que acabe o arquivo
- Fechar o arquivo
Como eu disse lá em cima, a lógica em si é extremamente simples! Todo o resto é questão de aprender a linguagem. E nisso o Python também é ótimo, porque é uma linguagem bastante fácil de aprender. E o melhor de tudo é que ele possui inúmeras bibliotecas com códigos prontos, você só precisa importá-las. Recomendo que assista um cursinho online de Python, tem vários por aí… pelo menos o básico, pois acho que até a parte de Orientação a Objetos não sei se é tão necessária assim para o propósito do que estamos criando.
Para esse nosso exemplo, vamos utilizar duas bibliotecas: uma chamada “requests” para enviar os métodos REST, e outra chamada “csv”, para fazer a leitura de um arquivo CSV. A biblioteca requests não vem instalada por padrão, então para instalá-la, basta abrir o prompt de comando do Windows e digitar:
pip3 install requests
Agora vamos começar a construir o código!
Primeiro, vamos tentar fazer um POST, só para ver se está funcionando. Lembrando que já testamos esse POST lá no Postman, aqui é só para ver ele funcionando via Python. A sintaxe para invocar o post é:
requests.post(url,verify=False,auth=(username, password),data=data)Onde:
url = https://<CUCM>:8443/axl/
verify=False: para que o script não faça a verificação de certificado
username = usuário de admin do CUCM
password = senha do usuário
data = conteúdo do POST
Então o primeiro passo seria importar a biblioteca requests, que já instalamos lá em cima, popular essas variáveis e enviar o POST:
import requestsurl = "https://192.168.100.10:8443/axl/"
username = "admin"
password = "C1sc0123"data = """
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Body>
<axl:updatePhone xmlns:axl="http://www.cisco.com/AXL/API/1.0" sequence="12055">
<ownerUserName>darth.vader</ownerUserName>
<name>SEPAAAABBBBCCCC</name>
</axl:updatePhone>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
"""requests.post(url,verify=False,auth=(username, password),data=data)
Para executar o código, basta clicar no arquivo py com o botão direito, e selecionar “Run”. O POST deve acontecer, mas veja que ao fazer isso, não temos nenhuma indicação se o POST foi executado com sucesso ou não. Para resolver isso, vamos jogar o retorno do requests.post em uma variável p, e retornar o atributo status_code, assim:
p = requests.post(url,verify=False,auth=(username, password),data=data)print(p.status_code)
Agora, ao executar o código, a console vai retornar “200”, que significa que foi executado com sucesso. Caso contrário, poderia dar um “401” (Forbidden), “503” (Internal Server Error), etc. São as respostas padrões do HTTP.
Bom, agora temos que fazer o código conseguir abrir o nosso arquivo CSV e colocar esse POST dentro de um loop, certo? No Python, é muito simples de abrir um arquivo e ler as suas linhas. E com a biblioteca csv, é fácil jogar cada valor em uma variável.
Para abrir um arquivo do jeito mais fácil, basta fazer:
arquivo = open('lista_usuarios.csv')
Mas existe uma forma mais elegante de se fazer isso, que é com o with open:
with open ('lista_usuarios.csv') as arquivo:
Dessa forma, é mais fácil tratar exceções quando, por exemplo, o arquivo não existe, ou por algum motivo o código não conseguir abrí-lo. Note que o with open termina com um dois pontos (:). Isso significa que ele abre um bloco de comandos. No Python, diferente de outras linguagens como C, ao abrir um bloco de comandos, não preciso delimitá-lo com chaves ({}). Basta identar com 4 espaços (ou um TAB no PyCharm). Tudo que estiver identado fará parte do bloco.
Agora, com a ajuda da biblioteca csv, iremos ler cada linha do arquivo, e jogar o userID e deviceID nas variáveis usuario e device. O csv.reader faz com que cada valor separado por virgula seja armazenado em um índice de uma matriz.
Com um simples loop for, é possível ler cada linha do CSV. O Python já tem essa inteligência de ler cada linha até que acabe o arquivo:
import requests
import csvurl = "https://192.168.100.10:8443/axl/"
username = "admin"
password = "C1sc0123"with open ('lista_usuarios.csv') as arquivo:
readCSV = csv.reader(arquivo, delimiter=",")
for linha in readCSV:
usuario = linha[0]
device = linha[1]arquivo.close()
Estamos quase lá! Agora basta substituir as variáveis dentro do conteúdo que vamos mandar dentro do POST:
url = "https://192.168.100.10:8443/axl/"
username = "admin"
password = "C1sc0123"
with open ('lista_usuarios.csv') as arquivo:
readCSV = csv.reader(arquivo, delimiter=",")
for linha in readCSV:
usuario = linha[0]
device = linha[1]
data = """
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Body>
<axl:updatePhone xmlns:axl="http://www.cisco.com/AXL/API/1.0" sequence="12055">
<ownerUserName>""" + usuario + """</ownerUserName>
<name>""" + device+ """</name>
</axl:updatePhone>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
"""
p = requests.post(url,verify=False,auth=(username, password),data=data)
Esse código já está funcional! Agora vamos só colocar um print a cada iteração, indicando se a operação foi feita com sucesso. Já sabemos que se o status retornar 200, é porque funcionou, senão, é porque deu algum erro. Então vamos fazer assim:
if p.status_code == 200:
print("Sucesso! Usuario {} foi associado ao device {} com sucesso".format(usuario,device))
else:
print("Erro! O Usuario {} nao foi associado ao device {}.".format(usuario,device))
Ou seja, se o status for 200, retornaremos a mensagem “Sucesso! Usuario {usuario} foi associado ao device {device} com sucesso”. Se não, retornaremos “Erro! O usuario {usuario} nao foi associado ao device {device}”. A sintaxe desse print é só uma forma de fazermos isso…
E aqui temos o nosso código completinho:
import requests
import csv
url = "https://192.168.100.10:8443/axl/"
username = "admin"
password = "C1sc0123"
with open ('lista_usuarios.csv') as arquivo:
readCSV = csv.reader(arquivo, delimiter=",")
for linha in readCSV:
usuario = linha[0]
device = linha[1]
data = """
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Body>
<axl:updatePhone xmlns:axl="http://www.cisco.com/AXL/API/1.0" sequence="12055">
<ownerUserName>""" + usuario + """</ownerUserName>
<name>""" + device+ """</name>
</axl:updatePhone>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
"""
p = requests.post(url,verify=False,auth=(username, password),data=data)
if p.status_code == 200:
print("Sucesso! Usuario {} foi associado ao device {} com sucesso".format(usuario,device))
else:
print("Erro! O Usuario {} nao foi associado ao device {}.".format(usuario,device))
arquivo.close()
Esse exemplo de código pode ser usado para qualquer aplicação que aceite métodos REST. No caso de Collaboration, podemos usar no CCX, CMS, Webex, etc. Praticamente tudo hoje em dia suporta REST APIs.
Este é apenas o primeiro passo de um mundo de coisas que podemos fazer conforme vamos avançando na linguagem, e conforme vão surgindo as demandas.
E aí, bora aprender Python?
Sobre o autor
Bruno Nonogaki é engenheiro de redes na NTT. Graduado em Ciência da Computação pela Unicamp, e certificado CCIE Collaboration desde 2012. Atua há mais de 10 anos no mercado de TI, tendo desenvolvido diversos projetos de Colaboração com tecnologias Cisco.