Python

A Beginner's Guide to NAPALM Network Automation

A Beginner's Guide to NAPALM Network Automation
In: Python, NetDevOps

Hello there, fellow Network Automation enthusiasts! I'm thrilled to see you're still sticking around. Either you're really interested in learning more or you're just trying to avoid doing actual work. Either way, I won't judge - in fact, I applaud your choice to pursue automation! Today, we're going to talk about a Python library that will make your life easier and your boss happier - NAPALM, let's get cracking and see what NAPALM can do for you!

Overview

NAPALM (Network Automation and Programmability Abstraction Layer with Multivendor support) is a Python library that implements a set of functions to interact with different network device operating systems using a unified API. The library supports several methods to connect to the devices, manipulate configurations, or retrieve data. In this blog post, we will explore the benefits of using NAPALM for network automation and how it can make managing network devices much easier.

Supported Network Operating Systems

NAPALM supports several network operating systems, including Arista EOS, Cisco IOS, Cisco IOS-XR, Cisco NX-OS, and Juniper JunOS. This allows network engineers to use a single library to automate network devices, regardless of their underlying operating system. This is particularly useful in environments where multiple vendors are used, as it removes the need to have separate scripts for each device type.

Common Interface and Mechanisms

NAPALM provides a common interface and mechanisms to push configuration and retrieve state data from network devices. This is achieved through a set of functions that abstract the differences between network operating systems. The benefit of this approach is that it allows you to manage a set of devices independent of their network OS.

For example, you can use the same function to retrieve the ARP table for a Cisco IOS device and a Juniper JunOS device. This simplifies the automation process, as you do not need to know the specific commands to retrieve data or configure devices for each operating system.

Examples

As they say, the best way to learn is through examples, and we couldn't agree more. By seeing NAPALM in action, you'll be able to grasp how it works and how it can make your life easier as a network engineer. So, let's dive in and see what NAPALM can do.

How to use NAPALM to connect to a single switch and obtain the MAC address table?

To use NAPALM to connect to a single switch and obtain the MAC address table, you first need to install the library and import the appropriate modules. Once you've done that, you can use the get_mac_address_table() function to retrieve the MAC address table from the switch.

You can find all the available functions/methods here - https://napalm.readthedocs.io/en/latest/support/index.html#general-support-matrix

pip install napalm
from napalm import get_network_driver
import getpass
import json

passwd = getpass.getpass('Please enter the password: ') # Reads the output from the user and save it as a string

driver = get_network_driver('ios')
switch_01 = {
    "hostname": '10.10.20.19', 
    "username": "cisco",
    "password": passwd,
    "optional_args": {"secret": passwd}
    }

switch_01_conn = driver(**switch_01)
switch_01_conn.open()
print(f"Connecting to {switch_01['hostname']}")
output = switch_01_conn.get_mac_address_table() #get mac-address table method
switch_01_conn.close()

output_json = json.dumps(output, indent=4)
print(output_json)

Let's break down the code line-by-line.

  1. from napalm import get_network_driver - This line imports the get_network_driver function from the NAPALM library, which is used to create a network driver object that can be used to interact with network devices.
  2. import getpass - This line imports the getpass module from the Python standard library, which provides a way to securely read user input from the command line.
  3. import json - This line imports the json module from the Python standard library, which is used to convert Python objects into JSON format and vice versa.
  4. passwd = getpass.getpass('Please enter the password: ') - This line prompts the user to enter a password, which is then read securely from the command line and stored as a string in the passwd variable.
  5. driver = get_network_driver('ios')- This line creates a network driver object for Cisco IOS devices using the get_network_driver function from NAPALM.
  6. switch_01 = {...} - This line creates a Python dictionary that contains the connection details for a network device, including the hostname or IP address, username, password, and any optional arguments (in this case, the secret argument (enable password) is set to the same value as the password).
  7. switch_01_conn = driver(**switch_01) - This line uses the network driver object to create a connection to the network device specified in the switch_01 dictionary.
  8. switch_01_conn.open() - This line opens the connection to the network device.
  9. print(f"Connecting to {switch_01['hostname']}") - This line prints a message to the console indicating that the script is connecting to the specified network device.
  10. output = switch_01_conn.get_mac_address_table() - This line retrieves the MAC address table from the network device using the get_mac_address_table method of the network driver object.
  11. switch_01_conn.close() - This line closes the connection to the network device.
  12. output_json = json.dumps(output, indent=4) - This line converts the output variable (which contains the MAC address table data) to JSON format and stores the result in the output_json variable.
  13. print(output_json) - This line prints the JSON-formatted MAC address table data to the console.

This is the output you would see after running the script.

Connecting to 10.10.20.19
[
    {
        "mac": "00:E0:4C:68:00:90",
        "interface": "Gi0/0",
        "vlan": 10,
        "static": false,
        "active": true,
        "moves": -1,
        "last_move": -1.0
    },
    {
        "mac": "DC:A6:32:04:D2:56",
        "interface": "Gi0/0",
        "vlan": 10,
        "static": false,
        "active": true,
        "moves": -1,
        "last_move": -1.0
    },
    {
        "mac": "00:50:79:66:68:06",
        "interface": "Gi1/1",
        "vlan": 20,
        "static": false,
        "active": true,
        "moves": -1,
        "last_move": -1.0
    },
    {
        "mac": "00:50:79:66:68:08",
        "interface": "Gi1/2",
        "vlan": 20,
        "static": false,
        "active": true,
        "moves": -1,
        "last_move": -1.0
    }
]

If you don't convert the output to JSON (as explained in steps #12-13), it won't look nice as shown below.

