AutoNetOps

Cover Image for Easily Find Available Device Ports Using Nornir and Scrapli

Easily Find Available Device Ports Using Nornir and Scrapli

2 min read

This post is based on a real situation where we received a request to gather information about one of our customer sites and check for available ports on the switches.

There is a SQL database inventory used as a source of truth where we can gather the device IPs for access. We also know that the client uses only Cisco switches, which will make our work much easier.

Given that information, we are going to leverage Nornir and Scrapli to gather this information quickly and print the requested information on a file for customer reference.

Let's get started!!!

Build Nornir Inventory with SQL

To build the Nornir inventory, we are using the Nornir SQL inventory plugin (https://viktorkertesz.github.io/nornir_sql/)

So, we build the conf.yaml file in the following manner:

    ---

    inventory:
      plugin: SQLInventory
      options:
        sql_connection: 'mssql+pymssql://USERNAME:PASSWORD@SERVER/DATABASE'
        hosts_query: >
            SELECT DeviceIP as hostname, DeviceName as name, OS_Platform as platform
            FROM DATABASE
            WHERE SiteID like '%SITE-CODE%' and Category = 'switch'
        groups: 
          ios:
            platform: ios
            connection_options:
              netmiko:
                platform: cisco_ios
                extras: {}
              scrapli:
                platform: cisco_iosxe
                extras: 
                  auth_strict_key: False
              napalm:
                platform: ios
                extras:
                  optional_args: {}
        defaults:
          username: 'USERNAME'
          password: 'PASSWORD'

So with this, we are going to build our inventory, groups and defaults. Notice that on my query, I am not specifying to which group each device belongs, so we are going to fix this in the code based on some rules. Let's take a look:

    from nornir.core import Nornir

    nr = InitNornir(config_file="config.yaml")

    def assign_groups(nr: Nornir):
        groups = nr.inventory.groups
        for host in nr.inventory.hosts.values():
            # put whatever logic to assign groups
            if "IOS" in host.platform:
                host.groups.add(groups["ios"])

    assign_groups(nr)

After adding the group info, which we are using to define the connection options, let's get into the function to get the information we need.

Getting the information

We will use the 'show interfaces' command to find interfaces that are in a 'down' state. Additionally, we want to check the 'LastInput' and 'LastOutput' fields to see how long it has been since the port was last active.

To make this information easier to collect, we will use the TextFSM parser to build the data we want to return from this function.

    def get_free_ports(task):
        output = task.run(task=send_command, command="show interfaces", severity_level=logging.DEBUG)
        interfaces = output.scrapli_response.textfsm_parse_output()
        info = []
        for int in interfaces:
            if int['link_status'] == 'down':
                info.append(f"{int['interface']} - {int['link_status']} -> LastInput: {int['last_input']} - LastOutput: {int['last_output']}")

        return Result(host=task.host, result=info)

Presenting The Information