This is the article on the 24th day of NetOpsCoding Advent Calendar 2016.
NAPALM is an open source Python library for setting up network devices and acquiring information, and controls multiple vendor products with a unified interface. It is developed for that purpose. For those who are planning to automate in a multi-vendor network operating environment, a multi-vendor library like NAPALM is a long-awaited existence.
NAPALM was introduced in the article "I tried touching the router control API library NAPALM" in June 2015, but it is still NANOG. Development is being actively continued under the initiative of the community centered on, and the number of functions and compatible models is increasing one after another. I felt that it might be time to put it into an actual operation site in a multi-vendor environment, so I summarized the information again this time.
NAPALM supports the following network operating systems.
--Arista EOS: 4.15.0F or later --Juniper JunOS: 12.1 or later --Cisco IOS-XR: 5.1.0 or later --Fortinet FortiOS: 5.2.0 or later --IBM: Supported version unknown --Cisco NXOS: 6.1 or later (Nexus 5k, 6k, 7k version 7.2 or later) --Cisco IOS: 12.4 (20) T or later
In the background of NAPALM, the manufacturer's official API (Juniper PyEZ and Arista eAPI pyeapi) etc.), and unofficial APIs developed by individuals or communities (pyIOSXR and netmiko) Etc.) are combined to make up.
Since it is a community-led development, it seems that the functions are being expanded steadily with the idea that "you can create the missing functions yourself". As of June 2015, there were only four compatible models, IOS XR, JUNOS, EOS, and FortiOS, so it can be seen that development has progressed dramatically in the past year and a half.
At the time of this article, NAPALM has the following features implemented. However, the functions implemented by the OS vary, so please refer to the official page Supported Devices for details.
--Load config (replace / merge) / Compare / Commit / Dicard / Rollback --Acquisition of device information --Get SNMP information --Acquisition of NTP information --Get ARP table --Getting interface information --Acquisition of LLDP information --Get BGP information --Getting routing information --Getting SLA prove information --Acquisition of user information --Acquisition of optical output information --Getting VRF network instances information --Get firewall policy information --Get ping information --Get Traceroute information
It is very helpful in developing automation software that the function of the status confirmation system is substantial. As I wrote in my previous blog "I tried using PyEZ and JSNAPy", it is very important to make the process of checking the normality of network devices into software. It is a work that breaks. Implement "Implementation of information acquisition command-> Acquire target character string with regular expression-> Acquire extracted character string as information or judge normal / abnormal" which is normally inevitable for software developers By using the process as a library without being aware of the vendor / model, it is possible to significantly reduce the development effort.
NAPALM is not only embedded in software, but is also expected to be called from an automation framework that is being introduced in server infrastructure operations. At the moment, NAPALM modules are being developed to work with Ansible and Salt.
This article does not provide details, but if you are interested, please refer to the following materials.
Let's try using a router to see what you can actually do with NAPALM.
As a result of randomly touching the function I want to use, the amount has become quite large, so please check from the item you are interested in.
-Environment -Reference -[Install](http://qiita.com/taijijiji/items/9dfcaa6d868958985095#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC% E3% 83% AB) -[Preparation of router](http://qiita.com/taijijiji/items/9dfcaa6d868958985095#%E3%83%AB%E3%83%BC%E3%82%BF%E3%81%AE%E4%B8 % 8B% E6% BA% 96% E5% 82% 99) -[NAPALM usage example: Acquisition of device information](http://qiita.com/taijijiji/items/9dfcaa6d868958985095#napalm%E5%88%A9%E7%94%A8%E4%BE%8B-%E6%A9 % 9F% E5% 99% A8% E6% 83% 85% E5% A0% B1% E3% 81% AE% E5% 8F% 96% E5% BE% 97) -[NAPALM usage example: Obtaining interface address information](http://qiita.com/taijijiji/items/9dfcaa6d868958985095#napalm%E5%88%A9%E7%94%A8%E4%BE%8B-%E3% 82% A4% E3% 83% B3% E3% 82% BF% E3% 83% 95% E3% 82% A7% E3% 83% BC% E3% 82% B9% E3% 82% A2% E3% 83% 89% E3% 83% AC% E3% 82% B9% E6% 83% 85% E5% A0% B1% E3% 81% AE% E5% 8F% 96% E5% BE% 97) -[NAPALM usage example: Get ARP table information](http://qiita.com/taijijiji/items/9dfcaa6d868958985095#napalm%E5%88%A9%E7%94%A8%E4%BE%8B-arp%E3 % 83% 86% E3% 83% BC% E3% 83% 96% E3% 83% AB% E6% 83% 85% E5% A0% B1% E3% 81% AE% E5% 8F% 96% E5% BE % 97) -[NAPALM usage example: Acquisition of routing information for a specific route](http://qiita.com/taijijiji/items/9dfcaa6d868958985095#napalm%E5%88%A9%E7%94%A8%E4%BE%8B-% E7% 89% B9% E5% AE% 9A% E7% B5% 8C% E8% B7% AF% E3% 81% AE% E3% 83% AB% E3% 83% BC% E3% 83% 86% E3% 82% A3% E3% 83% B3% E3% 82% B0% E6% 83% 85% E5% A0% B1% E3% 81% AE% E5% 8F% 96% E5% BE% 97) -[NAPALM usage example: Get BGP neighbor information](http://qiita.com/taijijiji/items/9dfcaa6d868958985095#napalm%E5%88%A9%E7%94%A8%E4%BE%8B-bgp%E3 % 83% 8D% E3% 82% A4% E3% 83% 90% E3% 83% BC% E6% 83% 85% E5% A0% B1% E3% 81% AE% E5% 8F% 96% E5% BE % 97) -[NAPALM usage example: Router configuration settings](http://qiita.com/taijijiji/items/9dfcaa6d868958985095#napalm%E5%88%A9%E7%94%A8%E4%BE%8B-%E3%83 % AB% E3% 83% BC% E3% 82% BF% E3% 81% AE% E3% 82% B3% E3% 83% B3% E3% 83% 95% E3% 82% A3% E3% 82% B0 % E8% A8% AD% E5% AE% 9A) -Summary -Finally
In this article, I experimented in the following environment. Everything except the Macbook can be prepared for free.
--PC (host machine) - MacBookAir OSX El Capitan 10.11.6 --Virtual router
If you want to know about Vagrant integration of firefly and IOS XRv, please refer to the following blog. -The story of progress in automated development when running firefly with Vagrant -I tried IOS-XRv Vagrant
This time, I proceeded with the implementation while looking at the following articles. -NAPALM Github Page -NAPALM Official Document
Install the latest version of NAPALM (version 1.1.0 at the time of this blog). Here, pip, which is a Python package management system, is used.
% 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
In order to use firefly, it is set as follows. --Host name: firefly1 --IP address: 192.168.34.16/24 --Username: user1 --Password: password1
For the procedure for building firefly Vagrant, please refer to The story of how automated development progressed when running firefly with 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
firefly additional settings
set system root-authentication plain-text-password
set system login user user1 class super-user
set system login user user1 authentication plain-text-password
#The default setting is ge-0/0/Communication with the host machine is not possible because 1 is set in the untrust zone.
#Here the host machine(MacbookAir)I want to operate the automation tool and communicate with ge-0/0/I am changing 1 to trust zone.
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
#The default setting is flow-based transfer mode(Mode to operate firewall function)Is enabled and
#Routing protocols such as BGP and OSPF will not work as they are.
#Here, in order to operate the routing protocol, packet-The setting to change to based transfer mode is implemented.
#To switch the mode, you need to restart after setting.
delete security policies
set security forwarding-options family mpls mode packet-based
set security forwarding-options family inet6 mode packet-based
#BGP related settings for dummies
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
#In addition, I was able to use NAPALM without setting the following NETCONF.
# (Not set) set system services netconf ssh
Check settings with 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;
}
}
}
Make sure you can ssh login to firefly from the host machine
% 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]
In order to use IOSXRv, it is set as follows. --Hostname: ios (default) --IP address: 127.0.0.1 --IOSXRv-Vagrant default settings use TCP2223 for SSH port from host machine --Username: vagrant --Password: vagrant
Please refer to I tried IOS-XRv Vagrant for the procedure to build IOSXRv.
Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = "IOS-XRv"
end
IOSXRv additional settings
#Required when using NAPALM
xml agent tty iteration off
#Dummy BGP settings
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
Check settings with 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
First, let's get the device information. Information can be obtained as a dictionary type variable by using get_facts (). ..
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'
Execution result
% 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
Checking the status of the actual router
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
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'
Execution result
% 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'}
Checking the status of the actual router
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
To get the interface address information, use the get_interfaces_ip () function.
Not implemented this time, but if you want to get interface up / down and MAC information, [get_interfaces () function](https://napalm.readthedocs.io/en/latest/base.html#napalm_base.base.NetworkDriver .get_interfaces), get_interfaces_counters () function if you want to get the interface error counter, If you want to get it, you can get the information by using get_optics () function. ..
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'
Execution result
% 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
Checking the status of the actual router
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
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'
Execution result
% 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
Checking the status of the actual router
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
Use the get_arp_table () function to get the ARP table information.
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'
Execution result
% 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
Checking the status of the actual router
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
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'
Execution result
% 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
Checking the status of the actual router
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
You can get the routing information of the specified route by using get_route_to () function.
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'
Execution result
% 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
Checking the status of the actual router
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
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'
Execution result
% 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: .
I can see the following on the router, but it failed on NAPALM.
Checking the status of the actual router
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.
get_route_to () function I wondered if it was wrong not to specify the protocol which is an optional argument. I thought, I tried the following patterns, but it didn't work.
pprint(device.get_route_to(destination=u'10.0.2.2', protocol=u'bgp'))
Execution result
% 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>
It may be a bug in pyIOSXR, so I'll try to find out more when I have time.
You can get BGP neighbor information by using the get_bgp_neighbors () function.
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'
Execution result
% 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
Checking the status of the actual router
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
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'
Execution result
% 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
Checking the status of the actual router
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)
You can change the config settings using the same procedure as introduced in the previous blog I tried to touch the router control API library NAPALM.
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'
Execution result
% 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)
I got an error. .. However, on the actual router, it seems that the changes have been made without any problems.
Checking the status of the actual router
root@firefly1
(Program execution)
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
When I changed the conditions and tried without "device.get_facts () [u'hostname']" immediately after commit, I got another error.
Execution result
% 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>
I haven't had enough time to troubleshoot, but it may be that something is wrong with JUNOS's Unlock. I will add it as soon as the cause is known.
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'
Execution result
% 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
Checking the status of the actual router
RP/0/RP0/CPU0:ios#
(Program execution)
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 was able to change the settings successfully!
This time, it was confirmed that by using NAPALM, information can be acquired and router settings can be performed in the environment of JUNOS router and IOS XR router. There were some things that didn't go well, but it may be improved in the future. I will add it when I understand the cause of the problem.
NAPALM has already implemented a large number of functions, and it seems that NAPALM can significantly reduce the man-hours for developing automation software in a multi-vendor environment.
In addition, since the development by the NAPALM community is very active, we can expect further expansion of functions and an increase in compatible models in the future.
At the moment, the only functions that seem to be missing are Brocade products, OSPF-related, and MPLS-related functions. If you touch it a little more, you may notice various aspects that are missing.
The program I tried this time is published on Github, so please refer to it if you like. (Sorry for the dirty code ...) https://github.com/taijiji/sample_nalapm
This time I ended up just introducing the functions of NAPALM, but if I have time in the future, I tried using the past blog "[PyEZ and JSNAPy. Part 4: Automating ISP setting work with PyEZ and JSNAPy]( I will also try to develop a multi-vendor compatible version (JUNOS and IOSXR for the time being) of the automation tool made with "http://qiita.com/taijijiji/items/983189f9bdebaa53e499)".
If anyone has tried to develop an automation tool using NAPALM, please introduce it in the future NetOps Coding. I'm glad.
Have a nice Christmas.
Recommended Posts