Tables and Views

Dernière modification le 11 janvier 2020

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.

Les données de configuration et d’exploitation sont basées sur un modèle de données cohérent et clairement défini. Selon le scénario, vous pouvez utiliser les langages internes DDL (Data Definition Language) et ODL (Output Definition Language), le langage YANG standard ou les modèles OpenConfig.

NETCONF est un protocole standardisé qui peut être utilisé pour transporter des données de configuration et des commandes opérationnelles vers un équipement réseau. NETCONF est le protocole d’automatisation de choix de Juniper depuis de nombreuses années et il est pris en charge sur tous les équipements Junos.
Avant NETCONF, il y avait JUNOScript, disponible depuis la version 4.2 de Junos OS en 2001. JUNOScript a été renommé «Junos XML Management Protocol», ou «Junos XML Protocol». Comme NETCONF, Junos XML Protocol est une API de gestion de réseau basée sur XML pour la gestion des équipements exécutant Junos.
En 2006, le protocole Junos XML (JUNOScript) a été modifié, amélioré, puis soumis à l’IETF pour ratification. Le protocole XML Junos est devenu NETCONF, un standard IETF ratifié avec le RFC 4741. Depuis lors, l’IETF a apporté des modifications et des ajouts à NETCONF, qui sont tous pris en charge par Juniper. Actuellement, NETCONF est défini dans le document RFC 6241 mis à jour par les RFC 7803 et 8526, et qui rend obsolète l’ancien document.
NETCONF est la base sur laquelle reposent de nombreuses technologies d’automatisation Juniper, notamment: Junos PyEZ, YANG, OpenConfig et l’intégration avec les systèmes de gestion de l’automatisation comme Ansible ou Salt.
Dans la plupart des cas, NETCONF utilise SSH comme couche de transport, bien que le RFC 6241 autorise également d’autres options sécurisées (par exemple, TLS).

La fonctionnalité « Tables and Vues », disponible dans les modules de PyEZ, facilite l’utilisation de RPC et des données de configuration. Elle permet de placer les données RPC et les données de configuration Junos OS dans une structure de données structurée de type tableau. Une table contient toutes les données extraites d’un RPC ou d’une configuration. Une vue contient une vue limitée ou un sous-ensemble des données de la table. Les tables et les vues sont définies à l’aide de fichiers YAML. Junos PyEZ est livré avec un grand ensemble de tables et de vues prédéfinies, qui se trouvent dans les packages op (pour les données opérationnelles) et ressources (pour la configuration) au sein de la structure de répertoires Junos PyEZ. Les tables Junos PyEZ étant définies à l’aide de YAML, vous pouvez définir simplement vos propres tables et vues si vous ne trouvez pas ce que vous recherchez dans celles existantes, en s’aidant du package factory.

Prenons un exemple simple de « Tables and Views » défini dans le module op de PyEZ et voyons son utilisation en Python sur une simulation Vagrant/VirtualBox.

#!/usr/bin/env python3

import sys
import yaml
from jnpr.junos import Device
from jnpr.junos.op.routes import RouteTable
from jnpr.junos.exception import ConnectError

# Display style
INFO = '\033[1;34;40m'
SUCCESS = '\033[1;32;40m'
ERROR = '\033[1;31;40m'
NORMAL = '\033[0;37;40m'

# Devices list
vqfx01 = {
  'host' : 'localhost',
  'user' : 'gilbert',
  'port' : '2222'
}
vqfx02 = {
  'host' : 'localhost',
  'user' : 'gilbert',
  'port' : '2200'
}
all_vqfx = [
  vqfx01,
  vqfx02
]

# List routes using predifined operational Table & View
for a_vqfx in all_vqfx:
  dev = Device(
    host=a_vqfx['host'],
    user=a_vqfx['user'],
    port=a_vqfx['port']
  )
  try:
    dev.open()
    print (
      '\nDisplaying {0}{1} - {2}{3} routes\n'
      .format(
        INFO,
        a_vqfx['host'],
        a_vqfx['port'],
        NORMAL
       )
    )
    tbl = RouteTable(dev)
    tbl.get()
    print ('summary: {0}\n'.format(tbl))
    for item in tbl:
      print ('protocol: {0}'.format(item.protocol))
      print ('via: {0}'.format(item.via))
      print ('age: {0}'.format(item.age))
      print ('nexthop: {0}\n'.format(item.nexthop))
  except ConnectError as err:
    print (
      'Cannot connect to device: {0}'
      .format(err)
    )
    sys.exit(1)
  except Exception as err:
    print (err)
    sys.exit(1)
  dev.close()
---

### ------------------------------------------------------
### show route <destination>
### ------------------------------------------------------

RouteTable:
  rpc: get-route-information
  args_key: destination
  item: route-table/rt 
  key: rt-destination
  view: RouteTableView

RouteTableView:
  groups:
    entry: rt-entry
  fields_entry:
    # fields taken from the group 'entry'
    protocol: protocol-name
    via: nh/via | nh/nh-local-interface
    age: { age/@seconds : int }
    nexthop: nh/to

### ------------------------------------------------------
### show route summary
### ------------------------------------------------------

RouteSummaryTable:
  rpc: get-route-summary-information
  item: route-table
  key: table-name
  view: RouteSummaryView

RouteSummaryView:
  fields:
    dests: { destination-count : int }
    total: { total-route-count : int }
    active: { active-route-count : int }
    holddown: { holddown-route-count : int }
    hidden: { hidden-route-count : int }
    proto: _rspTable 

_rspTable:
  item: protocols
  key: protocol-name
  view: _rspView

_rspView:
  fields:
    count: { protocol-route-count: int }
    active: { active-route-count : int }