[PYTHON] Suite ・ J'ai essayé de toucher la bibliothèque d'API de contrôle de routeur multifournisseur NAPALM

Ceci est l'article sur le 24e jour du Calendrier de l'Avent NetOpsCoding 2016.

NAPALM est une bibliothèque Python open source pour la configuration des périphériques réseau et l'acquisition d'informations, et contrôle plusieurs produits de fournisseurs avec une interface unifiée. Il est développé dans ce but. Pour ceux qui envisagent d'automatiser dans un environnement d'exploitation réseau multi-fournisseurs, une bibliothèque compatible multi-fournisseurs comme NAPALM est une existence tant attendue.

NAPALM a été introduit dans l'article "J'ai essayé de toucher la bibliothèque d'API de contrôle de routeur NAPALM" en juin 2015, mais c'est toujours NANOG. Le développement se poursuit activement à l'initiative de la communauté centrée sur, et le nombre de fonctions et de modèles compatibles augmente les uns après les autres. J'ai senti qu'il était peut-être temps de le mettre sur le site d'exploitation réel dans un environnement multi-fournisseurs, j'ai donc résumé les informations à nouveau cette fois.

Modèles compatibles

NAPALM prend en charge le système d'exploitation réseau suivant.

--Arista EOS: 4.15.0F ou version ultérieure --Juniper JunOS: 12.1 ou version ultérieure --Cisco IOS-XR: 5.1.0 ou version ultérieure --Fortinet FortiOS: 5.2.0 ou version ultérieure --IBM: version prise en charge inconnue --Cisco NXOS: 6.1 ou version ultérieure (Nexus 5k, 6k, 7k version 7.2 ou ultérieure) --Cisco IOS: 12,4 (20) T ou version ultérieure

En arrière-plan de NAPALM, l'API officielle du fabricant (Juniper PyEZ et Arista eAPI pyeapi) etc.), et des API de fabricant non officielles développées par des individus ou des communautés (pyIOSXR et netmiko Etc.) sont combinés pour constituer.

Puisqu'il s'agit d'un développement mené par la communauté, il semble que les fonctions soient régulièrement étendues avec l'idée que «vous pouvez créer vous-même les fonctions manquantes». En juin 2015, il n'y avait que quatre modèles compatibles, IOS XR, JUNOS, EOS et FortiOS, on peut donc voir que le développement a considérablement progressé au cours de la dernière année et demie.

Fonction correspondante

Au moment de cet article, NAPALM a implémenté les fonctionnalités suivantes. Cependant, les fonctions implémentées par le système d'exploitation varient, veuillez donc vous référer à la page officielle Appareils pris en charge pour plus de détails.

--Charger la configuration (remplacer / fusionner) / Comparer / Valider / Dicard / Rollback --Acquisition d'informations sur l'appareil

Il est très utile dans le développement d'un logiciel automatisé que les fonctions du système de confirmation d'état soient substantielles. Comme je l'ai écrit dans mon blog précédent "J'ai essayé d'utiliser PyEZ et JSNAPy", il est très important de rendre le processus de vérification de la normalité des périphériques réseau dans le logiciel. C'est une œuvre qui rompt. Implémenter "Implémentation de la commande d'acquisition d'informations-> Acquérir la chaîne de caractères cible avec une expression régulière-> Acquérir la chaîne de caractères extraite comme information ou juger normal / anormal", ce qui est normalement inévitable pour les développeurs de logiciels En utilisant le processus comme une bibliothèque sans connaître le fournisseur / modèle, il est possible de réduire considérablement l'effort de développement.

Coopération avec le cadre d'automatisation

NAPALM n'est pas seulement intégré dans le logiciel, mais devrait également être appelé à partir d'un cadre automatisé introduit dans les opérations d'infrastructure de serveur. Actuellement, des modules NAPALM sont en cours de développement pour fonctionner avec Ansible et Salt.

Je n'entrerai pas dans les détails dans cet article, mais si vous êtes intéressé, veuillez vous référer aux documents suivants.

J'ai essayé d'utiliser NAPALM

Essayons d'utiliser un routeur pour voir ce que vous pouvez réellement faire avec NAPALM.

Après avoir touché au hasard la fonction que je souhaite utiliser, le montant est devenu assez important, veuillez donc vérifier à partir de l'élément qui vous intéresse.

environnement

Dans cet article, j'ai expérimenté dans l'environnement suivant. Tous sauf Macbook peuvent être préparés gratuitement.

--PC (machine hôte) - MacBookAir OSX El Capitan 10.11.6 --Routeur virtuel

Si vous voulez en savoir plus sur l'intégration de Vagrant de Firefly et IOS XRv, veuillez vous référer au blog suivant.

référence

Cette fois, j'ai procédé à l'implémentation en regardant les articles suivants.

Installation

Installez la dernière version de NAPALM (version 1.1.0 au moment de ce blog). Ici, pip, qui est un système de gestion de paquets Python, est utilisé.

% pip install napalm
(snip)


% pip list
(snip)
napalm (1.1.0)
napalm-base (0.21.0)
napalm-eos (0.5.0)
napalm-fortios (0.3.0)
napalm-ibm (0.1.6)
napalm-ios (0.5.0)
napalm-iosxr (0.4.2)
napalm-junos (0.5.1)
napalm-nxos (0.5.0)
napalm-panos (0.2.2)
napalm-pluribus (0.4.2)
(snip)


% pip show napalm                                                                                           (git)-[master]
Name: napalm
Version: 1.1.0
Summary: Network Automation and Programmability Abstraction Layer with Multivendor support
Home-page: https://github.com/napalm-automation/napalm
Author: David Barroso
Author-email: [email protected]
License: UNKNOWN
Location: /usr/local/lib/python2.7/site-packages
Requires: napalm-pluribus, napalm-base, napalm-ios, napalm-iosxr, napalm-ibm, napalm-junos, napalm-eos, napalm-nxos, napalm-fortios, napalm-panos

Préparation du routeur

paramètres de luciole

