Nornir, Netmiko et Template Text Parser

Les développements Python, dans le domaine de l’automatisation réseau, ont tout à gagner à utiliser le Framework Nornir. Celui-ci propose plusieurs méthodes pour accéder aux équipements. Chacune de ces méthodes a ses avantages et inconvénients et surtout elles ne sont pas toujours applicables à tous les constructeurs.

La méthode adressant le plus grand nombre de constructeurs est sans aucun doute Netmiko. Cette souplesse vient du fait que l’idée consiste à initier une connexion avec chacun des équipements pour leur envoyer des commandes et récupérer le résultat de la commande au travers du canal qui a été ouvert. Ce qui est reçu en retour est le même texte qui se serait affiché à l’écran si la manipulation avait été faite manuellement.

Analyser les informations qui sont retournées dans ces conditions, relève d’une pratique qui s’appelle le « Screen Scraping ». Il s’agit majoritairement d’utiliser des expressions régulières (regex) pour extraire du texte les informations recherchées. Des librairies ont été mises au point pour simplifier cette analyse et pour retourner les informations recherchées dans une structure de données utilisable programmatiquement. Qui plus est, ces librairies ont été intégrées dans le module Netmiko et par voie de conséquence, elles sont utilisables dans le Framework Nornir.

Ces outils utilisés par Netmiko, appelés « Parser », se comptent au nombre de trois : TextFSM, TTP et Genie. Celui qui m’intéresse plus particulièrement ici est le plus récent « Template Text Parser » ou TTP. L’originalité de ce dernier est d’utiliser une sorte de modèle inspiré du langage Jinja2 (utilisé à l’envers, car le template sert à analyser le texte) pour construire les templates qui vont servir à analyser les informations brutes retournées. Détailler toute sa puissance serait long et la documentation reste la meilleure source d’information sur le sujet. Il faut noter que TTP dispose d’un mode d’utilisation CLI qui simplifie la mise au point des templates avant leur utilisation dans des programmes Python.

Arista lab topology
Topologie cEOS-lab

Pour illustrer l’utilisation de TTP, un lab Arista construit avec cEOS-lab, containerlab et multipass va servir de base à la démonstration. Une commande show version sur un switch virtuel Arista renvoie les informations affichée ci-dessous.

show version Arista cEOS-lab
show version

Il s’agit de texte brut avec des informations qui ne sont pas structurées. Voici un exemple simple de programme Python permettant de récupérer certaines informations de façon structurées sur l’ensemble des équipements du lab.

---
inventory:
    plugin: SimpleInventory
    options:
        host_file: "inventory/hosts.yaml"
        group_file: "inventory/groups.yaml"
        defaults_file: "inventory/defaults.yaml"
runner:
    plugin: threaded
    options:
        num_workers: 100
---
clab-arista-leaf1:
    hostname: 172.20.20.5
    groups:
        - ceos
clab-arista-leaf2:
    hostname: 172.20.20.6
    groups:
        - ceos
clab-arista-leaf3:
    hostname: 172.20.20.7
    groups:
        - ceos
clab-arista-spine1:
    hostname: 172.20.20.9
    groups:
        - ceos
clab-arista-spine2:
    hostname: 172.20.20.8
    groups:
        - ceos
---
ceos:
    platform: 'eos'
---
username: admin
password: admin
#!/usr/bin/env python
from nornir import InitNornir
from nornir.core.filter import F
from nornir_netmiko.tasks import netmiko_send_command
from nornir_utils.plugins.functions import print_result
from ttp import ttp


version_template = """
<doc>
Template to help with Arista show version
</doc>
<group name='version'>
Hardware MAC address: {{ hardware_mac_address | MAC }}
System MAC address: {{ system_mac_address | MAC }}
Software image version: {{ software_image_version | PHRASE }}
Architecture: {{ architecture }}
</group>
"""


def arista_get_version():
    nr = InitNornir(config_file='config.yaml')
    ceos = nr.filter(F(groups__contains='ceos'))
    results = ceos.run(
        netmiko_send_command,
        command_string="show version",
        use_ttp=True,
        ttp_template=version_template
    )
    print_result(results)


if __name__ == '__main__':
    arista_get_version()

Ce programme Python va interroger tous les équipements du lab pour récupérer le résultat du show version afin d’analyser le texte pour en extraire seulement certaines informations qui sont formatées dans une structure de données.

show version TTP Arista cEOS-lab
nornir / netmiko / TTP

L’accès à l’un des éléments de la structure résultante peut être réalisé à l’aide de la syntaxe suivante :

print(results['clab-arista-spine1'][0].result[0][0]['version']['architecture'])

En terme de performance, TTP est capable de traiter plusieurs centaines de lignes par milliseconde. Pour optimiser les performances, un certain nombre de recommandations sont disponibles dans la documentation.