Préface
Bonne journée à tous!
Je travaille en tant qu'ingénieur réseau pour un grand opérateur de télécommunications, et sous mon contrôle il y a tout un zoo de divers équipements réseau, mais nous parlerons de commutateurs d'accès.
Cet article n'est pas un guide d'action, ce n'est pas la seule solution et ne prétend clairement pas être un scénario de la nomination de l'année, mais je veux partager cette création, et peut-être qu'elle sera utile à quelqu'un.
L'article fournira un bloc de code sous le spoiler, et ci-dessous sera une description avec des coupures et des explications sur la raison pour laquelle il en est ainsi et à quoi il sert.
Défi
Utilisez python3 spécifiquement. Le script doit pouvoir accéder aux commutateurs à partir de la liste, déterminer le type de fournisseur, donner la commande requise, enregistrer.
En fait, comment je suis arrivé à cela
Face à un petit problème de changement de configuration sur un grand nombre de commutateurs, je vais tout de suite faire une réserve sur le système d'administration centralisée des équipements réseau dont nous disposons, de nombreux développements de mes collègues sous forme de scripts pour faciliter le travail manuel sont également disponibles, principalement bash, perl.
Mais pour moi, il était important de faire quelque chose de différent, car J'ai commencé à apprendre le python récemment et je dois améliorer mes compétences en programmation, et mon outil devrait ressembler à un marteau (facile à utiliser et facile à entretenir). Si l'intérêt persiste, je demande un chat.
Googler et ne pas trouver la bonne solution (comme si sur les forums cette question était posée, mais tout allait mal là-bas), j'ai décidé de commencer à écrire mon propre script.
Nous avons les commutateurs suivants:
- Raisecom
- Qtech rev. 1.0
- Qtech rev. 2.0 (différence de syntaxe)
- Eltex
- Lien D
- Spawn Frankenstein switch avec un museau de Qtech rev 1.0, et du fer de Raisecom nous l'appellerons ROS
Tout d'abord, importez les bibliothèques requises:
import telnetlib import time import os import sys import getpass import pexpect from telnetlib import Telnet import datetime import subprocess
Dans un premier temps, nous décrivons la fonction de définition du fournisseur, car a décidé d'utiliser deux méthodes:
1) Supposons de quel type de fournisseur il s'agit (à l'invitation à entrer la connexion) car j'ai remarqué que c'est différent pour tout le monde: Qtech (connexion :), Raisecom et ROS (Connexion :), Eltex (Nom d'utilisateur :), D-link (Nom d'utilisateur).
2) après la connexion - assurez-vous que le premier élément a été effectué sans erreur et pour une meilleure identification de l'interrupteur sur lequel nous sommes.
Toute la fonction est sous le spoiler. Nous déclarons des variables globales qui seront visibles par l'ensemble du script:
global ver_status global sab_versus global versus
les variables a, d, f, h, j, k, n stockent les mots-clés par lesquels nous déterminerons par la suite le modèle du commutateur.
a = 'Serial No.:1405'
Après avoir ouvert le fichier ver.txt, nous le lisons ligne par ligne et vérifions l'entrée par mots-clés, car la fonction find () renvoie -1 si ce résultat est négatif, et nous allons construire des branches.
parser=open('servers_&_log/ver.txt', 'r')
...
Je donne un exemple de partie du code, le reste sous le spoiler ci-dessus.
Le contenu de ce fichier sera décrit ci-dessous. Après toutes les manipulations et la définition du fournisseur, supprimez le fichier ver.txt.
Déclaration des variables principales, corps de la boucle principale user='user' password='password' komm=open('servers_&_log/komm.txt') log=open('servers_&_log/log.txt','a')
J'ai décidé de ne pas déranger et de définir les variables avec le nom d'utilisateur et le mot de passe dans le corps, je sais que ce n'est pas de la sécurité, je travaille dessus.
Ouvrez le fichier pour les journaux et la liste des commutateurs
komm=open('servers_&_log/komm.txt') log=open('servers_&_log/log.txt','a')
Après avoir utilisé la boucle for, lisez la ligne avec l'adresse IP du commutateur
for host in komm.readlines(): print('connect....',host) vend = ''
Nous vérifions sa disponibilité
response = os.system('ping -c 1 ' + host)
S'il est accessible à l'aide de la bibliothèque pexpect, nous essayons de nous connecter via telnet ici à cette itération et la première vérification à l'invitation a lieu, dont j'ai parlé au début.
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)
La variable vend obtiendra une valeur de 0 à 3 inclus, et en fonction de l'invite de connexion qu'elle voit, une autre branche sera formée.
À partir de ce morceau de code, un lecteur attentif peut remarquer que je fais une connexion au commutateur et ferme immédiatement la connexion, et ce n'est pas sans raison. J'ai essayé d'utiliser uniquement la bibliothèque telnetlib, mais lors du premier test, le script se bloquait et tombait périodiquement par timeout, et cette béquille m'aide beaucoup.
Après avoir fermé la connexion, nous ne nous reconnectons qu'en utilisant déjà la bibliothèque telnetlib.
Afin d'éviter de tomber des erreurs, nous avons déjà vérifié ci-dessus que le commutateur est accessible, et excluons l'interruption du script pendant le fonctionnement en raison d'un commutateur inactif, enveloppez tout dans un essai sauf le bloc.
Il y a eu des cas répétés où sur 100 commutateurs, un ne s'est pas laissé entrer.
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)
...
Si tout va bien et que nous sommes connectés, nous devons saisir un nom d'utilisateur et un mot de passe,
nous savons avec certitude que toute invite de deux points utilise un deux-points.
Nous l'attendons donc
tn.read_until(b':')
Après avoir entré la connexion
tn.write((user +'\n').encode('ascii'))
En attente de deux points du mot de passe
tn.read_until(b':')
Entrez le mot de passe
tn.write((password + '\n').encode('ascii'))
Et nous attendons 3 secondes (répit, sinon nous avons fait tellement de travail)
time.sleep(3)
Après avoir attendu l'invitation
tn.read_until(b'#',timeout=20)
Ici, à ce stade, nous passons au deuxième niveau pour vérifier le fournisseur.
if vend == 0:
Parce que nous avons supposé que nous sommes arrivés à Qtech, et si vous lisez attentivement, alors dans notre zoo, il existe deux versions de qtech qui diffèrent dans la syntaxe, nous devons encore nous réconcilier.
Par conséquent, nous donnons la commande show ver, mettons toute la sortie dans le fichier ver.txt
et appelez la procédure who_is (), que j'ai décrite ci-dessus. L'équipe show ver est universelle pour tous les Qtech, Raisecom, Eltex,
Malheureusement, D-link ne comprend pas et il doit dire montrer swich, mais nous sommes intelligents et n'avons pas vainement introduit une itération avec la définition supposée d'un fournisseur.
if vend == 3:
Donc, immédiatement, une petite remarque après avoir entré show swich, le commutateur affiche des informations incomplètes et attend que l'utilisateur appuie sur n'importe quelle touche pour une sortie supplémentaire, et donc nous envoyons ensuite le caractère "a" pour afficher des informations complètes.
tn.write(('a' + '\n').encode('ascii'))
Pour éviter cela, vous pouvez désactiver le clipadding
C'est là que la vérification du fournisseur se termine et avec une probabilité de 99%, nous pouvons supposer que nous avons correctement identifié le modèle du commutateur et que nous pouvons procéder à la configuration.
Pour chaque commutateur, nous avons un fichier séparé avec un ensemble de commandes.
Bloc de configuration ... 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)
Une fois que la fonction a fonctionné et renvoyé la variable ver_status, nous pouvons continuer à travailler avec la branche, car nous savons exactement quel commutateur est actuellement en ligne.
Tout d'abord, nous donnons au commutateur la commande show ver et écrivons la sortie dans le journal (à propos de d-link, rappelez-vous que nous lui donnons la commande sh sw)
tn.write(('show ver' + '\n').encode('ascii')) print((tn.read_until(b'#').decode('ascii')), file=log)
Assurez-vous de garder des compteurs pour identifier les non-conformités.
counter_qtech1_0+=1
Nous ouvrons un fichier avec des commandes
komand_qtech1_0=open('servers_&_log/komand_qtech_ver1.0.txt')
L'ordre des commandes dans le fichier doit être le même que l'administrateur les saisirait manuellement
Un exemple:
conf
vlan 2525
name SPD
int ethe 1/1
sw mode access
sw acc vl 2525
exit
exit
save
y
Ensuite, tout est conforme au scénario - nous lisons le fichier jusqu'à la fin des lignes et nous les exécutons
for kommand in komand_qtech1_0.readlines(): tn.write((kommand.replace('\n', '') + '\n').encode('ascii'))
Après avoir quitté la boucle, nous indiquons la sortie du commutateur et lisons toutes les sorties dans un fichier, et donc nous ne le faisons qu'avec qtech1.0, car parfois un script colle en prévision de quelque chose et c'est avec ce switch, pour ne pas faire d'histoires, cette solution me paraissait plus élégante.
Une fois le commutateur configuré, nous augmentons le compteur total d'une unité.
counter_komm+=1
Et nous recommençons, lisons la ligne suivante du fichier avec les commutateurs, déterminons le modèle et réalisons la configuration.
Après avoir quitté le cycle principal, vous devez faire un résumé du travail effectué,
à la fin du journal, nous entrons tous les modèles que nous avons traités et la date est obligatoire, eh bien, comment pourrait-il en être sans.
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()
Ce script a été traité à plusieurs reprises et le processus ne s'arrêtera pas là.
Merci à tous pour votre attention. La critique constructive est la bienvenue.
Tout le code sous le spoiler.