Use of a native PYTHON automation framework for multivendor environments.

Use of a native PYTHON automation framework for multivendor environments.

As a network engineer one of my tasks is to periodically collect and update information (such as serial numbers, license status, interfaces details, version of OS, etc) from every network device.

The task is fairly easy if there are few network devices in the environment, but as the number of network devices grow the task becomes cumbersome and error prone. I usually have to collect information from hundreds of devices and the task takes several days when doing it manually in each platform. I started to use network automation techniques for these sorts of things achieving these same tasks only in a few minutes.

Fortunately, nowadays there are several mature solutions that can help us to automate these tedious tasks. In this article I will present an open-source framework called Nornir. This framework is based in python, and has become so efficient that many vendors recognize the value of Nornir, and encourage their usage.

It should be noted that there is always a learning curve when trying new things. There is a learning curve even when learning to ride a bicycle and only after trying lots of times then riding a bicycle gets "easy". When learning it's also important to start with small tasks that are very simple to repeat, test and control. There are many good Nornir tutorials all over the internet but in my opinion the examples could be simpler, and my aim in this article is to make it simpler for you.

TIP 1:

There are 2 major versions of Python: Python 2.x and Python 3.x.? Python 2.x is deprecated. So, you should always use Python 3.x. As of June 2022, the latest stable version is Python 3.10.

TIP 2:

It's recommended to use a Linux OS to learn and use automation. Many Linux OS already have Python 3.x installed. I will use Ubuntu 18 in the following examples.

TIP 3:

"pip" command is the Python package manager. There is a very big Python ecosystem, and many Python modules are installed with "pip" command. In many Linux OS distributions (including Ubuntu 18) the "pip" command is already installed.

  1. NORNIR INSTALLATION

Basic Nornir installation only needs the following couple of “pip install” commands:?

auben@ubuntu18:~$ pip install nornir

auben@ubuntu18:~$ pip install nornir_utils

This basic installation ships with a default plugin called SimpleInventory where we can add all devices we need to manage. I will provide an example to use the inventory in just a minute, but first we need to install one extra plugin to connect to the devices. Nornir framework has several plugins like Netmiko and Napalm that can be used to connect to the devices. In this article I chose to use Netmiko due to its simplicity, so let's install it with the following “pip install” command:

auben@ubuntu18:~$ pip install nornir_netmiko

Let’s create a local directory called “nornir-tutorial” to store all the files used in the following examples.

auben@ubuntu18:~$ mkdir nornir-tutorial

auben@ubuntu18:~$ cd nornir-tutorial

auben@ubuntu18:~/nornir-tutorial$?

“nornir-tutorial” directory is empty. There are many ways to create a text file in Linux (using “vi” command, using “nano” command, copying from elsewhere using SCP, etc). As creating a text file is out of scope I will show you the text files already created as needed in the following examples.

TIP 4:

"YAML" is a well known and very popular text file format used in lots of IT tools. YAML files are very easy to read. Nornir uses “YAML” files to define the inventory.?

  1. EXAMPLES


Example 1: Simple inventory and sending a command to devices in inventory

I created "hosts.yaml" file in YAML format. This exact filename is needed to define the devices in Nornir inventory. This example has only 1 device called "linux01" which has several information fields. In particular the "hostname" field should carry an IP address or a resolvable name. The other fields (username, password, platform) are self-explanatory. Let's show the content of our inventory:

auben@ubuntu18:~/nornir-tutorial$ more hosts.yaml

---

linux01:

??hostname: 127.0.0.1

??username: auben

??password: auben123

??platform: linux

Now let’s review my Python script to use Nornir.

The InitNornir function initializes Nornir with default values and also initializes the inventory. The result of the InitNornir function is store in the “inv” variable.

The “inv.run” method runs a task called “netmiko_send_command” to send a command via SSH using netmiko. The command is "cat /etc/lsb-release". The result is stored in the “result” variable and printed to screen.

auben@ubuntu18:~/nornir-tutorial$ more example01.py

from nornir import InitNornir

from nornir_utils.plugins.functions import print_result

from nornir_netmiko import netmiko_send_command

inv = InitNornir()

result = inv.run(

????task=netmiko_send_command,

????command_string="cat /etc/lsb-release")

)

print_result(result)

Execute the script and see the results

auben@ubuntu18:~/nornir-tutorial$ python example01.py

netmiko_send_command************************************************************

* linux01 ** changed : False ***************************************************

vvvv netmiko_send_command ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO

DISTRIB_ID=Ubuntu

DISTRIB_RELEASE=18.04

DISTRIB_CODENAME=bionic

DISTRIB_DESCRIPTION="Ubuntu 18.04.5 LTS"

^^^^ END netmiko_send_command ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


Example 2: Using filters to send a command to only some devices in the inventory.?

In this example the inventory has 2 devices. The devices are called "router01" and "linux01".? "router01" has the “platform” field with value "juniper_junos" to indicate it is using Junos operating system.

auben@ubuntu18:~/nornir-tutorial$ more hosts.yaml

---

router01:

??hostname: 192.168.0.115

??username: auben

??password: aubenrouter

??platform: juniper_junos