Pour utiliser Firefly, il est défini comme suit. --Nom d'hôte: firefly1

Pour la procédure de construction de Firefly Vagrant, veuillez vous référer à L'histoire de la progression du développement automatisé lorsque Firefly a été exécuté sur Vagrant.

Vagrantfile


# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure(2) do |config|
    config.vm.box = "juniper/ffp-12.1X47-D20.7"
    config.vm.define :firefly1 do | firefly1 |
        firefly1.vm.hostname = 'firefly1'
        firefly1.vm.network "private_network",ip: "192.168.34.16",netmask: "255.255.255.0"
    end
end

paramètres supplémentaires de firefly


set system root-authentication plain-text-password
set system login user user1 class super-user
set system login user user1 authentication plain-text-password

#Le paramètre par défaut est ge-0/0/La communication avec la machine hôte n'est pas possible car 1 est défini dans la zone de non-confiance.
#Ici la machine hôte(MacbookAir)Je souhaite utiliser l'outil d'automatisation et communiquer avec ge-0/0/Je change 1 en zone de confiance.
set security zones security-zone trust interfaces ge-0/0/1
set security zones security-zone trust interfaces ge-0/0/1.0 host-inbound-traffic system-services all
set system time-zone Asia/Tokyo


#Le paramètre par défaut est flow-mode de transfert basé(Mode pour faire fonctionner la fonction de pare-feu)Est activé et
#En l'état, les protocoles de routage tels que BGP et OSPF ne fonctionneront pas.
#Ici, pour faire fonctionner le protocole de routage, paquet-Le paramètre pour passer au mode de transfert basé est implémenté.
#Pour changer de mode, vous devez redémarrer après le réglage.
delete security policies
set security forwarding-options family mpls mode packet-based
set security forwarding-options family inet6 mode packet-based

#Paramètres liés au BGP pour le mannequin
set routing-options autonomous-system 65001
set protocols bgp family inet unicast
set protocols bgp group ge-0/0/2 type external
set protocols bgp group ge-0/0/2 neighbor 192.168.35.2 peer-as 65002
set protocols bgp group ge-0/0/2 export advertised_for_firefly2
set routing-options rib inet.0 static route 10.10.10.0/24 discard
set routing-options rib inet.0 static route 10.10.20.0/24 discard
set policy-options policy-statement advertised_for_firefly2 term 10 from route-filter 10.10.10.0/24 exact
set policy-options policy-statement advertised_for_firefly2 term 10 then accept
set policy-options policy-statement advertised_for_firefly2 term 999 then reject


#De plus, j'ai pu utiliser NAPALM sans paramétrer le NETCONF suivant.
# (Pas encore défini) set system services netconf ssh

Vérifier les paramètres avec Firefly



root@firefly1> show configuration
## Last commit: 2016-12-24 18:32:08 JST by root
version 12.1X47-D20.7;
system {
    host-name firefly1;
    time-zone Asia/Tokyo;
    root-authentication {
        encrypted-password "$1$EUe8ffbf$HT20ATkJCGIyslemV9hTf1"; ## SECRET-DATA
        ssh-rsa "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqs9vHYiqhpS5/5QWI2EskcTz1nMdv+1NlxrCaDyO8+03rzyHiOjXILcYx5MHExvw4JRlMMxiO0D3dHW+i4EtIVTSstyzEyd2coxLtgBp4VfaINBLInQKQNxOPioPUtu7rJynR9cHPk7DQw7QjCCUawYgQHWzCiiYSnmKWZrJAgVQZzfP2LEj1+Cqrg1ro8VQ4CpLeplOT4qXmlTE/dvQFPHabhAmGdP7JZv4IDPwZtkJ7gRv/PfYdTpn96IiG4Y09yIMPXaq40A82bczptazcOdScVyjUrFe8NbzQfnkVpe2C6ieDc7lU7PQhqqBGPpb1eEbQo1vq2Lo9b88dT7EH vagrant"; ## SECRET-DATA
    }
    login {
        user user1 {
            uid 2001;
            class super-user;
            authentication {
                encrypted-password "$1$P9L/Y/Ca$dzv5waDzJeYa5VdKGDm340"; ## SECRET-DATA
            }
        }
        user vagrant {
            uid 2000;
            class super-user;
            authentication {
                ssh-rsa "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key"; ## SECRET-DATA
            }
        }
    }
    services {
        ssh {
            root-login allow;
        }
        web-management {
            http {
                interface ge-0/0/0.0;
            }
        }
    }
    syslog {
        user * {
            any emergency;
        }
        file messages {
            any any;
            authorization info;
        }
        file interactive-commands {
            interactive-commands any;
        }
    }
    license {
        autoupdate {
            url https://ae1.juniper.net/junos/key_retrieval;
        }
    }
}
interfaces {
    ge-0/0/0 {
        unit 0 {
            family inet {
                dhcp;
            }
        }
    }
    ge-0/0/1 {
        unit 0 {
            family inet {
                address 192.168.34.16/24;
            }
        }
    }
    ge-0/0/2 {
        unit 0 {
            family inet {
                address 192.168.35.1/30;
            }
        }
    }
}
routing-options {
    rib inet.0 {
        static {
            route 10.10.10.0/24 discard;
            route 10.10.20.0/24 discard;
        }
    }
    autonomous-system 65001;
}
protocols {
    bgp {
        family inet {
            unicast;
        }
        group ge-0/0/2 {
            type external;
            export advertised_for_firefly2;
            neighbor 192.168.35.2 {
                peer-as 65002;
            }
        }
    }
}
policy-options {
    policy-statement advertised_for_firefly2 {
        term 10 {
            from {
                route-filter 10.10.10.0/24 exact;
            }
            then accept;
        }
        term 999 {
            then reject;
        }
    }
}
security {
    forwarding-options {
        family {
            inet6 {
                mode packet-based;
            }
            mpls {
                mode packet-based;
            }
        }
    }
    screen {
        ids-option untrust-screen {
            icmp {
                ping-death;
            }
            ip {
                source-route-option;
                tear-drop;
            }
            tcp {
                syn-flood {
                    alarm-threshold 1024;
                    attack-threshold 200;
                    source-threshold 1024;
                    destination-threshold 2048;
                    queue-size 2000; ## Warning: 'queue-size' is deprecated
                    timeout 20;
                }
                land;
            }
        }
    }
    zones {
        functional-zone management {
            interfaces {
                ge-0/0/0.0 {
                    host-inbound-traffic {
                        system-services {
                            all;
                        }
                        protocols {
                            all;
                        }
                    }
                }
            }
        }
        security-zone trust {
            tcp-rst;
            interfaces {
                ge-0/0/1.0 {
                    host-inbound-traffic {
                        system-services {
                            all;
                        }
                    }
                }
                ge-0/0/2.0 {
                    host-inbound-traffic {
                        system-services {
                            all;
                        }
                    }
                }
            }
        }
        security-zone untrust {
            screen untrust-screen;
        }
    }
}

