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)