olly - Fotolia

Tip

Compare Paramiko, Netmiko and NAPALM network automation

Python is a useful language, but it can't do everything. Explore some basic network automation scripts that use Python with three automation libraries: Paramiko, Netmiko and NAPALM.

Python is the most common language for network automation, but it can't do the job easily all by itself. Fortunately, several motivated individuals have created libraries that handle a lot of the details of network automation with Python. These automation libraries enable users to more easily build automation systems.

Users starting with automation should first gain a basic understanding of the Python scripting language and data structures, such as lists, tuples, dictionaries and sets. They'll also want to learn the basics of the Jinja2 templating language and YAML (YAML Ain't Markup Language). Users get a powerful automation framework when they combine Python scripting, Jinja2 for templating, YAML for data representation and the automation libraries below.

Automation libraries

Network automation with Python and automation libraries can enable simplified communication with network devices. In this article, we take a look at three network automation libraries: Paramiko, Netmiko and NAPALM, or Network Automation Programmability Abstraction Layer with Multivendor support. Each library builds on its predecessor to provide greater layers of abstraction that enable users to build more efficient automation systems.

Paramiko

Paramiko is a low-level Secure Shell (SSH) client library. We can use it to programmatically control connecting to a network device's command-line interface (CLI) over a secure SSH connection. With the library, users send commands a person would normally type and parse the results of each command's execution, also known as screen scraping.

The Python script below uses the Paramiko library to query a Cisco Catalyst 3560 router for its Address Resolution Protocol (ARP) table. It is the first step of a script to identify the switch port where a device is connected.

01) #!/usr/bin/env python3
02) import sys
03) from time import sleep
04) import paramiko
05) router="192.168.1.108"
06)  
07) # Create an ssh connection and set terminal length 0
08) conn = paramiko.SSHClient()
09) conn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
10) conn.connect(router, username="tester", password="foobar")
11) router_conn = conn.invoke_shell()
12) print('Successfully connected to %s' % router)
13) router_conn.send('terminal length 0\n')
14) sleep(1)        # Wait for the cmd to be sent and processed
15)  
16) # Send the command and wait for it to execute
17) router_conn.send("show arp\n")
18) sleep(2)
19)  
20) # Read the output, decode into UTF-8 (ASCII) text, and print
21) print(router_conn.recv(5000).decode("utf-8"))

Lines one to five import the additional libraries we need and define the IP address of the router we're going to query. Lines seven to 14 create an SSH connection to the router and login using the name tester with the password foobar. A command is sent to disable output pagination. Lines 16 to 18 send the show arp command, and line 21 reads the command result and prints it. The connection is closed when the script ends.

Here is the result:

01) $ ./paramiko-example.py 
02) Successfully connected to 192.168.1.108
03)  
04) test-sw>terminal length 0
05) test-sw>show arp
06) Protocol  Address          Age (min)  Hardware Addr   Type   Interface
07) Internet  192.168.1.1             1   0025.9c1a.4c89  ARPA   Vlan1
08) Internet  192.168.1.3             0   0c84.dcc4.8569  ARPA   Vlan1
09) Internet  192.168.1.108           -   bcc4.933e.49c0  ARPA   Vlan1
10) Internet  192.168.1.141           0   4c32.7596.b70b  ARPA   Vlan1
11) test-sw>

Paramiko provides a low-level SSH interface to network devices. Many parameters that vary according to device model are encoded in the script, including changes in command syntax for different OSes. In addition, we would have to handle all the details of gathering data, making configuration changes and verifying those changes. To make a configuration change, we would need to manage each step of the process -- enabling access, entering config mode, sending the changes and saving the changes. Fortunately, other frameworks, like Netmiko, do a lot of this work for us.

Netmiko

The Netmiko library helps users hide many details of common device communications functions. It uses Paramiko for the low-level SSH connectivity, but it provides greater abstraction of the communication with a variety of network device models. Netmiko supports a wide range of devices, and the Netmiko script is much shorter than the Paramiko script, as seen below.

