Current State Device Config Audit

Welcome to my first post which happens to be on network automation. I’ve got a large number of network hardware replacements coming up so I’ve created a (fairly basic) script that uses Netmiko to do the following:

  • Import a list of IP addresses from an external file (routers.txt)
  • SSH to each IP address (with error handling)
  • Run a list of commands specified from an external file (commands.txt)
  • Output the result of the commands in an individual text file named with each devices hostname and IP address
  • Output the IP addresses of devices it was unable to connect to into a file which is named based on the error. Examples are:
    • Connection Timeouts.txt
    • Auth Failures.txt
    • SSH Failures.txt
    • EOF Errors.txt
    • UnknownError.txt

At the moment the script is only working for Cisco equipment as that’s the current use-case I have for it, however, it should be pretty easy to call the Aruba or other vendor Netmiko library instead.

I’ve attached the initial release of the code below, however, the most current version will always be located on my GitHub.

#!/usr/bin/env python
# Script by Mitch Bradford
# Dependencies - Netmiko, Python 3
# Instructions - List IP addresses in routers.txt and commands to run in commands.txt
# === Formatting ===
# routers.txt:
# [ip address]
# [ip address]
#
# commands.txt:
# exit
# [enable priv command]
# [enable priv command]

from netmiko import ConnectHandler
from netmiko.ssh_exception import  NetMikoTimeoutException
from paramiko.ssh_exception import SSHException 
from netmiko.ssh_exception import  AuthenticationException
from getpass import getpass
from pprint import pprint

with open('commands.txt') as f:
	commands_list = f.read().splitlines()

with open('routers.txt') as f:
	router_list = f.read().splitlines()

username=input('Enter your username:')
password=getpass()

for routers in router_list:
	print ('Connecting to device ' + routers)
	ip_address_of_device = routers
	ios_device = {
	'device_type': 'cisco_ios',
	'ip': ip_address_of_device,
	'username': username,
	'password': password
	}

	#Define the error handling files to reference if/when something fails
	Timeouts=open("Connection time outs.txt", "a")
	Authfailure=open("Auth failures.txt", "a")
	SSHException=("SSH Failure.txt", 'a')
	EOFError=("EOFerrors.txt",'a')
	UnknownError=("UnknownError.txt",'a')

	try:
		# Actually connect to the device
		net_connect = ConnectHandler(**ios_device)  
		
		# Grab the hostname of the device, so it can be used as a filename
		hostname = net_connect.send_command("show run | i hostname")
		hostname = hostname[9:]
		
		#open file to write command output
		file = open('1 - ' + hostname + " - " + ip_address_of_device + " " + '.txt', 'w')
		# Print output to console screen
		print('-------------- Running script on ' + ip_address_of_device + ' - ' + hostname + ' ------------------')

		file.write('======== ' + ip_address_of_device + ' @ ' + hostname + ' ========')
		file.write("\n")
		
		output=net_connect.send_config_set(commands_list)
		#print(output)
		file.write(output)
		
		# Close the file	
		file.close()
		
		# Cleanly disconnect SSH session	
		net_connect.disconnect()
	except (AuthenticationException):
		print ('Authentication Failure: ' + ip_address_of_device)
		Authfailure.write('\n' + ip_address_of_device)
		continue 
	except (NetMikoTimeoutException):
		print ('\n' + 'Timeout to device: ' + ip_address_of_device)
		Timeouts.write('\n' + ip_address_of_device)
		continue
	except (SSHException):
		print ('SSH might not be enabled: ' + ip_address_of_device)
		SSHException.write('\n' + ip_address_of_device)
		continue 
	except (EOFError):
		print ('\n' + 'End of attempting device: ' + ip_address_of_device)
		EOFError.write('\n' + ip_address_of_device)
		continue
	except unknown_error:
		print ('Some other error: ' + str(unknown_error))
		continue

The routers.txt file should be formatted as such:

IP Address 1
IP Address 2

The commands.txt file should be formatted as such:

Config Level Command 1
Config Level Command 2
exit
Enable Mode Command 1
Enable Mode Command 2