Confirmez que vous pouvez vous connecter ssh à Firefly depuis la machine hôte


% ssh [email protected]
Password:
--- JUNOS 12.1X47-D20.7 built 2015-03-03 21:53:50 UTC
user1@firefly1>
user1@firefly1> show version
Hostname: firefly1
Model: firefly-perimeter
JUNOS Software Release [12.1X47-D20.7]

Configuration IOSXRv

Pour utiliser IOSXRv, il est défini comme suit.

Veuillez vous référer à J'ai essayé IOS-XRv Vagrant pour la procédure de construction d'IOSXRv.

Vagrantfile


# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "IOS-XRv"
end

Paramètres supplémentaires IOSXRv


#Requis lors de l'utilisation de NAPALM
xml agent tty iteration off

#Paramètre BGP pour factice
router bgp 65001
 timers bgp 30 90
 address-family ipv4 unicast
  network 0.0.0.0/0
 !
 neighbor 192.168.0.1
  remote-as 65002
  description test_AS65002
  address-family ipv4 unicast
   send-community-ebgp
   next-hop-self
   soft-reconfiguration inbound always
  !
 !
!
end

Vérifiez les paramètres avec IOS XRv


RP/0/RP0/CPU0:ios#show running-config
Fri Dec 23 13:16:25.273 UTC
Building configuration...
!! IOS XR Configuration version = 6.2.1.23I
!! Last configuration change at Fri Dec 23 13:08:29 2016 by vagrant
!
telnet vrf default ipv4 server max-servers 10
username vagrant
 group root-lr
 group cisco-support
 secret 5 $1$RQve$C1P.pH/koIKYsybRgxtSZ0
!
tpa
 address-family ipv4
  update-source MgmtEth0/RP0/CPU0/0
 !
!
interface MgmtEth0/RP0/CPU0/0
 ipv4 address dhcp
!
router static
 address-family ipv4 unicast
  0.0.0.0/0 MgmtEth0/RP0/CPU0/0 10.0.2.2
 !
!
router bgp 65001
 timers bgp 30 90
 address-family ipv4 unicast
  network 0.0.0.0/0
 !
 neighbor 192.168.0.1
  remote-as 65002
  description test_AS65002
  address-family ipv4 unicast
   send-community-ebgp
   next-hop-self
   soft-reconfiguration inbound always
  !
 !
!
grpc
 port 57777
!
xml agent tty
 iteration off
!
ssh server v2
ssh server vrf default
end

Exemple d'utilisation de NAPALM: acquisition d'informations sur l'appareil

Tout d'abord, obtenons les informations sur l'appareil. Les informations peuvent être obtenues sous forme de variable de type dictionnaire en utilisant get_facts (). ..

Pour JUNOS

get_info.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm
from pprint import pprint

driver = napalm.get_network_driver('junos')
device = driver(
    hostname='192.168.34.16',
    username='user1',
    password='password1' )

print 'Open session: ',
device.open()
print 'OK'

pprint(device.get_facts())

print 'Close session: ',
device.close()
print 'OK'

Résultat d'exécution


% python get_info.py 

Open session:  OK
get facts:
{u'fqdn': u'firefly1',
 u'hostname': u'firefly1',
 u'interface_list': ['ge-0/0/0',
                     'gr-0/0/0',
                     'ip-0/0/0',
                     'lsq-0/0/0',
                     'lt-0/0/0',
                     'mt-0/0/0',
                     'sp-0/0/0',
                     'ge-0/0/1',
                     'ge-0/0/2',
                     '.local.',
                     'dsc',
                     'gre',
                     'ipip',
                     'irb',
                     'lo0',
                     'lsi',
                     'mtun',
                     'pimd',
                     'pime',
                     'pp0',
                     'ppd0',
                     'ppe0',
                     'st0',
                     'tap',
                     'vlan'],
 u'model': u'FIREFLY-PERIMETER',
 u'os_version': u'12.1X47-D20.7',
 u'serial_number': u'f0016079634f',
 u'uptime': 1740,
 u'vendor': u'Juniper'}
Close session:  OK

Vérification de l'état sur le routeur réel


root@firefly1> show version
Hostname: firefly1
Model: firefly-perimeter
JUNOS Software Release [12.1X47-D20.7]

root@firefly1> show chassis hardware
Hardware inventory:
Item             Version  Part number  Serial number     Description
Chassis                                f0016079634f      FIREFLY-PERIMETER
Midplane
System IO
Routing Engine                                           FIREFLY-PERIMETER RE
FPC 0                                                    Virtual FPC
  PIC 0                                                  Virtual VTNET GE
Power Supply 0

Pour IOS XR

get_info.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm
from pprint import pprint

driver = napalm.get_network_driver('iosxr')
device = driver(
    hostname='127.0.0.1',
    username='vagrant',
    password='vagrant',
    # IOSXRv default ssh port
    optional_args={'port': 2223}) 

print 'Open session: ',
device.open()
print 'OK'

print 'get facts: '
pprint(device.get_facts())

print 'Close session: ',
device.close()
print 'OK'

