4
Pour contourner les difficultés d’utilisation de la librairie Paramiko et gagner du temps, l’utilisation d’une librairie complémentaire venant en surcouche peut s’avérer une bonne solution. Netmiko a été conçue pour simplifier le dialogue SSH avec les équipements d’un grand nombre de constructeurs d’équipements de réseau. Pour avoir réalisé la partie Alcatel AOS de la librairie, je peux attester de sa qualité et de la rigueur avec laquelle la conception est contrôlée et validée.
Les objectifs de cette bibliothèque sont les suivants :
- Élaborer avec succès une connexion SSH à l’équipement
- Simplifiez l’exécution des commandes show et la récupération des données de sortie
- Simplifier l’exécution des commandes de configuration, y compris éventuellement des actions de validation
- Faire ces actions pour un large éventail de fournisseurs et de plates-formes de réseau
Sans l’appui de cette librairie, l’utilisation directe de la bibliothèque Paramiko peut impliquer de faire face à des difficultés récurrentes de traitement de certains caractères de retour lors de l’établissement de la connexion SSH ou lors de l’envoi de certaines commandes.
Fichier colors.py
INFO = "\033[1;34;40m" SUCCESS = "\033[1;32;40m" ERROR = "\033[1;31;40m" NORMAL = "\033[0;37;40m"
Fichier ale_commands.py
# Defines commands and add a field to search if necessary system = { 'command': 'show system', 'search': 'Up Time' } vlan = { 'command': 'show vlan', } topology = { 'command': 'show stack topology', } all_commands = [ system, vlan, topology ]
Fichier ale_devices.py
ale_lab_1 = { 'device_type': 'alcatel_aos', 'ip': '192.168.2.253', 'username': 'user', 'password': 'pass', } ale_lab_3 = { 'device_type': 'alcatel_aos', 'ip': '192.168.1.154', 'username': 'user', 'password': 'pass', } all_devices = [ ale_lab_1, ale_lab_3 ]
Fichier ale_netmiko.py
#!/usr/bin/env python # Use devices.py and commands.py from netmiko import ConnectHandler from colors import * from ale_devices import all_devices from ale_commands import all_commands for a_device in all_devices: try: net_connect = ConnectHandler(**a_device) print ("\n\n{0}{1} Device {2} {3}{4}" .format(SUCCESS, ">"*10, a_device["ip"], "<"*10, NORMAL)) for a_command in all_commands: output = net_connect.send_command(a_command['command']) print ("\nCommand: {0}{1}{2} \n" .format(INFO, a_command["command"], NORMAL)) try: a_command['search'] for single_line in output.splitlines(): if a_command['search'] in single_line: print (single_line) except: print (output) print ("\n") net_connect.disconnect() except: print ("\n\n{0}{1} Device {2} {3}{4}" .format(ERROR, ">"*10, a_device["ip"], "<"*10, NORMAL))
Ce script va itérer sur tous les équipements pour exécuter l’ensemble des commandes. Si l’une des commandes attend une information particulière devant être trouvée et affichée, celle-ci déclare un champ search. Lorsque le nombre d’équipements augmente, il est possible d’accélérer le traitement, et comme le ferait Ansible, lancer en parallèle plusieurs tâches grâce à la librairie Python threading. Mais face à un grand nombre d’équipements, il n’est pas judicieux d’imaginer lancer en parallèle la totalité des traitements. Dans ce cas, il est possible de travailler par lots, en limitant le nombre de « threads », grâce à ThreadPool du module multiprocessing.dummy.