Prefácio
Bom dia a todos!
Trabalho como engenheiro de rede de uma grande operadora de telecomunicações e, sob meu controle, existe um zoológico inteiro de vários equipamentos de rede, mas falaremos sobre switches de acesso.
Este artigo não é um guia de ação, não é a única solução e claramente não pretende ser um roteiro da indicação do ano, mas quero compartilhar essa criação, e talvez seja útil para alguém.
O artigo fornecerá um bloco de código sob o spoiler e, a seguir, haverá uma descrição com recortes e explicações sobre por que é assim e para que serve.
Desafio
Use python3 especificamente. O script deve ser capaz de acessar os comutadores da lista, determinar que tipo de fornecedor, fornecer o comando necessário, log.
Na verdade, como cheguei a isso
Diante de um pequeno problema de alterar a configuração em um grande número de comutadores, farei imediatamente uma reserva sobre o sistema de administração centralizada para equipamentos de rede que temos, muitos desenvolvimentos de meus colegas na forma de scripts para facilitar o trabalho manual também estão disponíveis, principalmente o bash, perl.
Mas para mim era importante fazer algo diferente, porque Comecei a aprender python recentemente e preciso atualizar minhas habilidades em programação, e minha ferramenta deve parecer um martelo (fácil de usar e fácil de manter). Se ainda houver interesse, peço um gato.
Pesquisando no Google e não encontrando a solução adequada (como se nos fóruns essa questão tivesse sido levantada, mas estava tudo errado lá), decidi começar a escrever meu próprio script.
Temos as seguintes opções:
- Raisecom
- Qtech rev. 1.0
- Qtech rev. 2.0 (diferença na sintaxe)
- Eltex
- D-link
- Spawn Frankenstein switch com um focinho de Qtech rev 1.0, e ferro da Raisecom chamaremos ROS
Primeiro, importe as bibliotecas necessárias:
import telnetlib import time import os import sys import getpass import pexpect from telnetlib import Telnet import datetime import subprocess
Inicialmente, descrevemos a função de definição de fornecedor, porque decidiu usar dois métodos:
1) Suponha que tipo de fornecedor (no convite para entrar no login), pois notei que é diferente para todos: Qtech (login :), Raisecom e ROS (login :), Eltex (nome do usuário :), D-link (nome de usuário).
2) após o login - verifique se o primeiro item foi concluído sem erros e para uma melhor identificação de qual opção estamos ativados.
Toda a função está sob o spoiler. Declaramos variáveis globais que serão visíveis para todo o script:
global ver_status global sab_versus global versus
as variáveis a, d, f, h, j, k, n armazenam as palavras-chave pelas quais determinaremos subsequentemente o modelo do comutador.
a = 'Serial No.:1405'
Após abrir o arquivo ver.txt, lemos linha por linha e verificamos a entrada por palavras-chave, porque a função find () retorna -1 se esse resultado for negativo, e construiremos ramificações.
parser=open('servers_&_log/ver.txt', 'r')
...
Dou um exemplo de parte do código, o restante sob o spoiler acima.
O conteúdo deste arquivo será descrito abaixo. Após todas as manipulações e definição do fornecedor, exclua o arquivo ver.txt.
Declaração das principais variáveis, corpo do loop principal user='user' password='password' komm=open('servers_&_log/komm.txt') log=open('servers_&_log/log.txt','a')
Decidi não me incomodar e definir as variáveis com nome de usuário e senha no corpo, sei que não é segurança, estou trabalhando nisso.
Abra o arquivo para os logs e a lista de opções
komm=open('servers_&_log/komm.txt') log=open('servers_&_log/log.txt','a')
Depois de usar o loop for, leia a linha com o endereço IP do switch
for host in komm.readlines(): print('connect....',host) vend = ''
Verificamos a disponibilidade
response = os.system('ping -c 1 ' + host)
Se estiver acessível usando a biblioteca pexpect, tentaremos conectar via telnet aqui nesta iteração e ocorrerá a primeira verificação no convite, sobre a qual escrevi no começo.
if response == 0: telnet = pexpect.spawn('telnet ' + host,timeout=40) vend = telnet.expect(['login:', 'Login:', 'User Name:', 'Username']) telnet.close() tn = Telnet(host.replace('\n', ''), 23,30)
A variável vend obterá um valor de 0 a 3, inclusive, e dependendo do prompt de login exibido, uma outra ramificação será formada.
A partir desse código, um leitor atento pode perceber que estou fazendo uma conexão com o switch e fechando imediatamente a conexão, e isso não é sem razão. Tentei usar apenas a biblioteca telnetlib, mas no primeiro teste, o script travou e caiu periodicamente com o tempo limite, e essa muleta ajuda muito.
Depois de fechar a conexão, fazemos a reconexão apenas usando a biblioteca telnetlib.
Para evitar erros, já verificamos acima se o comutador está acessível e excluímos a interrupção do script durante a operação devido a um comutador inativo, envolva tudo em uma tentativa, exceto no bloco.
Houve casos repetidos em que de 100 interruptores, um não se deixava entrar
try: print('Ok'+'\n') tn.read_until(b':') tn.write((user +'\n').encode('ascii')) tn.read_until(b':') tn.write((password + '\n').encode('ascii')) time.sleep(3) tn.read_until(b'#',timeout=20) except: print('connection refused' + '\n') f = open('servers_&_log/log.txt', 'a') print(host, 'connection refused', file=log) print('#' * 100, host, file=log)
...
Se está tudo bem e estamos conectados, precisamos inserir um nome de usuário e senha,
sabemos com certeza que qualquer prompt de dois pontos usa dois pontos.
Então, estamos esperando por ele
tn.read_until(b':')
Depois de entrar no login
tn.write((user +'\n').encode('ascii'))
Aguardando dois pontos da senha
tn.read_until(b':')
Digite a senha
tn.write((password + '\n').encode('ascii'))
E esperamos 3 segundos (pausa, caso contrário, fizemos muito trabalho)
time.sleep(3)
Depois de esperar pelo convite
tn.read_until(b'#',timeout=20)
Aqui, nesta etapa, passamos para o segundo nível para verificar o fornecedor.
if vend == 0:
Porque assumimos que chegamos ao Qtech e, se você ler atentamente, em nosso zoológico existem duas versões do qtech que diferem na sintaxe, ainda precisamos reconciliar.
Portanto, damos o comando show ver, colocamos toda a saída no arquivo ver.txt
e chame o procedimento who_is (), que eu descrevi acima. A equipe show ver é universal para todas as empresas Qtech, Raisecom, Eltex,
Infelizmente, o D-link não entende e ele precisa dizer show swich, mas somos inteligentes e não em vão introduzimos uma iteração com a suposta definição de fornecedor.
if vend == 3:
Então, imediatamente, uma pequena observação depois de entrar no show swich, o comutador exibe informações incompletas e aguarda o usuário pressionar qualquer tecla para obter mais informações e, portanto, enviamos o caractere "a" para exibir informações completas.
tn.write(('a' + '\n').encode('ascii'))
Para evitar isso, você pode desativar o recorte
É aqui que a verificação do fornecedor termina e, com uma probabilidade de 99%, podemos assumir que identificamos corretamente o modelo do comutador e podemos prosseguir com a configuração.
Para cada opção, temos um arquivo separado com um conjunto de comandos.
Bloco de configuração ... elif ver_status == 'qtech_rev_1.0': tn.write(('show ver' + '\n').encode('ascii')) print((tn.read_until(b'#').decode('ascii')), file=log) counter_qtech1_0+=1 komand_qtech1_0=open('servers_&_log/komand_qtech_ver1.0.txt') for kommand in komand_qtech1_0.readlines(): tn.write((kommand.replace('\n', '') + '\n').encode('ascii')) tn.write(('exit' + '\n').encode('ascii')) print(tn.read_all().decode('ascii'), file=log) print(' qtech1.0') print('Qtech rev1.0 ' + host, file=log) print('#' * 100, file=log)
Depois que a função funcionou e retornou a variável ver_status, podemos continuar trabalhando com a ramificação, porque sabemos exatamente qual opção está atualmente em jogo.
Primeiro, damos ao switch o comando show ver e escrevemos a saída no log (sobre o d-link, lembre-se de dar o comando sh sw)
tn.write(('show ver' + '\n').encode('ascii')) print((tn.read_until(b'#').decode('ascii')), file=log)
Certifique-se de manter contadores para identificar não-conformidades.
counter_qtech1_0+=1
Abrimos um arquivo com comandos
komand_qtech1_0=open('servers_&_log/komand_qtech_ver1.0.txt')
A ordem dos comandos no arquivo deve ser a mesma que o administrador os digitaria manualmente
Um exemplo:
conf
vlan 2525
name SPD
int ethe 1/1
sw mode access
sw acc vl 2525
exit
exit
save
y
Então tudo está de acordo com o cenário - lemos o arquivo até o final das linhas e os executamos
for kommand in komand_qtech1_0.readlines(): tn.write((kommand.replace('\n', '') + '\n').encode('ascii'))
Depois de sair do loop, informamos à saída do switch e lemos toda a saída em um arquivo, e o fazemos apenas com qtech1.0, porque Às vezes, um script se antecipa a algo e é com essa opção, para não causar confusão, essa solução me pareceu mais elegante.
Após a configuração do switch, aumentamos o contador total em um.
counter_komm+=1
E começamos tudo de novo, lemos a próxima linha do arquivo com os comutadores, determinamos o modelo e fazemos a configuração.
Depois de sair do ciclo principal, você precisa fazer um resumo do trabalho realizado,
no final do log, inserimos todos os modelos que processamos e a data é obrigatória, bem, como poderia ser sem ele.
print('\n\n\n : ', counter_komm,file=log) print('\n\nD-link:', counter_dlink,'\nQtech ver1.0:', counter_qtech1_0,'\nROS:', counter_ROS,'\nRaisecom:',counter_raisecom,'\nEltex:', counter_eltex,'\nQtech ver2.0 :', counter_qtech2_0,file=log) print('\n: ', datetime.datetime.now().isoformat(),'\n', '#'*100,'\n\n\n\n\n',file=log) verinfo.close() log.close()
Este script foi processado repetidamente e o processo não para por aí.
Obrigado a todos pela atenção. Críticas construtivas são bem-vindas.
Todo o código sob o spoiler.