Résultat d'exécution


% python get_info.py                                                                                                                                                                         (git)-[master]
Open session:  OK
get facts:
{u'fqdn': u'ios',
 u'hostname': u'ios',
 u'interface_list': [u'Null0', u'MgmtEth0/RP0/CPU0/0'],
 u'model': u'XRV-P-L--CH',
 u'os_version': u'6.2.1.23I',
 u'serial_number': u'XRV-SN---CH',
 u'uptime': 1585,
 u'vendor': u'Cisco'}

Vérification de l'état sur le routeur réel


RP/0/RP0/CPU0:ios#show version
Fri Dec 23 12:38:05.156 UTC

Cisco IOS XR Software, Version 6.2.1.23I
Copyright (c) 2013-2016 by Cisco Systems, Inc.

Build Information:
 Built By     : jwu
 Built On     : Mon Nov 21 00:33:58 PST 2016
 Build Host   : iox-ucs-005
 Workspace    : /auto/iox-ucs-005-san1/nightly/xr-dev_16.11.20C/iosxrv-x64
 Version      : 6.2.1.23I
 Location     : /opt/cisco/XR/packages/

cisco IOS XRv x64 () processor
System uptime is 34 minutes


RP/0/RP0/CPU0:ios#show inventory
Fri Dec 23 12:39:25.870 UTC
NAME: "0/RP0", DESCR: "FLEX_PH"
PID: XRV-P-L--RP       , VID: FLEX_PH, SN: XRV-SN---RP

NAME: "Rack 0", DESCR: "FLEX_PH"
PID: XRV-P-L--CH       , VID: FLEX_PH, SN: XRV-SN---CH

Exemple d'utilisation de NAPALM: acquisition des informations d'adresse d'interface

Pour obtenir les informations d'adresse de l'interface, utilisez la fonction get_interfaces_ip ().

Non implémenté cette fois, mais si vous voulez obtenir des informations d'interface haut / bas et MAC, [fonction get_interfaces ()](https://napalm.readthedocs.io/en/latest/base.html#napalm_base.base.NetworkDriver .get_interfaces), fonction get_interfaces_counters () si vous souhaitez obtenir des compteurs d'erreurs d'interface, des informations sur l'intensité lumineuse Si vous voulez l'obtenir, vous pouvez obtenir les informations en utilisant la fonction get_optics (). ..

Pour JUNOS

get_info.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm
from pprint import pprint

driver = napalm.get_network_driver('junos')
device = driver(
    hostname='192.168.34.16',
    username='user1',
    password='password1')

print 'Open session: ',
device.open()
print 'OK'

print 'get interface IP: '
pprint(device.get_interfaces_ip())

print 'Close session: ',
device.close()
print 'OK'

Résultat d'exécution


% python get_info.py 

Open session:  OK
get interface IP:
{u'ge-0/0/0.0': {u'ipv4': {u'10.0.2.15': {u'prefix_length': 24}}},
 u'ge-0/0/1.0': {u'ipv4': {u'192.168.34.16': {u'prefix_length': 24}}},
 u'ge-0/0/2.0': {u'ipv4': {u'192.168.35.1': {u'prefix_length': 30}}},
 u'lo0.16384': {u'ipv4': {u'127.0.0.1': {u'prefix_length': 0}}},
 u'lo0.16385': {u'ipv4': {u'10.0.0.1': {u'prefix_length': 0},
                          u'10.0.0.16': {u'prefix_length': 0},
                          u'128.0.0.1': {u'prefix_length': 0},
                          u'128.0.0.4': {u'prefix_length': 0},
                          u'128.0.1.16': {u'prefix_length': 0}}},
 u'sp-0/0/0.16383': {u'ipv4': {u'10.0.0.1': {u'prefix_length': 0},
                               u'10.0.0.6': {u'prefix_length': 0},
                               u'128.0.0.1': {u'prefix_length': 0},
                               u'128.0.0.6': {u'prefix_length': 0}}}}
Close session:  OK

Vérification de l'état sur le routeur réel


root@firefly1> show interfaces terse
Interface               Admin Link Proto    Local                 Remote
ge-0/0/0                up    up
ge-0/0/0.0              up    up   inet     10.0.2.15/24
gr-0/0/0                up    up
ip-0/0/0                up    up
lsq-0/0/0               up    up
lt-0/0/0                up    up
mt-0/0/0                up    up
sp-0/0/0                up    up
sp-0/0/0.0              up    up   inet
                                   inet6
sp-0/0/0.16383          up    up   inet     10.0.0.1            --> 10.0.0.16
                                            10.0.0.6            --> 0/0
                                            128.0.0.1           --> 128.0.1.16
                                            128.0.0.6           --> 0/0
ge-0/0/1                up    up
ge-0/0/1.0              up    up   inet     192.168.34.16/24
ge-0/0/2                up    up
ge-0/0/2.0              up    up   inet     192.168.35.1/30
dsc                     up    up
gre                     up    up
ipip                    up    up
irb                     up    up
lo0                     up    up
lo0.16384               up    up   inet     127.0.0.1           --> 0/0
lo0.16385               up    up   inet     10.0.0.1            --> 0/0
                                            10.0.0.16           --> 0/0
                                            128.0.0.1           --> 0/0
                                            128.0.0.4           --> 0/0
                                            128.0.1.16          --> 0/0
lo0.32768               up    up
lsi                     up    up
mtun                    up    up
pimd                    up    up
pime                    up    up
pp0                     up    up
ppd0                    up    up
ppe0                    up    up
st0                     up    up
tap                     up    up
vlan                    up    down

Pour IOS XR

get_info.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm
from pprint import pprint

driver = napalm.get_network_driver('iosxr')
device = driver(
    hostname='127.0.0.1',
    username='vagrant',
    password='vagrant',
    # IOSXRv default ssh port
    optional_args={'port': 2223}) 

print 'Open session: ',
device.open()
print 'OK'

print 'get interface IP: '
pprint(device.get_interfaces_ip())

