This script was written to manage multiple switches which require you to enter the user credentials twice during an SSH session. I tried using Paramiko which authenticated fine for the first part, but would then always send the enable password instead of the second username.
Solarwinds NCM was also an option but again I could not find a way for NCM to pass the credentials twice.
In order for this specific script to function, you must first create a CSV file with the fields ‘hostname, ip, password’:
hostname,ip,password SWITCH-1,10.1.1.1,password01 SWITCH-2,10.1.1.2,password02 SWITCH-3,10.1.1.3,password03
And create a text file which stores the commands to be sent. You do not need to write ‘conf t’ or ‘wr’ in the config file as these are part of the script.
#!/usr/bin/env ''' Python Script which connects to devices defined in a CSV file and runs configuration commands from a .TXT file Usage: python script.py <csvfile.csv> <commands.txt> e.g: python script.py test-switches.csv ntp-enable.txt Log file (./log.txt) shows all data received during SSH session Written by Tom Whitfield - 2019 ''' import pexpect import sys import datetime import pandas as pd today = datetime.datetime.now() log = open('multiconf.txt', 'a+') csvfile = sys.argv[1] configfile = sys.argv[2] hn = pd.read_csv((csvfile), sep=',', usecols=['hostname'], squeeze=True) ip = pd.read_csv((csvfile), sep=',', usecols=['ip'], squeeze=True) pw = pd.read_csv((csvfile), sep=',', usecols=['password'], squeeze=True) index = 0 def yes_or_no(question): answer = raw_input(question + "(y/n): ").lower().strip() print("") while not(answer == "y" or answer == "yes" or \ answer == "n" or answer == "no"): print("Input yes or no") answer = raw_input(question + "(y/n):").lower().strip() print("") if answer[0] == "y": return True else: return False print('\nWARNING: You are about to send the following configuration:\n') cfg = open(configfile) for line in cfg: print(line.rstrip()) print('\n\nTo the following devices:\n') for line in hn: print(line.rstrip()) if yes_or_no('\nDo you want to continue?'): () else: quit() for i in ip: print('------------- connecting --------------\n') print('connecting to ' + (hn[index]) + '...') try: log.write('\n\n!----------------------------------------------------------------\n') log.write('! Connection to ' + (hn[index]) + '\n') log.write('! Executed on ' + today.strftime('%d %B %Y at %H:%M') + '\n') log.write('!----------------------------------------------------------------\n\n') child = pexpect.spawn('ssh -o StrictHostKeyChecking=no [email protected]' + (ip[index])) child.logfile_read = log child.expect('password:', timeout=10) child.sendline(pw[index]) print(' - auth success (stage 1)') e = child.expect (['Username: ', '>']) if e == 0: child.sendline ('root') child.expect ('Password:', timeout=10) child.sendline (pw[index]) print(' - auth success (stage 2)') else: print(' - stage 2 auth not required') child.sendline ('enable') child.expect ('Password:', timeout=10) child.sendline (pw[index]) child.expect ('#', timeout=10) print(' - entered priviledged mode') except pexpect.TIMEOUT: print('\nERROR: The connection to ' + (hn[index]) + ' timed out\n') log.write('\nERROR: The connection to ' + (hn[index]) + ' timed out\n') index = index + 1 continue except pexpect.EOF: print('\nERROR: EOF\n') log.write('\nERROR: EOF\n') index = index + 1 continue except Exception as exception: print('\nERROR: Script failed (Other)\n') print(exception) log.write('\nERROR: Script failed (Other)\n') index = index + 1 continue try: child.sendline ('conf t') child.expect ('config', timeout=10) cfg = open((configfile), 'r') for c in cfg: child.sendline(c) child.sendline ('exit') child.sendline ('wr') child.expect ('[OK]', timeout=10) child.sendline ('logout') child.close() except: print('\nERROR: Failed to amend configuration on ' + (hn[index])+ '\n' ) print(child.before) index = index + 1 continue print('\nSUCCESS: ' + (hn[index]) + ' configured\n') index = index + 1 print('\n------------ end of script ------------\n') print('updated logfile at ./log.txt\n') exit()