Lorsqu’il est nécessaire de mettre une interface CLI sur une application Python, c’est le package Click qui a ma préférence, mais quand il est souhaitable de mettre une interface web sur une application Python, mon choix oscille en permanence entre le micro framework Flask et le framework full-stack Django.
C’est le contexte et l’objectif visé (parfois aussi l’humeur du jour…) qui déterminent la meilleure stratégie. Démarrer avec Flask est très facile et la courbe d’apprentissage (subjective et empirique comme la plupart des lois scalantes) est rapide. Cependant, si l’objectif est de développer une application complète, on est rapidement obligé de rajouter des librairies en tant qu’extensions. D’un autre côté, la structuration mise en place par Django est un peu plus difficile à intégrer, mais tout est disponible et inclus pour réaliser une application complète, même une interface d’admin qui se génère automatiquement.
Dans la gamme des commutateurs Alcatel-Lucent Enterprise, appelée OmniSwitch, il existe deux systèmes d’exploitation : AOS6 et AOS8. La stratégie consiste à uniformiser de plus en plus les équipements avec AOS8.
AOS8 possède plus de méthodes d’automatisation que AOS6, mais les points communs entre les deux systèmes sont :
Zero-touch Provisionning
Serveurs DHCP / FTP / TFTP ou…
Serveur OmniVista 2500 on-premise ou en cloud (Cirrus)
Python / SSH avec mon module Netmiko en Off-box scripting
Je conseille d’utiliser Netmiko avec le framework Python Nornir
Ansible / SSH avec mes Network Modules disponibles dans la Galaxy
Outre des objectifs de disponibilité et de performance qui nous avaient été fixés par la direction du numérique de la Métropole et de la Ville de Perpignan, la Direction du Numérique souhaitait mettre en oeuvre une approche DevOps. Dans ce cadre là, notre rôle a consisté à accompagner les équipes sur les nouvelles technologies, méthodologies et outils nécessaires à la mise en œuvre de ces infrastructures innovantes.
Comme déjà évoqué, il existe plusieurs façons d’accéder aux informations et de les configurer sur des équipements Juniper Networks. Une de ces méthodes est de passer par les API REST (Representational State Transfer). Comme pour le CLI et NETCONF, les connexions REST, appelée parfois RESTful, se font au travers du process mgd. REST est considéré comme étant stateless car aucun contexte client n’est stocké sur le serveur entre les requêtes. Chaque requête contient toutes les informations nécessaires pour executer la requête et l’état de la session est conservé sur le client.
Pour des constructeurs du monde de l’automatisation, accéder aux informations de configurations est souvent synonyme d’analyser les chaînes de caractères retournées pour les formater à l’affichage et y chercher des éléments ciblés. Par exemple, le module Python TextFSM a été mis au point pour permettre l’accès par programme aux informations renvoyées par l’interface de ligne de commande (CLI) des équipements réseau.
Dans le cas de Juniper Networks, Junos possède un ensemble complet d’API : API XML (accessible localement ou à distance en utilisant le protocole sécurisé NETCONF), API REST et API JET. Il existe donc plusieurs façons d’accéder avec certitude et de façon structurée aux éléments souhaités.
Les processus les plus importants pour l’automatisation de Junos sont les processus de service mgd et JET (jsd). Mgd gère les demandes d’automatisation impliquant l’API XML de Junos, YANG, l’API REST et certaines fonctions SNMP. Le processus de service JET (jsd) gère les demandes d’automatisation qui utilisent l’API JET (Juniper Extension Toolkit). Le processus de gestion (mgd) est au cœur de toute automatisation Junos basée sur NECTONF. L’interface de ligne de commande de Junos est également gérée par le biais de mgd.
En 2016 j’ai écrit le module alcatel_aos pour Netmiko. Depuis, ce module Python fonctionne pour AOS6 et AOS8 et il est maintenu par Kirk Byers lorsque des changements majeurs sont effectués sur la librairie Netmiko.
Lorsqu’il s’agit de faire appel à Netmiko pour réaliser de l’automatisation sur OmniSwitch ALE, j’y adjoins le framework d’automatisation Nornir écrit en Python.
JSNAPy est un outil Open Source mis à disposition par Juniper. Il permet de valider la configuration d’un équipement et de comparer l’état d’une configuration avant et après une modification.
L’action peut être réalisée sur la configuration actuelle (snapcheck) ou sur le couple de configurations « avant et après » (PRE et POST).
Cet outil possède sa propre interface CLI pour être utilisé de façon autonome. Il est également possible de faire fonctionner JSNAPy à partir du modules Ansible galaxy juniper_junos_jsnapy ou directement à partir de scripts Python.
tests_include:
- test_interfaces_terse
test_interfaces_terse:
- rpc: get-interface-information
- iterate:
xpath: //physical-interface
id: './name'
tests:
- no-diff: description
err: "Test Failed! description for <{{id_0}}> got changed, before it was <{{pre['description']}}>, now it is <{{post['description']}}>"
info: "Test succeeded! description for <{{id_0}}> did not change, before it was <{{pre['description']}}>, now it is <{{post['description']}}>"
J’ai demandé une amélioration car le nom des fichiers snapshots est constitué avec l’adresse IP mais pas avec le port, et il n’est pas possible de changer le nom du fichier depuis un playbook Ansible utilisant juniper_junos_jsnappy. Lorsque JSNAPy est utilisé en environnement de simulation Vagrant, tous les devices ont la même adresse IP, ce n’est que le port qui les différencient. A suivre…
Même si Ansible est très bien pour faire du Human-driven Automation face à des équipements Juniper, je trouve gratifiant et plus pratique de développer directement en Python. Comme je l’ai déjà expliqué, j’utilise le protocole NETCONF simplifié par le micro framework PyEZ. Je me sers de PyEZ de façon transparente au travers de NAPALM, lui même piloté par le framework Nornir.
Lorsque l’on écrit des scripts, il peut rapidement y en avoir une grande quantité très proches les uns des autres et qui ne font, chacun, qu’une seule fonction.
C’est pour cette raison, que je rajoute le package Python Click qui permet de réaliser des interfaces CLI (Command-Line Interface) enrichie, de manière à limiter le nombre de scripts.
Prenons comme exemple un script dont l’objectif serait de faire des napalm_get et napalm_configure avec un CLI simplifié.
PyEZ, de son vrai nom junos-eznc, est un micro framework proposé en Open Source par Juniper afin de faciliter l’accès, à l’aide du protocole NETCONF, aux équipement tournant Junos . Comme le montre l’image, indépendamment de l’accès direct par le langage Python, ce micro framework est utilisé par d’autres outils comme Ansible, Salt ou JSNAPy.
Junos PyEZ est un package jnpr.junos qui contient les modules suivants :
device: Defines the Device class, which represents the device running Junos OS and enables you to connect to and retrieve facts from the device.
exception: Defines exceptions encountered when accessing, configuring, and managing devices running Junos OS.
factory: Contains code pertaining to Tables and Views, including the loadyaml() function, which is used to load custom Tables and Views.
facts: A dictionary-like object of read-only facts about the device. These facts are accessed using the facts attribute of a Device object instance.
op: Includes predefined operational Tables and Views that can be used to filter output for common operational commands.
resources: Includes predefined configuration Tables and Views representing specific configuration resources, which can be used to programmatically configure devices running Junos OS.
transport: Contains code used by the Device class to support the different connection types.
utils: Includes configuration utilities, file system utilities, shell utilities, software installation utilities, and secure copy utilities.
Pour les constructeurs leaders du domaine de l’automatisation de réseau, la librairie NAPALM (Network Automation and Programmability Abstraction Layer with Multivendor support) fournit des fonctions abouties. Une matrice de compatibilité permet de savoir sur quels constructeurs, les fonctions proposées sont supportées. Un des avantages est de pouvoir écrire des scripts qui effectuent une même tâche sur plusieurs types d’équipements différents sans avoir à prendre en compte les spécificités de chacun des systèmes. Avec quelques lignes en Python, il est possible de simuler le comportement idempotent d’Ansible.
Pour accéder aux équipements, NAPALM s’appuie sur les librairies suivantes :
EOS : pyeapi
Junos : junos-eznc
IOS-XR : pyIOSXR
NX-OS : pynxos
NX-OS SSH : netmiko
IOS : netmiko
NAPALM est une librairie présente dans de nombreux frameworks d’automatisation comme Ansible, Salt ou Nornir.
Outre NAPALM, deux autres librairies sont disponibles :
napalm-logs : bibliothèque Python qui écoute les messages syslog des périphériques réseau et renvoie les données structurées selon les modèles OpenConfig ou IETF YANG.
napalm-yang : YANG (RFC6020) est un langage de modélisation de données, c’est un moyen de définir l’apparence des données. La bibliothèque napalm-yang fournit un cadre d’utilisation des modèles définis avec YANG dans le contexte de la gestion de réseau. Il fournit des mécanismes pour transformer les données / configuration natives en YANG et inversement.