print 'Close session: ',
device.close()
print 'OK'

Résultat d'exécution


% python get_info.py                                                                                                                                                                         (git)-[master]
Open session:  OK

get interface IP:
{u'MgmtEth0/RP0/CPU0/0': {u'ipv4': {u'10.0.2.15': {u'prefix_length': 24}}}}

Close session:  OK

Vérification de l'état sur le routeur réel


RP/0/RP0/CPU0:ios#show ipv4 interface brief
Fri Dec 23 12:44:59.827 UTC

Interface                      IP-Address      Status          Protocol Vrf-Name
MgmtEth0/RP0/CPU0/0            10.0.2.15       Up              Up       default

Exemple d'utilisation de NAPALM: Acquisition des informations de table ARP

Utilisez la fonction get_arp_table () pour obtenir les informations de la table ARP.

Pour JUNOS

get_info.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm
from pprint import pprint

driver = napalm.get_network_driver('junos')
device = driver(
    hostname='192.168.34.16',
    username='user1',
    password='password1')

print 'Open session: ',
device.open()
print 'OK'

print 'get ARP table'
pprint(device.get_arp_table())

print 'Close session: ',
device.close()
print 'OK'

Résultat d'exécution


% python get_info.py

Open session:  OK
get ARP table
[{'age': 530.0,
  'interface': u'ge-0/0/0.0',
  'ip': u'10.0.2.2',
  'mac': u'52:54:00:12:35:02'},
 {'age': 505.0,
  'interface': u'ge-0/0/0.0',
  'ip': u'10.0.2.3',
  'mac': u'52:54:00:12:35:03'},
 {'age': 1415.0,
  'interface': u'ge-0/0/1.0',
  'ip': u'192.168.34.1',
  'mac': u'0A:00:27:00:00:04'}]
Close session:  OK

Vérification de l'état sur le routeur réel


root@firefly1> show arp
MAC Address       Address         Name                      Interface           Flags
52:54:00:12:35:02 10.0.2.2        10.0.2.2                  ge-0/0/0.0          none
52:54:00:12:35:03 10.0.2.3        10.0.2.3                  ge-0/0/0.0          none
0a:00:27:00:00:04 192.168.34.1    192.168.34.1              ge-0/0/1.0          none
Total entries: 3

Pour IOS XR

get_info.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm
from pprint import pprint

driver = napalm.get_network_driver('iosxr')
device = driver(
    hostname='127.0.0.1',
    username='vagrant',
    password='vagrant',
    # IOSXRv default ssh port
    optional_args={'port': 2223}) 

print 'Open session: ',
device.open()
print 'OK'

print 'get ARP table'
pprint(device.get_arp_table())

print 'Close session: ',
device.close()
print 'OK'

Résultat d'exécution


% python get_info.py

Open session:  OK
get ARP table
[{u'age': 1228.0,
  u'interface': u'MgmtEth0/RP0/CPU0/0',
  u'ip': u'10.0.2.2',
  u'mac': u'52:54:00:12:35:02'},
 {u'age': 0.0,
  u'interface': u'MgmtEth0/RP0/CPU0/0',
  u'ip': u'10.0.2.15',
  u'mac': u'08:00:27:0D:1E:94'}]

Close session:  OK

Vérification de l'état sur le routeur réel


RP/0/RP0/CPU0:ios#show arp
Fri Dec 23 12:46:58.918 UTC

-------------------------------------------------------------------------------
0/RP0/CPU0
-------------------------------------------------------------------------------
Address         Age        Hardware Addr   State      Type  Interface
10.0.2.2        00:37:45   5254.0012.3502  Dynamic    ARPA  MgmtEth0/RP0/CPU0/0
10.0.2.15       -          0800.270d.1e94  Interface  ARPA  MgmtEth0/RP0/CPU0/0

Exemple d'utilisation de NAPALM: Acquisition des informations de routage pour un itinéraire spécifique

Vous pouvez obtenir les informations de routage de la route spécifiée en utilisant la fonction get_route_to ().

Pour JUNOS

get_info.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm
from pprint import pprint

driver = napalm.get_network_driver('junos')
device = driver(
    hostname='192.168.34.16',
    username='user1',
    password='password1')

print 'Open session: ',
device.open()
print 'OK'

print 'get route to 192.168.35.0'
pprint(device.get_route_to(destination=u'192.168.35.0'))

print 'Close session: ',
device.close()
print 'OK'

Résultat d'exécution


% python get_info.py 

Open session:  OK
get route to 192.168.35.0
{u'192.168.35.0/30': [{'age': 3444,
                       'current_active': True,
                       'inactive_reason': u'',
                       'last_active': True,
                       'next_hop': None,
                       'outgoing_interface': u'ge-0/0/2.0',
                       'preference': 0,
                       'protocol': u'Direct',
                       u'protocol_attributes': {},
                       'routing_table': u'inet.0',
                       'selected_next_hop': True}]}
Close session:  OK

Vérification de l'état sur le routeur réel


root@firefly1> show route 192.168.35.2 detail

inet.0: 7 destinations, 7 routes (7 active, 0 holddown, 0 hidden)
192.168.35.0/30 (1 entry, 1 announced)
        *Direct Preference: 0
                Next hop type: Interface
                Address: 0x9350448
                Next-hop reference count: 2
                Next hop: via ge-0/0/2.0, selected
                State: <Active Int>
                Age: 58:00
                Task: IF
                Announcement bits (1): 1-Resolve tree 1
                AS path: I

Pour IOSXR (échec)

get_info.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm
from pprint import pprint

driver = napalm.get_network_driver('iosxr')
device = driver(
    hostname='127.0.0.1',
    username='vagrant',
    password='vagrant',
    # IOSXRv default ssh port
    optional_args={'port': 2223}) 

print 'Open session: ',
device.open()
print 'OK'

pprint 'get route to 10.0.2.2'
pprint(device.get_route_to(destination=u'10.0.2.2'))

print 'Close session: ',
device.close()
print 'OK'

Résultat d'exécution


