The Nornir framework
Nornir (https://nornir.readthedocs.io/en/latest/) is a pure Python automation framework intended to be used directly from Python. We will discuss another automation framework written in Python, Ansible, in Chapter 4, The Python Automation Framework – Ansible Basics, and Chapter 5, The Python Automation Framework – Beyond Basics. I wanted to introduce the framework in this chapter as a way to demonstrate another way to automate devices with low-level interaction. However, if you are just starting out on the automation journey, the framework might make more sense after you have finished reading Chapter 5, The Python Automation Framework – Beyond Basics. Please feel free to scan through the example and come back to it later.
Of course, we will start with installing nornir
in our environment:
(venv) $ pip install nornir
Nornir expects us to define an inventory file, hosts.yaml
, consisting of the device information in a YAML format. The information specified in this file is no different than what we have previously defined using the Python dictionary in the Netmiko example:
---
iosv-1:
hostname: '172.16.1.20'
port: 22
username: 'cisco'
password: 'cisco'
platform: 'cisco_ios'
iosv-2:
hostname: '172.16.1.21'
port: 22
username: 'cisco'
password: 'cisco'
platform: 'cisco_ios'
We can use the netmiko
plugin from the nornir
library to interact with our device, as illustrated in the chapter2_5.py
file:
from nornir import InitNornir
from nornir.plugins.tasks.networking import netmiko_send_command
from nornir.plugins.functions.text import print_result
nr = InitNornir()
result = nr.run(
task=netmiko_send_command,
command_string="show arp"
)
print_result(result)
The execution output is shown as follows:
(venv) $ python chapter2_5.py
netmiko_send_command************************************************************
* iosv-1 ** changed : False ****************************************************
vvvv netmiko_send_command ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
Protocol Address Age (min) Hardware Addr Type Interface
Internet 10.0.0.5 - fa16.3e0e.a3a3 ARPA GigabitEthernet0/1
Internet 10.0.0.6 40 fa16.3ed7.1041 ARPA GigabitEthernet0/1
^^^^ END netmiko_send_command ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* iosv-2 ** changed : False ****************************************************
vvvv netmiko_send_command ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
Protocol Address Age (min) Hardware Addr Type Interface
Internet 10.0.0.5 40 fa16.3e0e.a3a3 ARPA GigabitEthernet0/1
Internet 10.0.0.6 - fa16.3ed7.1041 ARPA GigabitEthernet0/1
^^^^ END netmiko_send_command ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
There are other plugins in Nornir besides Netmiko, such as the popular NAPALM library (https://github.com/napalm-automation/napalm). Please feel free to check out Nornir's project page for the latest plugins: https://nornir.readthedocs.io/en/latest/plugins/index.html.
We'll discuss another automation framework, pyATS and Genie, in Chapter 15, Test-Driven Development for Networks, when we discuss testing and verification.
We have taken a pretty huge leap forward in this chapter in automating our network using Python. However, some of the methods we have used feel like workarounds for automation. We attempted to trick the remote devices into thinking they were interacting with a human on the other end. Even if we use libraries such as Netmiko or the Nornir framework, the underlying approach remains the same. Just because somebody else has done the work to help abstract the grunt work of the low-level interaction, we are still susceptible to the downsides of dealing with CLI-only devices.
Looking ahead, let us discuss some of the downsides of Pexpect and Paramiko compared to other tools in preparation for our discussion on API-driven methods in the next chapters.
Downsides of Pexpect and Paramiko compared to other tools
The biggest downside of our method for automating CLI-only devices so far is that the remote devices do not return structured data. They return data that is ideal for fitting on a terminal to be interpreted by a human, not by a computer program. The human eye can easily interpret a space, while a computer only sees a return character.
We will take a look at a better way in the upcoming chapter. As a prelude to Chapter 3, APIs and Intent-Driven Networking, let's discuss the idea of idempotency.
Idempotent network device interaction
The term idempotency has different meanings, depending on its context. But in this book's context, the term means that when a client makes the same call to a remote device, the result should always be the same. I believe we can all agree that this is necessary. Imagine a scenario where each time you execute the same script, you get a different result back. I find that scenario very scary. How can you trust your script if that is the case? It would render our automation effort useless because we need to be prepared to handle different returns.
Since Pexpect and Paramiko are blasting out a series of commands interactively, the chance of having a non-idempotent interaction is higher. Going back to the fact that the return results needed to be screen scraped for useful elements, the risk of difference is much higher. Something on the remote end might have changed between the time we wrote the script and the time when the script is executed for the 100th time. For example, if the vendor makes a screen output change between releases without us updating the script, the script might break.
If we need to rely on the script for production, we need the script to be idempotent as much as possible.
Bad automation speeds bad things up
Bad automation allows you to poke yourself in the eye a lot faster, it is as simple as that. Computers are much faster at executing tasks than us human engineers. If we had the same set of operating procedures executed by a human versus a script, the script would finish faster than humans, sometimes without the benefit of having a solid feedback loop between procedures. The internet is full of horror stories of when someone pressed the Enter key and immediately regretted it.
We need to make sure the chances of bad automation scripts screwing things up are as small as possible. We all make mistakes; carefully testing your script before any production work and having a small blast radius are two keys to making sure you can catch your mistake before it comes back and bites you. No tool or human can eliminate mistakes completely, but we can strive to minimize the mistakes. As we have seen, as great as some of the libraries we have used in this chapter are, the underlying CLI-based method is inherently faulty and error-prone. We will introduce the API-driven method in the next chapter, which addresses some of the CLI-driven management deficiencies.