Cisco France Blog
Partager

Faire un commit sur IOS-XE, c’est possible !


25 November 2020


L’automatisation des réseaux est un sujet qui continue à se développer. Et dans ce contexte vous vous demandez peut-être encore comment il est possible de valider un bloc de configuration complet sur IOS-XE. Vous cherchez comment faire un commit pour vous assurer que les configurations soient bien appliquées proprement, toutes en même temps si et seulement si elles ne génèrent pas d’erreur. Je vous confirme que tout cela est possible depuis pas mal de temps en IOS-XE…

Je vais vite clarifier : n’allez pas chercher un commit en CLI. Vous imaginez bien ce qui se passerait si on introduisait la nécessité de faire un commit dans le CLI, nous aurions des milliers et des milliers de clients et partenaires furieux de voir leurs scripts actuels (parfois développés il y a des années) cesser de fonctionner. Innover oui, mais sans rien changer, c’est là un véritable challenge !

Le CLI est un langage conçu pour les humains. Oui cela peut faire sourire, et on est d’accord que parfois humain n’est pas forcément le bon terme pour nous décrire dans le monde réseau mais c’est un fait : le CLI sur IOS a été conçu pour qu’une personne puisse taper de la configuration simplement et rapidement. Et nous sommes beaucoup à apprécier pouvoir faire en quelques secondes sur du CLI à grand coup de copier/coller ce qui parfois prend très longtemps sur des GUI sophistiquées.

Quand une machine va parler avec une autre machine, utiliser le CLI n’est donc pas ce qui a le plus de sens. Il faut des méthodes optimisées pour les machines.

Les modèles de données

La première chose à prendre en compte est l’utilisation de modèles de données. Pour expliquer ce que c’est vous pouvez regarder la manière dont j’ai rédigé ma “bio” sur le blog. Vous arrivez avec votre cerveau humain à comprendre ce que j’ai écrit mais imaginez l’effort incroyable de développement à faire pour qu’une machine puisse comprendre ce que j’ai écrit afin de me répertorier dans un annuaire. Il eut été préférable que je remplisse un formulaire :

  • Nom :
  • Prénom :
  • Url profil linkedin :
  • Liste des technologies maîtrisées (RFC IETF …) :
  • Liste des publications (url des documents produits) :

Un modèle de données c’est justement cela : se mettre d’accord sur la manière de présenter les informations. Faites un “show interfaces” par exemple, vous arriverez à lire les informations parce que votre cerveau va trouver ce qui l’intéresse rapidement. Mais pour qu’une machine puisse le faire il vous faudra parser du CLI et ce n’est pas le plus efficace. Suivre un schéma est alors plus approprié, plus simple.

La bonne nouvelle est que toute la configuration IOS-XE (et de nos autres IOS d’ailleurs) est modélisée. Les modèles sont rédigés en YANG (RFC 6020) et sont soit publiés par différents organismes de “standardisation” comme l’IETF, l’ITU ou Openconfig, ou bien créés par Cisco. Nous ne pouvons pas forcément compter sur des organismes tiers pour modéliser convenablement toutes nos fonctionnalités.

API programmatiques

Maintenant que nos machines savent quelles données échanger, elles doivent utiliser le bon langage pour communiquer. Et là aussi le CLI dans SSH n’est pas la meilleure option. Pensez-vous par exemple que le plus simple pour un automate soit d’interpréter un ” % Invalid input detected at ‘^’ marker.” qui serait retourné par l’équipement en cas d’une mauvaise CLI ? Le mieux est d’utiliser une API programmatique. Il en existe plusieurs sur IOS-XE : NETCONF, RESTCONF, GNMI, gRPC… De la même manière que les développeurs ne se mettront jamais d’accord pour utiliser tous le même langage de développement, on aura des API différentes car elles adressent des besoins différents et des populations distinctes. Un développeur web par exemple sera ravi de communiquer avec un équipement réseau en REST de la même manière qu’il parle avec une page web. Les fans des développements qui utilisent des microservices privilégieront peut-être gRPC (et gNXI par extension). Mais pour l’admin réseau pur et dur, NETCONF (RFC 6241) sera certainement plus approprié. Transporté sur SSH, ce protocole ne se contente pas de pousser des configurations, il offre aussi des fonctions très adaptées à la configuration d’équipements réseau. Je cite quelques exemples ci-dessous :

  • Récupération au moment de la connexion de toutes les “capabilities” de l’équipement : on sait donc nativement ce que l’équimement peut faire, quels modèles YANG il supporte.
  • Possibilité de lire / écrire une configuration
  • Possibilité de configurer en addition (merge) ou bien de remplacer complètement un élément de configuration sans se soucier de ce qu’il y avait avant.
  • Possibilité de faire un lock/unlock sur la configuration d’un équipement (pour éviter que plusieurs modifications parallèles soient faites)
  • Configurer en mode transactionnel : soit la configuration est entièrement acceptée, soit elle ne l’est pas. Pas de risque que le job soit à moitié fait.
  • Messages d’erreur clairs en cas d’échec d’une opération
  • Possibilité de choisir la configuration (ou “datastore”) que l’on va modifier (running, startup, mais aussi le candidate datastore) Ce dernier datastore permet de vérifier une configuration sur l’équipement sans pour autant l’appliquer
  • Commit pour passer le contenu du candidate datastore dans la running-configuration
  • … et j’en passe !

