Python: Network Automation with Napalm

4 minute read

Updated:

What is Napalm?

NAPALM (Network Automation and Programmability Abstraction Layer with Multi-vendor support) is a Python library that implements a set of functions to interact with different network device Operating Systems using a unified API. Unified API means the same code is used to configure multi-vendor devices.

N.A.P.A.L.M is and can:

  • Python library
  • Open-source
  • Unified API for multiple vendors
  • Methods to manipulate configs
  • Methods to retrieve data

Supported Network Operating Systems

It is used to interact with different hardware networking vendors. It works as an API on top of other APIs, adding another level of abstraction. Lately, many vendors have developed APIs to make it easier to interact with their equipment. For example, most of the JunOS devices support Juniper PyEZ, and so does Cisco’s Nexus with its NX-API.

  • Arista EOS
  • Cisco IOS
  • Cisco IOS-XR
  • Cisco NX-OS
  • Juniper JunOS

How does NAPALM work?

Let’s look at it this way, if you wanted to access different network devices with different operating systems through Python, we would probably have to use libraries developed for each operating system. It would be a tedious task to apply Network Programmability in these circumstances. To facilitate programming, NAPALM adds an abstraction layer. This layer allows us to use the same function to perform the same action on different operating systems.

We will use our previous topology as below:

picture

Lab Configuration same as previous.

Installation

You can install napalm with pip:

pip install napalm

That will install all the core drivers currently available.

NAPALM CLI

The NAPALM installation comes with a tool that allows us to use NAPALM directly from the command line. Its use is quite simple and we can see how it is used in the command’s help menu. We execute the following command to see this menu:

napalm --help

From this tool it is possible to execute configuration operations on the devices, validate configurations or states and make calls to the NAPALM methods to obtain data from the devices.

These actions are carried out by passing to the command the user arguments and the password of the device to which we are going to connect, the operating system, the IP or name of the equipment and finally the name of the method.

Let’s see an example:

napalm --user admin --password cisco --vendor ios 192.168.10.10 call ping --method-kwargs "destination='192.168.10.10'"

Command Output:-

{
    "success": {
        "probes_sent": 5,
        "packet_loss": 0,
        "rtt_min": 8.0,
        "rtt_max": 18.0,
        "rtt_avg": 12.0,
        "rtt_stddev": 0.0,
        "results": [
            {
                "ip_address": "192.168.10.10",
                "rtt": 0.0
            },
            {
                "ip_address": "192.168.10.10",
                "rtt": 0.0
            },
            {
                "ip_address": "192.168.10.10",
                "rtt": 0.0
            },
            {
                "ip_address": "192.168.10.10",
                "rtt": 0.0
            },
            {
                "ip_address": "192.168.10.10",
                "rtt": 0.0
            }
        ]
    }
}

IOS Prerequisites

IOS has no native API to play with, that’s the reason why Napalm used the Netmiko library to interact with it. Having Netmiko installed in your working box is a prerequisite.

Archive

IOSDriver requires that the archive functionality be enabled on IOS Device to perform auto-rollback on error. Make sure it’s enabled and set to a local filesystem (for example ‘flash:’ or ‘bootflash:’).

archive
  path flash:archive
  write-memory

Configuration file template Requirement

  • IOS requires a config file to begin with a version eg. 15.0 and end marker at the end of the file. Otherwise, IOS will reject configure replace operation.
  • For the diff to work properly, the indentation of your candidate file has to exactly match the indentation in the running-config.
  • Finish blocks with ! as with the running-config, otherwise, some IOS versions might not be able to generate the diff properly.

SCP File Transfers

The NAPALM-ios driver requires SCP to be enabled on the managed device. SCP server functionality is disabled in IOS by default and is configured using ip scp server enable.

Selecting the right driver

We can only specify what OS we are going to talk to and NAPALM will select the correct NetworkDriver. NetworkDriver is a library with all the functions related to that OS. You can select the driver you need by doing the following:

# Import get_network_diver
from napalm import get_network_driver
'''Use the appropriate network driver to connect to the device.
The network driver is ios for cisco ios'''
get_network_driver('ios')

Programming samples

NAPALM tries to provide a standard interface and mechanisms to push configuration and retrieve state data from network devices. This method is very useful in combination with tools like Ansible, which in turn allows you to manage a set of devices independent of their network OS.

from napalm import get_network_driver
# Connect to device.
driver = get_network_driver('ios')
# the device IP and password.
device = driver('192.168.10.11', 'admin', 'cisco') 
device.open()
# Get facts from device.
output = device.get_facts()
print(output)
# close the session with the device.
device.close()

Output from the Router

root@NetworkAutomation-1:~# python3 02_napalm.py 
{'uptime': 660, 'vendor': 'Cisco', 'os_version': 'IOSv Software (VIOS-ADVENTERPRISEK9-M), Version 15.6(2)T, RELEASE SOFTWARE (fc2)', 'serial_number': '9HHI7QPAASZSJCJC1NC87', 'model': 'IOSv', 'hostname': 'R1', 'fqdn': 'R1.cisco.com', 'interface_list': ['GigabitEthernet0/0', 'GigabitEthernet0/1', 'GigabitEthernet0/2', 'GigabitEthernet0/3']}

Import JSON to output a nicely formatted JSON object.

import json
from napalm import get_network_driver

driver = get_network_driver('ios')
device = driver('192.168.10.10', 'admin', 'cisco')
device.open()

output = device.get_interfaces()
print(json.dumps(output, indent=4))

device.close()
The output is a nicely formatted
root@NetworkAutomation-1:~# python3 03_napalm.py 
{
    "GigabitEthernet0/0": {
        "is_enabled": true,
        "is_up": true,
        "description": "",
        "mac_address": "0C:79:31:D9:00:00",
        "last_flapped": -1.0,
        "mtu": 1500,
        "speed": 100.0
    },
    "GigabitEthernet0/1": {
        "is_enabled": false,
        "is_up": false,
        "description": "",
        "mac_address": "0C:79:31:D9:00:01",
        "last_flapped": -1.0,
        "mtu": 1500,
        "speed": 1000.0
    },
    "GigabitEthernet0/2": {
        "is_enabled": false,
        "is_up": false,
        "description": "",
        "mac_address": "0C:79:31:D9:00:02",
        "last_flapped": -1.0,
        "mtu": 1500,
        "speed": 1000.0
    },
    "GigabitEthernet0/3": {
        "is_enabled": false,
        "is_up": false,
        "description": "",
        "mac_address": "0C:79:31:D9:00:03",
        "last_flapped": -1.0,
        "mtu": 1500,
        "speed": 1000.0
    }
}

Configuration support Method

  • Config.replace
  • Config.merge
  • Commit Confirm
  • Compare config
  • Atomic Changes
  • Rollback

The NAPALM library offers various methods we can invoke on a device object. Check them out in the official docs.

Comments