Recently I found myself in a situation where I had to find every Switch in a deployment that was hitting a specific bug.
This bug ultimately meant that certain commands on the Switch could not be run and would return a specific word-for-word error instead. The solution to this bug was the age old, highly technical act of rebooting said Switch.
Sounds simple enough, just SSH onto a Switch and check if it is affected, right?
Right.
But how do you go about finding how many Switches are suffering from this bug when you have a deployment of hundreds of Switches?
Thankfully, with a Python script utilising Netmiko, we can scan our deployment and return a list of affected Switches while sitting back and enjoying the time returned to our dominion by the power of automation.
The Script
Below is the script in its entirety.
For those familiar with Python and Netmiko, you’ll be able to figure out how it does what it does, but for those whom a reminder would benefit (including myself), lets walk through it.
from netmiko import ConnectHandler
print('-'*28)
print('Switches Requiring a Reboot:')
print('-'*28)
with open('devices.txt') as switches:
for IP in switches:
Switch = {
'device_type': 'cisco_ios',
'ip': IP,
'username': 'username',
'password': 'password'
}
net_connect = ConnectHandler(**Switch)
output = net_connect.send_command('[COMMAND]')
if '[]' in output:
print(IP)
net_connect.disconnect()
Script Breakdown
from netmiko import ConnectHandler
The line above simply imports a Function from the Netmiko library so that we can use it as part of our script. This particular Function is what we will use to send a command to the Switch. It will come in handy later on.
print('-'*28)
print('Switches Requiring a Reboot:')
print('-'*28)
The above code just makes the output of the script look nice, so that when we have our results, they will be formatted as such:
----------------------------
Switches Requiring a Reboot:
----------------------------
Moving on to the next section:
with open('devices.txt') as switches:
for IP in switches:
Switch = {
'device_type': 'cisco_ios',
'ip': IP,
'username': 'username',
'password': 'password'
}
net_connect = ConnectHandler(**Switch)
output = net_connect.send_command('[COMMAND]')
The above code block references a separate text file that I have made and stored in the same directory called ‘devices.txt’. It contains a line by line list of all the IP Addresses of Switches that I want to connect to and enter a command on.
Here I am telling the script that for every IP given inside that file, connect via SSH to it using the parameters in ‘Switch = …’ and send the command that I wish (signified here as an example by ‘[COMMAND]’.
Moving on, we can see the following code:
if '[]' in output:
print(IP)
The last section says that if the script sees a certain string in the Switch CLI output, it will display the IP Address of the offending Switch. Just to illustrate the point, in the above code I would be searching for ‘[]’.
net_connect.disconnect()
The final line of code above tells the script to disconnect the SSH session to the Switch.
Script Output
The below is an example of what the script will look like when it finds the output we are looking for.
----------------------------
Switches Requiring a Reboot:
----------------------------
XXX.XXX.XXX.XXX
XXX.XXX.XXX.XXX
XXX.XXX.XXX.XXX
XXX.XXX.XXX.XXX
XXX.XXX.XXX.XXX
XXX.XXX.XXX.XXX
XXX.XXX.XXX.XXX
XXX.XXX.XXX.XXX
XXX.XXX.XXX.XXX
XXX.XXX.XXX.XXX
Final Thoughts
While my use case might be relatively obscure, it helped me identify which Switches were affected by the bug in question. I’d imagine similar use cases for this script where a certain output is checked on a deployment of Switches.
Its important to note that I didn’t natively write this script by myself, I compiled it from various sources, slimmed it down and added my own requirements. I’d like to reference this website as giving me a solid start.
Lastly, for large deployments, this script may take a while to run. This is because the Switches are connected to one by one. There are options to connect to multiple Switches in parallel, but it isn’t something I myself have tried yet. The best thing about openly sharing code is allowing others the ability to add onto it and improve it as necessary, so I hope this helps!