[{'mac': '00:E0:4C:68:00:90', 'interface': 'Gi0/0', 'vlan': 10, 'static': False, 'active': True, 'moves': -1, 'last_move': -1.0}, {'mac': 'B4:2E:99:FC:83:76', 'interface': 'Gi0/0', 'vlan': 10, 'static': False, 'active': True, 'moves': -1, 'last_move': -1.0}, {'mac': 'DC:A6:32:04:D2:56', 'interface': 'Gi0/0', 'vlan': 10, 'static': False, 'active': True, 'moves': -1, 'last_move': -1.0}]

How to use NAPALM to connect to a single switch and obtain facts?

In this second example, let's connect to the same switch and obtain some facts such as hostname, OS Version and serial number.

get_facts() is a method provided by the NAPALM library that retrieves a set of basic facts or information about a network device. These facts typically include device-specific details such as the hostname, model, serial number, vendor, and OS version.

from napalm import get_network_driver
import getpass
import json

passwd = getpass.getpass('Please enter the password: ')

driver = get_network_driver('ios')
switch_01 = {
    "hostname": '10.10.20.19', 
    "username": "cisco",
    "password": passwd,
    "optional_args": {"secret": passwd}
    }

switch_01_conn = driver(**switch_01)
switch_01_conn.open()
print(f"Connecting to {switch_01['hostname']}")

# Get facts
facts = switch_01_conn.get_facts() #get facts method

output_json = json.dumps(facts, indent=4)
print(output_json)
Please enter the password: 
Connecting to 10.10.20.19
{
    "uptime": 1260.0,
    "vendor": "Cisco",
    "os_version": "vios_l2 Software (vios_l2-ADVENTERPRISEK9-M)",
    "serial_number": "9JY0NJZA4N2",
    "model": "IOSv",
    "hostname": "switch-02",
    "fqdn": "switch-02.packet.lan",
    "interface_list": [
        "GigabitEthernet0/0",
        "GigabitEthernet0/1",
        "GigabitEthernet0/2",
        "GigabitEthernet0/3",
        "GigabitEthernet1/0",
        "GigabitEthernet1/1",
        "GigabitEthernet1/2",
        "GigabitEthernet1/3",
        "Vlan10"
    ]
}

The Benefits of Structured Data

You may be wondering why you should bother with all this Python stuff, when you can just log in to the switch and run a show command to look at the MAC address table, for example.

While it's true that you can obtain information from network devices by logging in and running show commands, the data you receive in this way is typically semi-structured, meaning it can be difficult to parse and analyze using automation tools. Structured data, on the other hand, is organized in a way that is easy to read and process using tools like Python, making it much easier to automate tasks like configuration management and network monitoring.

Imagine if you have 100s of switches and 1000s of Mac addresses, with structured data, you can export them to Excel or present them as a table. Using our first example, let's use the tabulate library to output the data as a table.

pip install tabulate
from napalm import get_network_driver
import getpass
import json
from tabulate import tabulate

passwd = getpass.getpass('Please enter the password: ')

driver = get_network_driver('ios')
switch_01 = {
    "hostname": '10.10.20.19', 
    "username": "cisco",
    "password": passwd,
    "optional_args": {"secret": passwd}
    }

switch_01_conn = driver(**switch_01)
switch_01_conn.open()
print(f"Connecting to {switch_01['hostname']}")
output = switch_01_conn.get_mac_address_table()
switch_01_conn.close()

table = []
for entry in output:
    table.append([entry['interface'], entry['mac'], entry['vlan']])

print(tabulate(table, headers=['Interface', 'Mac Address', 'VLAN'], tablefmt='orgtbl'))
| Interface   | Mac Address       |   VLAN |
|-------------+-------------------+--------|
| Gi0/0       | 00:E0:4C:68:00:90 |     10 |
| Gi0/0       | B4:2E:99:FC:83:76 |     10 |
| Gi0/0       | DC:A6:32:04:D2:56 |     10 |
| Gi1/1       | 00:50:79:66:68:06 |     20 |
| Gi1/2       | 00:50:79:66:68:08 |     20 |

Behind the Scenes

If you're curious about how NAPALM obtains structured output from network devices, you may be wondering if there's some kind of magic involved. The good news is that while there's no magic, the process is a bit more complex than just sending a command and getting back the output.

Under the hood, NAPALM uses a variety of techniques to obtain and process the output from network devices. This includes parsing the output of show commands, using regular expressions to extract specific pieces of information, and constructing dictionaries or other data structures to organize the retrieved data.

If you want to explore this further, you can check out the NAPALM GitHub page, which provides detailed documentation on the methods and functions provided by the library. For example, the get_facts() method uses a variety of techniques to extract specific pieces of information from the output of show commands, and constructs a dictionary containing this information as shown below. You can access the repo using this link - https://github.com/napalm-automation/napalm

Overall, while there's no magic involved in how NAPALM obtains structured output from network devices, the library's developers have put a lot of thought and effort into creating a set of methods and functions that can simplify the process of network automation.

Conclusion

In conclusion, NAPALM is a powerful Python library that simplifies network automation by providing a unified API to interact with different network device operating systems. Its support for multiple vendors and ability to handle various tasks make it an essential tool for network engineers looking to save time and effort in managing their networks.

In the upcoming posts, we will cover working with multiple devices and vendors.

Written by
Suresh Vina
Tech enthusiast sharing Networking, Cloud & Automation insights. Join me in a welcoming space to learn & grow with simplicity and practicality.
Comments
More from Packetswitch
Table of Contents
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to Packetswitch.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.