Welcome back to Part 2 of our Nornir course. In this part, we will explore the Netmiko plugin. The Netmiko plugin is used within the Nornir framework to simplify interactions with network devices. Netmiko is a Python library that facilitates SSH connections to network devices. This plugin leverages Netmiko's functionalities to execute commands over SSH, making it easier to manage and configure devices without creating our own functions or plugins.
You can install the plugin with a simple pip command as shown below.
pip3 install nornir_netmiko
Nornir Netmiko Simple Exmaple
So far, we've seen that Nornir is a framework that provides inventory management, and Netmiko offers a way to SSH and interact with network devices. Now, if we combine them, what do we get? Well, we have a neat way to SSH into multiple devices at once and perform tasks efficiently and concurrently.
Let's look at a simple example where we have two Cisco devices and we want to run a show
command and print the output.
from nornir import InitNornir
from nornir_netmiko.tasks import netmiko_send_command
from nornir_utils.plugins.functions import print_result
nr = InitNornir(config_file='config.yaml')
results = nr.run(task=netmiko_send_command, command_string='show ip interface brief | excl down')
print_result(results)
Here’s a breakdown of the code and how each component functions.
- Import Statements
from nornir import InitNornir
- Imports theInitNornir
function, which initializes a Nornir instance using a configuration file.from nornir_netmiko.tasks import netmiko_send_command
- Imports thenetmiko_send_command
task from thenornir_netmiko
plugin.from nornir_utils.plugins.functions import print_result
- Imports theprint_result
function, which is used to print the results of tasks executed by Nornir.
- Initializing Nornir
nr = InitNornir(config_file='config.yaml')
- Initializes a Nornir object (nr
) using settings from a configuration file namedconfig.yaml
.
- Running a Task with Netmiko
results = nr.run(task=netmiko_send_command, command_string='show ip interface brief | excl down')
- This line runs a task across all devices in the inventory. Thenetmiko_send_command
task (which is part of the nornir_netmiko plugin) is used to send a specific command to each device. In this case, the command isshow ip interface brief | excl down
- Printing Results
print_result(results)
- This function call prints the results of the executed task. Theprint_result
plugin formats the output to be more readable and structured, showing which devices returned what results in an organized manner.
Sending multiple show commands
If we want to send multiple commands? All we have to do is, simply add another line that specifies the new command and execute the run
method again. Below is the updated code snippet where I added a command to show the ARP table of the devices.
from nornir import InitNornir
from nornir_netmiko.tasks import netmiko_send_command
from nornir_utils.plugins.functions import print_result
nr = InitNornir(config_file='config.yaml')
results_ip_brief = nr.run(task=netmiko_send_command, command_string='show ip interface brief | excl down')
results_ip_arp = nr.run(task=netmiko_send_command, command_string='show ip arp')
print_result(results_ip_brief)
print_result(results_ip_arp)
A Slightly Modified Script (Sub-Tasks)
This is my preferred way of running multiple tasks under a parent task. For me at least, this looks much better than having separate tasks and printing the results separately.
from nornir import InitNornir
from nornir_netmiko.tasks import netmiko_send_command
from nornir_utils.plugins.functions import print_result
def get_output(task):
task.run(task=netmiko_send_command, command_string='show ip interface brief | excl down')
task.run(task=netmiko_send_command, command_string='show ip arp')
nr = InitNornir(config_file='config.yaml')
results = nr.run(task=get_output)
print_result(results)
In this example, you would have seen two different ways to run tasks, task.run
and nr.run
. Here’s a brief explanation of the difference between the two.
task.run
- This is used within a task function to execute another task. Think of it as calling a sub-task within your main task. When you usetask.run
, you're essentially saying, "While performing this task, go ahead and run these additional tasks as part of it."nr.run
- On the other hand,nr.run
is used to kick off tasks at the top level. This is the method you call when you want to start your automation process and execute tasks across your inventory of devices.
In summary, nr.run
is used to initiate your automation tasks on your network devices, while task.run
allows you to organize and modularize your tasks by calling other tasks within a task.
I hope you can already spot the differences and benefits of using Nornir here. I'm not using any for loops, and I haven't used any lists or dictionaries to manage the devices; everything is handled by Nornir.
write_file plugin
Now, suppose we want to back up the configs by running show run
on all the devices and save it to a file. Let's look at how to use the write_file
plugin to do just that. Please note that the write_file
plugin is part of nornir_utils
collection and you can install it by running a simple pip command.
pip3 install nornir_utils
In the following script, we use Nornir to automate network configuration backups using a function named backup_config
. Here are the key components explained.
from nornir import InitNornir
from nornir_netmiko.tasks import netmiko_send_command
from nornir_utils.plugins.tasks.files import write_file
def backup_config(task):
output = task.run(task=netmiko_send_command, command_string='show run')
task.run(task=write_file, filename=f'{task.host}-backup.cfg', content=output[0].result)
nr = InitNornir(config_file='config.yaml')
results = nr.run(task=backup_config)
- task.host - This is used within the script to dynamically retrieve the name of the current device (host) that Nornir is working with. It allows us to customize actions like file naming based on each host's unique name. For instance, in the script,
task.host
is used to name the backup file uniquely for each device, ensuring that the configurations are saved in separate files named after each host. - result - In this context,
result
refers to the outcome of the tasks that are run. Each task execution, such asnetmiko_send_command
, returns a result object. This object contains data about the execution, including the output of the command run on the network device. We will explore Nornir results in more detail later but remember thatresult[0].result
contains the actual output from the device. (We will cover the result object in detail in the upcoming sections)
The script is structured to initiate Nornir, run the backup_config
task across configured hosts, get the output and save it to the file.
Netmiko Configuration Commands
In this final example, we look at how to send configuration commands to network devices using the Netmiko library through Nornir. The function we focus on here is netmiko_send_config
, which is designed for sending configuration commands rather than just executing show commands.
from nornir import InitNornir
from nornir_netmiko.tasks import netmiko_send_config
from nornir_utils.plugins.functions import print_result
def ntp_config(task):
task.run(task=netmiko_send_config, config_commands=['ntp server 10.10.10.10'])
nr = InitNornir(config_file='config.yaml')
results = nr.run(task=ntp_config)
print_result(results)
netmiko_send_config - This function from the nornir_netmiko
plugin allows you to send configuration commands to network devices. It differs from netmiko_send_command
, which is used for sending show commands.
Closing up
In the next part, we will dive deep into the Nornir Inventory and execute tasks in subsequent devices (Inventory Filtering)