Mais vous avez bien là votre commit. En poussant d’abord votre configuration dans le candidate-datastore, et en réalisant un commit une fois l’opération validée vous avez bien le comportement désiré. Vous pouvez même avoir ce comportement sur tout un parc : d’abord vous lockez toutes les configurations. Ensuite vous modifiez tous les candidate datastore. Si et seulement si toutes les configurations se sont bien passées alors vous pourrez passer tous les commits et faire les unlocks.

Lab

Pour mettre tout cela en musique je vous propose un petit exemple dans mon lab pour changer le hostname d’un Catalyst 9300.

Tout d’abord je vais demander à mon équipement de me dire son petit nom. Je fais donc un get-config et je spécifie via un filtre ce que je veux chercher (le hostname) et le modèle de données que j’utilise (Cisco-IOS-XE-native). NETCONF utilise des payloads au format XML. Si c’est un peu pénible pour l’humain, ne vous en faites pas trop votre code saura très bien composer avec et il y a des tonnes d’outils qui font cela automatiquement.

<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
  <get-config>
    <source>
      <running/>
    </source>
    <filter>
      <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
        <hostname/>
      </native>
    </filter>
  </get-config>
</rpc>

L’équipement me répond et me retourne l’information souhaitée.

<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:768acdcf-9a85-4474-bde2-738540fba9b6">
  <data>
    <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
      <hostname>CAT9K-DEMO-1</hostname>
    </native>
  </data>
</rpc-reply>

Je peux réaliser la même opération en utilisant un modèle de données Openconfig (openconfg-system). Il existe parfois plusieurs moyens de décrire la même chose : à vous de choisir ce qui vous conviendra le mieux.

<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
  <get-config>
    <source>
      <running/>
    </source>
    <filter>
      <system xmlns="http://openconfig.net/yang/system">
        <config>
          <hostname/>
        </config>
      </system>
    </filter>
  </get-config>
</rpc>

Et fort heureusement l’équipement va me donner la même information (présentée différemment)

<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:9f5f68c6-62e0-470b-9115-87a845437aac">
  <data>
    <system xmlns="http://openconfig.net/yang/system">
      <config>
        <hostname>CAT9K-DEMO-1</hostname>
      </config>
    </system>
  </data>
</rpc-reply>

En utilisant des modèles standard vous pourrez ainsi configurer de la même manière des équipements de fournisseurs différents, si tant est que les modèles sont supportés…

Je demande maintenant à changer le hostname en “RESEAUXBLOG” dans le candidate datastore (en réutilisant le modèles Cisco-IOS-XE-Native).

<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
  <edit-config>
    <target>
      <candidate/>
    </target>
    <config>
      <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
        <hostname>RESEAUXBLOG</hostname>
      </native>
    </config>
  </edit-config>
</rpc>

Mon switch me dit que tout s’est bien passé.

<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:ed4b513c-3d04-4816-826b-0398c0375410">
  <ok/>
</rpc-reply>

A ce stade si je me connecte sur mon équipement, c’est toujours l’ancien nom qui est utilisé.

CAT9K-DEMO-1#sh run | i hostname
hostname CAT9K-DEMO-1

Il est temps de faire mon commit (au sein de la même session NETCONF)

<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="102">
  <commit/>
</rpc>

L’équipement me confirme à nouveau que tout s’est bien passé.

<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:202ebac8-0203-40fe-90fc-0602e5ef4013">
  <ok/>
</rpc-reply>

Et la modification est prise en compte sur le device et dans sa running-config CLI :

RESEAUXBLOG#sh run | i hostname
hostname RESEAUXBLOG

Pour en savoir plus…

J’espère que ces petits exemples vous donneront envie d’utiliser les bons outils pour automatiser vos réseaux. J’avais abordé ces points dans un article que j’avais publié pour la conférence JRES 2019, l’article et la vidéo sont en ligne.

Pour démarrer le mieux est d’aller sur le portail DEVNET. Vous y trouverez des tonnes d’exemples, des labs vraiment très bien faits et des outils pour vous aider. Et comme toujours si vous avez des questions n’hésitez pas à les poser dans les commentaires ci-dessous.

@JeromeDurand

 

Tags:
Laisser un commentaire