linux01:

??hostname: 127.0.0.1

??username: auben

??password: aubenlinux

??platform: linux

The “filter” method is used to select only some devices from the inventory.

The “inv_linux” variable stores all linux devices as selected by inv.filter(platform="linux").

The “inv_junos” variable stores all junos devices as selected by inv.filter(platform="juniper_junos").

Then the “inv_linux.run” method is used to send the command “cat /etc/lsb-release” to all linux devices.

The “inv_junos.run” method is used to send the command “show system information” to all junos devices.

auben@ubuntu18:~/nornir-tutorial$ more example02.py

from nornir import InitNornir

from nornir_utils.plugins.functions import print_result

from nornir_netmiko import netmiko_send_command

inv = InitNornir()

inv_linux = inv.filter(platform="linux")

inv_junos = inv.filter(platform="juniper_junos")

result_linux = inv_linux.run( task=netmiko_send_command , command_string="cat /etc/lsb-release" )

result_junos = inv_junos.run( task=netmiko_send_command , command_string="show system information" )

print_result(result_linux)?

print_result(result_junos)?

Execute the script and see the results

auben@ubuntu18:~/nornir-tutorial$ python example02.py

netmiko_send_command************************************************************

* linux01 ** changed : False ***************************************************

vvvv netmiko_send_command ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO

DISTRIB_ID=Ubuntu

DISTRIB_RELEASE=18.04

DISTRIB_CODENAME=bionic

DISTRIB_DESCRIPTION="Ubuntu 18.04.5 LTS"

^^^^ END netmiko_send_command ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

netmiko_send_command************************************************************

* router01 ** changed : False **************************************************

vvvv netmiko_send_command ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO

Model: mx960

Family: junos

Junos: 19.4R3-S7.3

Hostname: router01

^^^^ END netmiko_send_command ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


Example 3: Using defaults for all inventory devices and pushing configuration to devices.

In the previous example all devices had the same username. To avoid repetition Nornir can use a “defaults.yaml” file to include information that applies to all devices. In this example the “username” field with value “auben” applies to all devices.

auben@ubuntu18:~/nornir-tutorial$ more defaults.yaml

---

username: auben

I deleted “username” field in all devices in “hosts.yaml”.

auben@ubuntu18:~/nornir-tutorial$ more hosts.yaml

---

router01:

??hostname: 192.168.0.115

??password: aubenrouter

??platform: juniper_junos


linux01:

??hostname: 127.0.0.1

??password: aubenlinux

??platform: linux

The “inv_junos” variable stores all junos devices selected by the “inv.filter” method.

The “my_config” variable is a list and every element in the list is a configuration command.

Then the “inv.junos.run” method runs a task called “netmiko_send_config” to push the configuration defined in the “my_config” variable. The result is stored in “result_junos” variable

auben@ubuntu18:~/nornir-tutorial$ more example03.py

from nornir import InitNornir

from nornir_utils.plugins.functions import print_result

from nornir_netmiko import netmiko_send_command , netmiko_send_config

inv = InitNornir()

inv_junos = inv.filter(platform="juniper_junos")

my_config = [

??"set system host-name EXAMPLE03" ,

??"set interfaces ge-0/0/0.0 family inet address 10.10.10.10/24" ,

??"commit"

]

result_junos = inv_junos.run( task=netmiko_send_config , config_commands= my_config )

print_result(result_junos)

Execute the script and see the results. Please notice the hostname has changed from router01 to EXAMPLE03.

auben@ubuntu18:~/nornir-tutorial$ python example03.py?

netmiko_send_config*************************************************************

* router01 ** changed : True ***************************************************

vvvv netmiko_send_config ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO

configure?

Entering configuration mode

The configuration has been changed but not committed


[edit]

auben@router01# set system host-name EXAMPLE03?


[edit]

auben@router01# set interfaces ge-0/0/0.0 family inet address 10.10.10.10/24?


[edit]

auben@MX# commit?

commit complete


[edit]

auben@EXAMPLE03# exit configuration-mode?

Exiting configuration mode


auben@EXAMPLE03>?

^^^^ END netmiko_send_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


CONCLUSION:

It is not needed to be a Python expert to use Nornir. Nornir scripts are easy to read and understand. By default it uses multithreading which makes Nornir a fast and highly scalable tool.

Nornir supports multivendor environments through the use of plugins like Netmiko and Napalm. All these features make Nornir a very powerful tool at your disposal.


HELPFUL LINKS:

Official Documentation

https://nornir.readthedocs.io/en/latest/

Great tutorial by Kirk Byers

https://pynet.twb-tech.com/blog/nornir-an-introduction.html

You can learn more about YAML here

https://en.wikipedia.org/wiki/YAML

Netmiko supported devices

https://ktbyers.github.io/netmiko/PLATFORMS.html?


Author: Eduardo Aliaga

Telecommunication engineer. Latin-American expert in networking technologies for Service Provider, Enterprise and Security markets. Committed to constant training regarding networking specifications, focusing mainly on high-scale networks design, support, deployment and consultancy.

要查看或添加评论,请登录

Auben Networks的更多文章

社区洞察

其他会员也浏览了