[python]Understanding how to capture the result you need with Nornir

Introduction

The documentation has illustrated how to display the output to the console screen, however it did not explicitly show how to capture the data you need. It does document about what is AggregatedResult object and Result object, but still using examples will be easier to understand and also to encourage more people to use Nonir.

Function to send show command

Refer to previous post about an example of nornir, there is a function that sends command with netmiko and also another function to process the response to get the output of show ip interface brief, but this function is actually not needed, I can just use the send command function to process the response.

See the code below:

from pyvault2.vault.hvault2 import get_kv2_secret
from nornir.plugins.tasks.networking import netmiko_send_command
from nornir import InitNornir

def show_command_to_all_hosts(cmd=None):
    with InitNornir(
            inventory={
                "plugin": "nornir.plugins.inventory.simple.SimpleInventory",
                "options":
                    {
                        "host_file": host_file
                    }
            }
    ) as nr:
        for host in nr.inventory.hosts.keys():
            """
            Collect host information from hashicorp vault.
            """
            vault_data = get_kv2_secret(mount_path="cisco_ios",
                                        path=host,
                                        find="data")
            """
            Modify the username and password of each key in yaml file.
            """
            nr.inventory.hosts[host].username = vault_data["username"]
            nr.inventory.hosts[host].password = vault_data["password"]

        # routers is the AggregatedResult object of all hosts in inventory
        routers = nr.run(task=netmiko_send_command,
                         command_string=cmd,
                         use_textfsm=True)
    return routers

This function returns the output from the command I put in.

Explaining the result of nornir object

Reference:
https://nornir.readthedocs.io/en/latest/ref/api/task.html#aggregatedresult

I am using the function above to illustrate how to parse the result, the cisco ios command I am using is show cdp neighbor, which has a made textfsm template.

response = show_command_to_all_hosts(cmd="show cdp neighbor")
print(response)

The result is this:

AggregatedResult (netmiko_send_command): {'mgmt': MultiResult: [Result: "netmiko_send_command"], 'R2': MultiResult: [Result: "netmiko_send_command"], 'R3': MultiResult: [Result: "netmiko_send_command"], 'R4': MultiResult: [Result: "netmiko_send_command"], 'R5': MultiResult: [Result: "netmiko_send_command"]}

From the documentation, AggregatedResult is a dictionary like object, hence if you need to filter the result of “mgmt”, use response["mgmt"] the result will be:

MultiResult: [Result: "netmiko_send_command"]

From the documentation MultiResult is a list like object, and from the above result there is only one index which is [Result: "netmiko_send_command"], so let’s check the output of index 0 response["mgmt"][0] gives you this result: Result: "netmiko_send_command" but this is not the output of show cdp neigh, in order to access the actual output use the result method like this response["mgmt"][0].result, the result will be this:

[{'capability': 'R B',
  'local_interface': 'Eth 0/0',
  'neighbor': 'R4.cyruslab.local',
  'neighbor_interface': 'Eth 0/3',
  'platform': 'Linux Uni'},
 {'capability': 'R B',
  'local_interface': 'Eth 0/0',
  'neighbor': 'R5.cyruslab.local',
  'neighbor_interface': 'Eth 0/1',
  'platform': 'Linux Uni'},
 {'capability': 'R B',
  'local_interface': 'Eth 0/0',
  'neighbor': 'R2.cyruslab.local',
  'neighbor_interface': 'Eth 0/1',
  'platform': 'Linux Uni'},
 {'capability': 'R B',
  'local_interface': 'Eth 0/0',
  'neighbor': 'R3.cyruslab.local',
  'neighbor_interface': 'Eth 0/2',
  'platform': 'Linux Uni'}]

What if you need to know the failure status? To know if the command is executed by nornir/netmiko successfully use this response["mgmt"][0].failed which will give you a boolean result either True or False. To know if the device has changed configuration, change the method from failed to changed which will also give a boolean object either True or False.

The result, changed, failed methods are belonging to MultiResult object which is a list-like object, hence when I referred to response["mgmt"][0] I am referring to MultiResult.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s