% python get_info.py                                                                                                                                                                         

Open session:  OK
get route to 10.0.2.2
Traceback (most recent call last):
  File "get_info.py", line 38, in <module>
    pprint(device.get_route_to(destination=u'10.0.2.2'))
  File "/usr/local/lib/python2.7/site-packages/napalm_iosxr/iosxr.py", line 1218, in get_route_to
    protocol=protocol
TypeError: Protocol not supported: .

Je peux voir ce qui suit sur le routeur, mais il a échoué sur NAPALM.

Vérification de l'état sur le routeur réel


RP/0/RP0/CPU0:ios#show route 10.0.2.15
Fri Dec 23 12:49:19.184 UTC

Routing entry for 10.0.2.15/32
  Known via "local", distance 0, metric 0 (connected)
  Installed Dec 23 12:09:11.148 for 00:40:08
  Routing Descriptor Blocks
    directly connected, via MgmtEth0/RP0/CPU0/0
      Route metric is 0
  No advertising protos.

Je me demande s'il était faux de ne pas spécifier le protocole d'argument optionnel dans la fonction get_route_to (). J'ai pensé, j'ai essayé les modèles suivants, mais cela n'a pas fonctionné.

pprint(device.get_route_to(destination=u'10.0.2.2', protocol=u'bgp'))

Résultat d'exécution


% python get_info.py                                                                                                                                                                         

Open session:  OK
get route to 10.0.2.2
Traceback (most recent call last):
  File "get_info.py", line 38, in <module>
    pprint(device.get_route_to(destination=u'10.0.2.2', protocol=u'bgp'))
  File "/usr/local/lib/python2.7/site-packages/napalm_iosxr/iosxr.py", line 1239, in get_route_to
    routes_tree = ETREE.fromstring(self.device.make_rpc_call(route_info_rpc_command))
  File "/usr/local/lib/python2.7/site-packages/pyIOSXR/iosxr.py", line 148, in make_rpc_call
    result = self._execute_rpc(rpc_command)
  File "/usr/local/lib/python2.7/site-packages/pyIOSXR/iosxr.py", line 412, in _execute_rpc
    raise XMLCLIError(error_msg, self)
pyIOSXR.exceptions.XMLCLIError:
Original call was: <?xml version="1.0" encoding="UTF-8"?><Request MajorVersion="1" MinorVersion="0"><Get><Operational><RIB><VRFTable><VRF><Naming><VRFName>default        </VRFName></Naming><AFTable><AF><Naming><AFName>IPv4</AFName></Naming><SAFTable><SAF>        <Naming><SAFName>Unicast</SAFName></Naming><IP_RIBRouteTable><IP_RIBRoute><Naming>        <RouteTableName>default</RouteTableName></Naming><RouteTable><Route><Naming><Address>        10.0.2.2</Address></Naming></Route></RouteTable></IP_RIBRoute></IP_RIBRouteTable>        </SAF></SAFTable></AF></AFTable></VRF></VRFTable></RIB></Operational></Get></Request>

Cela peut être un bogue dans pyIOSXR, donc j'essaierai d'en savoir plus quand j'aurai le temps.

Exemple d'utilisation de NAPALM: acquisition des informations de voisinage BGP

Vous pouvez obtenir des informations sur les voisins BGP en utilisant la fonction get_bgp_neighbors ().

Pour JUNOS

get_info.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm
from pprint import pprint

driver = napalm.get_network_driver('junos')
device = driver(
    hostname='192.168.34.16',
    username='user1',
    password='password1')

print 'Open session: ',
device.open()
print 'OK'

print 'get BGP neighbors'
pprint(device.get_bgp_neighbors())

print 'Close session: ',
device.close()
print 'OK'

Résultat d'exécution


% python get_info.py

Open session:  OK
get BGP neighbors
{u'global': {u'peers': {u'192.168.35.2': {u'address_family': {},
                                          'description': u'',
                                          'is_enabled': True,
                                          'is_up': False,
                                          'local_as': 65001,
                                          'remote_as': 65002,
                                          'remote_id': u'',
                                          u'uptime': 291}},
             u'router_id': u'None'}}
Close session:  OK

Vérification de l'état sur le routeur réel


root@firefly1> show bgp neighbor
Peer: 192.168.35.2+179 AS 65002 Local: 192.168.35.1 AS 65001
  Type: External    State: Connect        Flags: <ImportEval>
  Last State: Connect       Last Event: ConnectRetry
  Last Error: None
  Export: [ advertised_for_firefly2 ]
  Options: <Preference AddressFamily PeerAS Refresh>
  Address families configured: inet-unicast
  Holdtime: 90 Preference: 170
  Number of flaps: 0

Pour IOS XR

get_info.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm
from pprint import pprint

driver = napalm.get_network_driver('iosxr')
device = driver(
    hostname='127.0.0.1',
    username='vagrant',
    password='vagrant',
    # IOSXRv default ssh port
    optional_args={'port': 2223}) 

print 'Open session: ',
device.open()
print 'OK'

print 'get BGP neighbors'
pprint(device.get_bgp_neighbors())

print 'Close session: ',
device.close()
print 'OK'

Résultat d'exécution


% python get_info.py

Open session:  OK
get BGP neighbors
{u'global': {u'peers': {u'192.168.0.1': {u'address_family': {u'ipv4': {u'accepted_prefixes': 0,
                                                                       u'received_prefixes': 0,
                                                                       u'sent_prefixes': 0}},
                                         u'description': u'test_AS65002',
                                         u'is_enabled': False,
                                         u'is_up': False,
                                         u'local_as': 65001,
                                         u'remote_as': 65002,
                                         u'remote_id': u'0.0.0.0',
                                         u'uptime': -1}},
             u'router_id': u'0.0.0.0'}}
Close session:  OK

Vérification de l'état sur le routeur réel


RP/0/RP0/CPU0:ios#show bgp neighbor
Fri Dec 23 13:14:16.879 UTC

