Lab 06 - Exploring NAPALM and Netmiko Task Modules for Configuration Changes¶
This lab is going to show how to make configuration changes using NAPALM and Netmiko modules like napalm_configure and netmiko_send_config. The examples will show how to make changes by sending a single command, list of commands, and commands stored in a file.
Task 1 - Make Configuration Changes with NAPALM¶
This task is going to focus on how to make configuration changes using napalm_configure.
Step 1¶
In the /home/ntc/nornir, edit the nr_napalm.py file to import one additional function, namely napalm_configure from the nornir_napalm.plugins.tasks module.
The file should look like this (notice the addition to the second line):
from nornir import InitNornir
from nornir_napalm.plugins.tasks import napalm_get, napalm_cli, napalm_configure
from nornir_utils.plugins.functions import print_result, print_title
from nornir.core.filter import F
from rich import print
nr = InitNornir(config_file="nornir_configuration/napalm_configuration.yml")
Step 2¶
First, execute the nr_napalm.py file in a new interactive Python shell (notice the -i parameter). Then, create the iosxe variable to filter out the group.
ntc@ntc-training:nornir$ python -i nr_napalm.py
>>>
>>> iosxe = nr.filter(F(groups__contains="iosxe"))
>>>
Step 2¶
Create a variable called napalm_snmp_config to run a task on the iosxe group using the napalm_config module. As arguments for the module, use dry_run, which allows the task to run without applying any changes to the devices and configuration argument for providing a single string command to send.
>>>
>>> napalm_snmp_config = iosxe.run(task=napalm_configure, dry_run=True, configuration="snmp-server community ntc RO")
>>>
Step 3¶
Print the out the result using the print_result function. Notice the output showing there is change and also the diffs on what is going to get added to the configuration.
>>>
>>> print_result(napalm_snmp_config)
napalm_configure****************************************************************
* csr1 ** changed : True *******************************************************
vvvv napalm_configure ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
+snmp-server community ntc RO
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr2 ** changed : True *******************************************************
vvvv napalm_configure ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
+snmp-server community ntc RO
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr3 ** changed : True *******************************************************
vvvv napalm_configure ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
+snmp-server community ntc RO
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>>
Step 4¶
Run the same task again except this time modify the arguments and remove the dry_run argument from the task.
>>>
>>> napalm_snmp_config = iosxe.run(task=napalm_configure, configuration="snmp-server community ntc RO")
>>>
Step 5¶
Use the print_result function to view the result from the task. The output should look the same as in step 3, except this time it's going to apply the changes to the running config.
>>>
>>> print_result(napalm_snmp_config)
napalm_configure****************************************************************
* csr1 ** changed : True *******************************************************
vvvv napalm_configure ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
+snmp-server community ntc RO
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr2 ** changed : True *******************************************************
vvvv napalm_configure ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
+snmp-server community ntc RO
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr3 ** changed : True *******************************************************
vvvv napalm_configure ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
+snmp-server community ntc RO
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>>
Step 6¶
Run the same task again without changing anything.
>>>
>>> napalm_snmp_config = iosxe.run(task=napalm_configure, configuration="snmp-server community ntc RO")
>>>
Step 7¶
Print out the results and notice the difference in the output on how there is no longer a change. This behavior indicates that the module is idempotent, meaning that it will only make changes if the configuration is not present in the device. This same task and commands can be run 1000 times, and the result will still be the same.
>>>
>>>
>>> print_result(napalm_snmp_config)
napalm_configure****************************************************************
* csr1 ** changed : False ******************************************************
vvvv napalm_configure ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr2 ** changed : False ******************************************************
vvvv napalm_configure ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr3 ** changed : False ******************************************************
vvvv napalm_configure ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>>
Step 8¶
Create a list of SNMP community configuration commands.
>>>
>>> list_commands = ["snmp-server community ntc_idempotent RO", "snmp-server community ntc_list RO", "snmp-server community ntc RO"]
>>>
Step 9¶
Use a for loop to iterate through the list of commands. Create a task to send each item inside the list. Print the result, and the output should have changed to the new configurations applied to the device, but for the ones that already existed should return False for change.
>>>
>>> for command in list_commands:
... snmp_config = iosxe.run(task=napalm_configure, configuration=command)
... print_result(snmp_config)
...
napalm_configure****************************************************************
* csr1 ** changed : True *******************************************************
vvvv napalm_configure ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
+snmp-server community ntc_idempotent RO
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr2 ** changed : True *******************************************************
vvvv napalm_configure ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
+snmp-server community ntc_idempotent RO
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr3 ** changed : True *******************************************************
vvvv napalm_configure ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
+snmp-server community ntc_idempotent RO
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
napalm_configure****************************************************************
* csr1 ** changed : True *******************************************************
vvvv napalm_configure ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
+snmp-server community ntc_list RO
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr2 ** changed : True *******************************************************
vvvv napalm_configure ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
+snmp-server community ntc_list RO
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr3 ** changed : True *******************************************************
vvvv napalm_configure ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
+snmp-server community ntc_list RO
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
napalm_configure****************************************************************
* csr1 ** changed : False ******************************************************
vvvv napalm_configure ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr2 ** changed : False ******************************************************
vvvv napalm_configure ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr3 ** changed : False ******************************************************
vvvv napalm_configure ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>>
Step 10¶
In a separate terminal, create a new directory called device_configuration (under /home/ntc/nornir) and a new file called snmp_config.cfg, inside the new directory.
ntc@ntc-training:nornir$ pwd
/home/ntc/nornir
ntc@ntc-training:nornir$ mkdir device_configuration
ntc@ntc-training:nornir$ touch device_configuration/snmp_config.cfg
ntc@ntc-training:nornir$
Step 11¶
Save the following configuration commands inside the snmp_config.cfg file.
Step 12¶
Back in your Python interpreter, create a new variable called snmp_file_config and as a value run the same napalm_configure task. This time, change the configuration argument with filename and provide the path to the new file snmp_config.cfg created on the previous step.
>>>
>>> snmp_file_config = iosxe.run(task=napalm_configure, filename="device_configuration/snmp_config.cfg")
>>>
Step 13¶
Print out the result and view the changes to the configuration.
>>>
>>> print_result(snmp_file_config)
napalm_configure****************************************************************
* csr1 ** changed : True *******************************************************
vvvv napalm_configure ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
+snmp-server community public RO
+snmp-server community private RW
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr2 ** changed : True *******************************************************
vvvv napalm_configure ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
+snmp-server community public RO
+snmp-server community private RW
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr3 ** changed : True *******************************************************
vvvv napalm_configure ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
+snmp-server community public RO
+snmp-server community private RW
^^^^ END napalm_configure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>>
Task 2 - Make Configuration Changes with Netmiko¶
This task is going to focus on using the netmiko_send_config module to make configuration changes to the networking devices.
Step 1¶
In the /home/ntc/nornir, edit the nr_netmiko.py file to import one additional function, namely netmiko_send_config from the nornir_netmiko.tasks module.
The file should look like this (notice the addition to the second line):
from nornir import InitNornir
from nornir_netmiko.tasks import netmiko_send_command, netmiko_send_config
from nornir_utils.plugins.functions import print_result, print_title
from nornir.core.filter import F
from rich import print
nr = InitNornir(config_file="nornir_configuration/netmiko_configuration.yml")
Step 2¶
First, execute the nr_netmiko.py file in a new interactive Python shell (notice the -i parameter). Then, create the iosxe variable to filter out the group and run a command against it using Netmiko.
ntc@ntc-training:nornir$ python -i nr_netmiko.py
>>>
>>> iosxe = nr.filter(F(groups__contains="iosxe"))
>>>
>>> netmiko_snmp_config = iosxe.run(netmiko_send_config, config_commands="snmp-server community netmiko_module RO")
>>>
Step 3¶
Use the print_result function to view the output of the task. Notice the output difference from NAPALM how it shows entering the config term command first, then enters the line of command and exists the config terminal by using the command end.
>>>
>>> print_result(netmiko_snmp_config)
netmiko_send_config*************************************************************
* csr1 ** changed : True *******************************************************
vvvv netmiko_send_config ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
csr1(config)#snmp-server community netmiko_module RO
csr1(config)#end
csr1#
^^^^ END netmiko_send_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr2 ** changed : True *******************************************************
vvvv netmiko_send_config ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
csr2(config)#snmp-server community netmiko_module RO
csr2(config)#end
csr2#
^^^^ END netmiko_send_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr3 ** changed : True *******************************************************
vvvv netmiko_send_config ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
csr3#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
csr3(config)#snmp-server community netmiko_module RO
csr3(config)#end
csr3#
^^^^ END netmiko_send_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>>
Step 4¶
Run the netmiko_snmp_config task again.
>>>
>>> netmiko_snmp_config = iosxe.run(netmiko_send_config, config_commands="snmp-server community netmiko_module RO")
>>>
Step 5¶
Print the result again and notice how the same command was entered, and the result came back as changed. The output shows this module is not idempotent, and it will always try to make a change when sending commands to the device.
>>>
>>> print_result(netmiko_snmp_config)
netmiko_send_config*************************************************************
* csr1 ** changed : True *******************************************************
vvvv netmiko_send_config ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
csr1(config)#snmp-server community netmiko_module RO
csr1(config)#end
csr1#
^^^^ END netmiko_send_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr2 ** changed : True *******************************************************
vvvv netmiko_send_config ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
csr2(config)#snmp-server community netmiko_module RO
csr2(config)#end
csr2#
^^^^ END netmiko_send_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr3 ** changed : True *******************************************************
vvvv netmiko_send_config ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
csr3(config)#snmp-server community netmiko_module RO
csr3(config)#end
csr3#
^^^^ END netmiko_send_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>>
Step 6¶
Create a list of commands and add two elements to the list for the SNMP community configuration.
>>>
>>> list_commands = ["snmp-server community netmiko_module RO", "snmp-server community netmiko_list RO"]
>>>
Step 7¶
Create a new variable called netmiko_snmp_config_list, run a task using the netmiko_send_config module again and in the config_commands use the list_commands variable.
Notice the difference between the napalm_configure, module which required to use a for loop to iterate through the list while the netmiko_send_config can take as input a list.
>>>
>>> netmiko_snmp_config_list = iosxe.run(netmiko_send_config, config_commands=list_commands)
>>>
Step 8¶
Print the result to view the commands sent to the devices.
>>>
>>> print_result(netmiko_snmp_config_list)
netmiko_send_config*************************************************************
* csr1 ** changed : True *******************************************************
vvvv netmiko_send_config ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
csr1(config)#snmp-server community netmiko_module RO
csr1(config)#snmp-server community netmiko_list RO
csr1(config)#end
csr1#
^^^^ END netmiko_send_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr2 ** changed : True *******************************************************
vvvv netmiko_send_config ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
csr2(config)#snmp-server community netmiko_module RO
csr2(config)#snmp-server community netmiko_list RO
csr2(config)#end
csr2#
^^^^ END netmiko_send_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr3 ** changed : True *******************************************************
vvvv netmiko_send_config ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
csr3(config)#snmp-server community netmiko_module RO
csr3(config)#snmp-server community netmiko_list RO
csr3(config)#end
csr3#
^^^^ END netmiko_send_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>>
Step 9¶
To test out sending a config file with commands to the device, create a new variable called netmiko_snmp_config_file. Use the iosxe object to run the netmiko_send_config task and as argument use the config_file and provide a path to the snmp_config.cfg file containing the configuration commands.
>>>
>>> netmiko_snmp_config_file = iosxe.run(netmiko_send_config, config_file="device_configuration/snmp_config.cfg")
>>>
Step 10¶
Use the print_result function to view the output of the task.
>>>
>>> print_result(netmiko_snmp_config_file)
netmiko_send_config*************************************************************
* csr1 ** changed : True *******************************************************
vvvv netmiko_send_config ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
csr1(config)#snmp-server community public RO
csr1(config)#snmp-server community private RW
csr1(config)#end
csr1#
^^^^ END netmiko_send_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr2 ** changed : True *******************************************************
vvvv netmiko_send_config ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
csr2(config)#snmp-server community public RO
csr2(config)#snmp-server community private RW
csr2(config)#end
csr2#
^^^^ END netmiko_send_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr3 ** changed : True *******************************************************
vvvv netmiko_send_config ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
csr3(config)#snmp-server community public RO
csr3(config)#snmp-server community private RW
csr3(config)#end
csr3#
^^^^ END netmiko_send_config ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>>
Step 11¶
Create a new variable called show_snmp run the netmiko_send_command as a task and use the command_string argument to send the show run | include snmp command to the device.
>>>
>>> show_snmp = iosxe.run(task=netmiko_send_command, command_string="show run | include snmp")
>>>
Step 12¶
Use the print_result function to view the results of all the new SNMP configurations on the device.
>>>
>>> print_result(show_snmp)
netmiko_send_command************************************************************
* csr1 ** changed : False ******************************************************
vvvv netmiko_send_command ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
snmp-server community ntc-public RO
snmp-server community ntc-private RW
snmp-server community ntc RO
snmp-server community ntc_idempotent RO
snmp-server community ntc_list RO
snmp-server community public RO
snmp-server community private RW
snmp-server community netmiko_module RO
snmp-server community netmiko_list RO
^^^^ END netmiko_send_command ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr2 ** changed : False ******************************************************
vvvv netmiko_send_command ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
snmp-server community ntc-public RO
snmp-server community ntc-private RW
snmp-server community ntc RO
snmp-server community ntc_idempotent RO
snmp-server community ntc_list RO
snmp-server community public RO
snmp-server community private RW
snmp-server community netmiko_module RO
snmp-server community netmiko_list RO
^^^^ END netmiko_send_command ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* csr3 ** changed : False ******************************************************
vvvv netmiko_send_command ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
snmp-server community ntc-public RO
snmp-server community ntc-private RW
snmp-server community ntc RO
snmp-server community ntc_idempotent RO
snmp-server community ntc_list RO
snmp-server community public RO
snmp-server community private RW
snmp-server community netmiko_module RO
snmp-server community netmiko_list RO
^^^^ END netmiko_send_command ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>>