01) #!/usr/bin/env python3
02) import sys
03) from time import sleep
04) from netmiko import ConnectHandler
05) dev={
06)   'device_type': 'cisco_ios',
07)   'host': '192.168.1.108',
08)   'username': 'tester',
09)   'password': 'foobar',
10) } # Use a dictionary to pass the login parameters
11)  
12) # Connect to the device
13) router_conn = ConnectHandler(**dev)
14)  
15) # Send the command and print the result
16) print(router_conn.send_command("show arp\n"))

Lines one to four import the necessary modules, and lines five to 10 then create a Python dictionary that contains the connection parameters for this device. When working with many devices, users will need additional code to iterate over the devices, which they can easily do with a list of dictionaries. The device connection is one line, and another line sends the command and prints the output.

The Netmiko output is shorter as well, having stripped the device prompts from around the command output:

01) $ ./netmiko-example.py 
02) Protocol  Address          Age (min)  Hardware Addr   Type   Interface
03) Internet  192.168.1.1             1   0025.9c1a.4c89  ARPA   Vlan1
04) Internet  192.168.1.3             0   0c84.dcc4.8569  ARPA   Vlan1
05) Internet  192.168.1.108           -   bcc4.933e.49c0  ARPA   Vlan1
06) Internet  168.1.141               0   4c32.7596.b70b  ARPA   Vlan1

Netmiko used the device_type definition to properly handle communications with the device, and we didn't have to do any of the device-specific work. While Netmiko enables users to issue device commands and get the responses, it doesn't automate configuration management. That's where we use NAPALM.

NAPALM

NAPALM is built on top of Netmiko and provides a mechanism for interacting with device configurations. It supports a smaller set of devices than Netmiko: Arista, Juniper and Cisco (IOS, IOS XR, NX-OS and NX-OS SSH). It also supports a large set of getter functions that retrieve basic device data. The following script uses the get_arp_table() function:

01) #!/usr/bin/env python3
02) import sys
03) import time
04) import napalm
05) import os
06) import json
07) dev_type = 'ios'
08) dev_creds={
09)   'hostname': '192.168.1.108',
10)   'username': 'tester',
11)   'password': 'foobar',
12)   'optional_args': {'secret': 'foobar'}
13) } # Use a dictionary for the login parameters
14)  
15) driver = napalm.get_network_driver(dev_type)
16) conn = driver(**dev_creds)
17) conn.open()
18) output = conn.get_arp_table()
19) print(json.dumps(output, indent=2))
20) close()

The setup with NAPALM is longer than with Netmiko because it needs more libraries and the login parameters must be specified differently, as in lines two to 13. The connection is established in lines 15 to 17. Finally, the ARP table information is retrieved.

NAPALM returns it in Python dictionary format, so we use a library function to prettyprint it:

01) $ ./napalm-example.py 
02) [
03)   {
04)     "interface": "Vlan1",
05)     "mac": "00:25:9C:1A:4C:89",
06)     "ip": "192.168.1.1",
07)     "age": 0.0
08)   },
09)   {
10)     "interface": "Vlan1",
11)     "mac": "0C:84:DC:C4:85:69",
12)     "ip": "192.168.1.3",
13)     "age": 0.0
14)   },
15)   {
16)     "interface": "Vlan1",
17)     "mac": "BC:C4:93:3E:49:C0",
18)     "ip": "192.168.1.108",
19)     "age": 0.0
20)   },
21)   {
22)     "interface": "Vlan1",
23)     "mac": "4C:32:75:96:B7:0B",
24)     "ip": "192.168.1.141",
25)     "age": 2.0
26)   }
27) ]

The dictionary output can be used directly within Python. The other libraries provide the CLI textual output, which would have to be converted to a Python data structure to be useful for other purposes.

The real power of NAPALM is in its ability to work with configurations, including the following:

  • configuration replace
  • configuration merge
  • configuration compare
  • commit a deployed configuration
  • discard a candidate configuration
  • roll back to a prior configuration

Getting started with network automation and Python

Several online courses and videos cover network automation with Python and automation frameworks. Nick Russo's courses are a good starting point. Ivan Pepelnjak also explores other technologies in his more advanced "Building Network Automations Solutions" and "Ansible for Networking Engineers" (with David Barroso) courses.

Dig Deeper on Network management and monitoring