A Beginner's Guide to NAPALM Network Automation
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.
from napalm import get_network_driver
- This line imports theget_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.import getpass
- This line imports thegetpass
module from the Python standard library, which provides a way to securely read user input from the command line.import json
- This line imports thejson
module from the Python standard library, which is used to convert Python objects into JSON format and vice versa.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 thepasswd
variable.driver = get_network_driver('ios')
- This line creates a network driver object for Cisco IOS devices using theget_network_driver
function from NAPALM.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, thesecret
argument (enable password) is set to the same value as the password).switch_01_conn = driver(**switch_01)
- This line uses the network driver object to create a connection to the network device specified in theswitch_01
dictionary.switch_01_conn.open()
- This line opens the connection to the network device.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.output = switch_01_conn.get_mac_address_table()
- This line retrieves the MAC address table from the network device using theget_mac_address_table
method of the network driver object.switch_01_conn.close()
- This line closes the connection to the network device.output_json = json.dumps(output, indent=4)
- This line converts theoutput
variable (which contains the MAC address table data) to JSON format and stores the result in theoutput_json
variable.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.