BGP neighbor is 192.168.0.1
 Remote AS 65002, local AS 65001, external link
 Description: test_AS65002
 Remote router ID 0.0.0.0
  BGP state = Idle (eBGP neighbor not directly connected)
  NSR State: None
  Last read 00:00:00, Last read before reset 00:00:00
  Hold time is 180, keepalive interval is 60 seconds
  Configured hold time: 90, keepalive: 30, min acceptable hold time: 3
(snip)

Exemple d'utilisation de NAPALM: paramètres de configuration du routeur

Vous pouvez modifier les paramètres de configuration en utilisant la même procédure que celle présentée dans le blog précédent J'ai essayé de toucher la bibliothèque d'API de contrôle du routeur NAPALM.

Pour JUNOS (échec)

change_hostname_JUNOS.conf


system {
    host-name firefly1_changed_by_NAPALM;
}

set_hostname.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm

# For JUNOS firefly1
driver = napalm.get_network_driver('junos')
device = driver(
    hostname='192.168.34.16',
    username='user1',
    password='password1')

print 'Open session: ',
device.open()
print 'OK'

print 'get hostname : ', 
print device.get_facts()[u'hostname']

print 'Config load (merge mode): ',
device.load_merge_candidate(filename='./change_hostname_JUNOS.conf')
print 'OK'

print 'Compare config: '
print device.compare_config()

print 'Do you commit? y/n'
choice = raw_input().lower()
if choice == 'y':
    print 'Commit config:',
    device.commit_config()
    print 'OK'
else:
    print 'Discard config:',
    device.discard_config()
    print 'OK'

print 'Close session: ',
device.close()
print 'OK'

Résultat d'exécution


% python set_hostname.py                                                                                                                                                                     (git)-[master]
Open session:  OK
get hostname :  firefly1
Config load (merge mode):  OK
Compare config:
[edit system]
-  host-name firefly1;
+  host-name firefly1_changed_by_NAPALM;
Do you commit? y/n
y
Commit config: OK
get hostname :
Traceback (most recent call last):
  File "set_hostname.py", line 41, in <module>
    print device.get_facts()[u'hostname']
  File "/usr/local/lib/python2.7/site-packages/napalm_junos/junos.py", line 182, in get_facts
    interfaces.get()
  File "/Library/Python/2.7/site-packages/jnpr/junos/factory/optable.py", line 64, in get
    self.xml = getattr(self.RPC, self.GET_RPC)(**rpc_args)
  File "/Library/Python/2.7/site-packages/jnpr/junos/rpcmeta.py", line 156, in _exec_rpc
    return self._junos.execute(rpc, **dec_args)
  File "/Library/Python/2.7/site-packages/jnpr/junos/decorators.py", line 58, in wrapper
    result = function(*args, **kwargs)
  File "/Library/Python/2.7/site-packages/jnpr/junos/decorators.py", line 26, in wrapper
    return function(*args, **kwargs)
  File "/Library/Python/2.7/site-packages/jnpr/junos/device.py", line 520, in execute
    raise EzErrors.RpcTimeoutError(self, rpc_cmd_e.tag, self.timeout)
jnpr.junos.exception.RpcTimeoutError: RpcTimeoutError(host: 192.168.34.16, cmd: get-interface-information, timeout: 60)

J'ai une erreur. .. Cependant, sur le routeur réel, les modifications semblent avoir changé sans aucun problème.

Vérification de l'état sur le routeur réel


root@firefly1
(Exécution du programme)

root@firefly1_changed_by_NAPALM>

root@firefly1_changed_by_NAPALM> show version
Hostname: firefly1_changed_by_NAPALM
Model: firefly-perimeter
JUNOS Software Release [12.1X47-D20.7]

[edit]
root@firefly1_changed_by_NAPALM# rollback ?
Possible completions:
  <[Enter]>            Execute this command
  0                    2016-12-24 18:55:57 JST by user1 via netconf
  1                    2016-12-24 18:32:08 JST by root via cli
  2                    2016-12-24 15:20:22 JST by root via cli

Quand j'ai changé les conditions et essayé sans "device.get_facts () [u'hostname ']" immédiatement après la validation, j'ai eu une autre erreur.

Résultat d'exécution


% python set_hostname.py                                                                                                                                                                     (git)-[master]
Open session:  OK
get hostname :  firefly1
Config load (merge mode):  OK
Compare config:
[edit system]
-  host-name firefly1;
+  host-name firefly1_changed_by_NAPALM;
Do you commit? y/n
y
Commit config: OK
Close session:
Traceback (most recent call last):
  File "set_hostname.py", line 44, in <module>
    device.close()
  File "/usr/local/lib/python2.7/site-packages/napalm_junos/junos.py", line 94, in close
    self._unlock()
  File "/usr/local/lib/python2.7/site-packages/napalm_junos/junos.py", line 106, in _unlock
    self.device.cu.unlock()
  File "/Library/Python/2.7/site-packages/jnpr/junos/utils/config.py", line 489, in unlock
    raise UnlockError(rsp=err.rsp)
jnpr.junos.exception.UnlockError: <exception str() failed>

Je n'ai pas eu assez de temps pour dépanner, mais il se peut que quelque chose ne va pas avec le déverrouillage de JUNOS. Je l'ajouterai dès que la cause sera connue.

Pour IOS XR

change_hostname_IOSXR.conf


hostname iosxrv1_changed_by_NAPALM

set_hostname.py


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import napalm

# For Cisco IOSXRv
driver = napalm.get_network_driver('iosxr')
device = driver(
    hostname='127.0.0.1',
    username='vagrant',
    password='vagrant',
    # IOSXRv default ssh port
    optional_args={'port': 2223}) 

print 'Open session: ',
device.open()
print 'OK'

print 'get hostname : ', 
print device.get_facts()[u'hostname']

print 'Config load (merge mode): ',
device.load_merge_candidate(filename='./change_hostname_IOSXR.conf')
print 'OK'

print 'Compare config: '
print device.compare_config()

print 'Do you commit? y/n'
choice = raw_input().lower()
if choice == 'y':
    print 'Commit config:',
    device.commit_config()
    print 'OK'
else:
    print 'Discard config:',
    device.discard_config()
    print 'OK'

print 'get hostname : ', 
print device.get_facts()[u'hostname']

print 'Close session: ',
device.close()
print 'OK'

Résultat d'exécution


% python set_hostname.py                                                                                                                                                                     (git)-[master]
Open session:  OK
get hostname :  ios
Config load (merge mode):  OK
Compare config:
---
+++
@@ -1,5 +1,6 @@
 !! Last configuration change at Fri Dec 23 13:20:24 2016 by vagrant
 !
+hostname iosxrv1_changed_by_NAPALM
 telnet vrf default ipv4 server max-servers 10
 username vagrant
  group root-lr
Do you commit? y/n
y
Commit config: OK
get hostname :  iosxrv1_changed_by_NAPALM
Close session:  OK

Vérification de l'état sur le routeur réel


RP/0/RP0/CPU0:ios#
(Exécution du programme)

RP/0/RP0/CPU0:iosxrv1_changed_by_NAPALM#

RP/0/RP0/CPU0:iosxrv1_changed_by_NAPALM#sh running-config hostname
Fri Dec 23 13:21:32.129 UTC
hostname iosxrv1_changed_by_NAPALM

IOSXR a pu modifier les paramètres avec succès!

Résumé

Cette fois, il a été confirmé qu'en utilisant NAPALM, les informations peuvent être acquises et les paramètres du routeur peuvent être effectués dans l'environnement du routeur JUNOS et du routeur IOS XR. Certaines choses ne se sont pas bien déroulées, mais cela pourrait être amélioré à l'avenir. Je l'ajouterai lorsque je comprendrai la cause du problème.

NAPALM a déjà implémenté un grand nombre de fonctions, et il semble que NAPALM peut réduire considérablement l'effort requis pour développer un logiciel d'automatisation dans un environnement multifournisseur.

De plus, le développement par la communauté NAPALM étant très actif, on peut s'attendre à une nouvelle extension des fonctions et à une augmentation des modèles compatibles dans le futur.

Pour le moment, les seules fonctions qui semblent manquer sont les produits Brocade, les fonctions liées à OSPF et MPLS. Si vous le touchez un peu plus, vous remarquerez peut-être divers aspects qui manquent.

Le programme que j'ai essayé cette fois est publié sur Github, veuillez donc vous y référer si vous le souhaitez. (Désolé pour le code sale ...) https://github.com/taijiji/sample_nalapm

finalement

Cette fois, je viens de présenter les fonctions de NAPALM, mais si j'ai le temps dans le futur, j'ai essayé d'utiliser le blog précédent "[PyEZ et JSNAPy. Partie 4: Automatisation des paramètres de FAI avec PyEZ et JSNAPy]( J'essaierai également de développer une version compatible multi-vendeurs (JUNOS et IOSXR pour le moment) de l'outil d'automatisation réalisé avec "http://qiita.com/taijijiji/items/983189f9bdebaa53e499)".

Si quelqu'un a essayé de développer un outil d'automatisation à l'aide de NAPALM, veuillez le présenter ultérieurement NetOps Coding. Je suis contente.

Passez un bon Noël.

Recommended Posts

Suite ・ J'ai essayé de toucher la bibliothèque d'API de contrôle de routeur multifournisseur NAPALM
J'ai essayé de toucher la bibliothèque d'API de contrôle de routeur multi-fournisseur NAPALM
J'ai essayé la bibliothèque changefinder!
J'ai essayé le roman Naro API 2
J'ai essayé l'API du roman Naruro
J'ai essayé d'utiliser l'API checkio
J'ai essayé de toucher l'API COTOHA
J'ai essayé d'utiliser l'API BigQuery Storage
J'ai recherché dans la bibliothèque l'utilisation de l'API Gracenote
J'ai essayé d'accéder à l'API Qiita depuis le début
J'ai essayé d'utiliser l'API Google Cloud Vision
J'ai essayé d'utiliser la bibliothèque de programmation fonctionnelle toolz
J'ai essayé d'utiliser l'API de Sakenowa Data Project
J'ai essayé de frapper l'API avec le client python d'echonest
[Première API COTOHA] J'ai essayé de résumer l'ancienne histoire
J'ai essayé d'utiliser la bibliothèque Python de Ruby avec PyCall
J'ai essayé de sauvegarder l'historique des demandes d'API DRF avec django-request
[Python] J'ai essayé de collecter des données en utilisant l'API de wikipedia
J'ai essayé l'API Google Cloud Vision pour la première fois
J'ai essayé d'obtenir diverses informations de l'API codeforces
[Pour les débutants] J'ai essayé d'utiliser l'API Tensorflow Object Detection
J'ai essayé de toucher l'API Qiita
J'ai créé une bibliothèque Python pour appeler l'API de LINE WORKS
J'ai essayé d'utiliser l'API COTOHA (il y a aussi du code sur GitHub)
Continuation: j'ai essayé d'introduire l'outil de génération de diagramme blockdiag
J'ai essayé le tutoriel TensorFlow 1er
J'ai essayé de créer l'API Quip
J'ai essayé le tutoriel TensorFlow 2ème
J'ai touché l'API de Tesla
J'ai essayé de déplacer le ballon
J'ai essayé d'estimer la section.
J'ai essayé d'appeler l'API de prédiction du modèle d'apprentissage automatique de WordPress
J'ai essayé de contrôler plusieurs servomoteurs MG996R en utilisant le servomoteur PCA9685.
J'ai essayé de résumer diverses phrases à l'aide de l'API de synthèse automatique "summpy"
J'ai essayé de visualiser le modèle avec la bibliothèque d'apprentissage automatique low-code "PyCaret"
J'ai essayé d'obtenir les informations sur le film de l'API TMDb avec Python
J'ai essayé de toucher des méthodes liées au toucher dans le module de scène de pythonista
J'ai essayé de contrôler la bande passante et le délai du réseau avec la commande tc