I need some help for a script in Python. it works for few times, but I just added some time.sleep() and now the script won't work : It did not connect to switch by SSH or Telnet.
I also need some tips to optimize it, because i'm not pro and i would like to learn more on scripting.
Thank you !
(Sorry commentaries in french :/)
import paramiko, time, re, os
from ciscoconfparse import CiscoConfParse
import telnetlib
###cherche hotes depuis fichier hosts.txt###
with open("./hosts/hosts.txt","r") as f:
hosts = re.findall(r'(\d+.\d+.\d+.\d+)', f.read())
f.close()
###boucle pour chaque hotes###
for host in hosts:
state = ""
running_config = ""
try:
###Connexion SSH switch###
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(host, username='admin', password='XXXXX')
###création shell interactif###
connection = client.invoke_shell()
###commande enable###
connection.send("enable\n")
time.sleep(1)
connection.send("XXXX\n")
###commande running-config###
connection.send("terminal length 0\n") ###Permet l'affichage de l'intégralité des commande###
time.sleep(1)
connection.send("show running-config\n")
###récupération commande running-config###
resp_run = connection.recv(10000).decode(encoding='utf-8')
###fermeture sessions SSH###
connection.close()
client.close()
###Traitement running-config###
regex = re.compile(r'(Current configuration : (.+\n)+end)')
res = re.findall (regex, resp_run)
running_config = res[0][0] ###aide appel variable
except:
###si fail SSH test telnet###
state = "SSH NOK "###Permet génération rapport###
try:
###connexion telnet si SSH NOK###
session = telnetlib.Telnet(host, 23)
session.write(b"admin\n")
session.read_until(b"Password: ")
session.write(b"XXXXXX\n")
time.sleep(1)
session.write(b"enable\n")
session.read_until(b"Password: ")
session.write(b"XXXXXX\n")
session.read_until(b"#")
session.write(b"term len 0\n")
session.write(b"show run\n")
res = session.read_until(b"\nend").decode('utf-8')
###fermeture session telnet###
session.close()
###récupération commande running-config###
regex = re.compile(r'(Current configuration : (.+\n)+end)')
res = re.findall(regex, res)
running_config = res[0][0] ###aide appel variable###
except:
state += "TELNET NOK"###Permet génération rapport###
###Création fichier running_config.txt + dir selon host###
newpath = ('./config_switch/'+host+'/')
if not os.path.exists(newpath):
os.makedirs(newpath)
f = open("./config_switch/"+host+"/running_config.txt", "w+")
f.write(running_config)
f.close()
###test ssh telnet pour rapport###
if not state:
print (host+" OK")
else:
print (host+" : "+state+" ERREUR")
###generation rapport###
f = open("./rapport.txt","a")
f.write(state)
f.close()
###arrêt de 2sec par sécurité###
time.sleep(2)
You should have a good error handling mechanism if you have different version/model devices in your network. So we use below functions for some of operations these might help you.
Code (SSH Connection):
#Make Connection To Device Through SSH (If returns None Do Not Proceed)
def connectToCPESSH(ip, uname, pin, CI_LOCAL_ID, CI_Name, CI_Org_Name, runIDnull):
ip = ip.strip()
SSHCliente = None
try:
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(ip, port=22, username=uname, password=pin,
timeout=240,banner_timeout=250, auth_timeout=500)
SSHCliente = client.invoke_shell()
return SSHCliente
except paramiko.ssh_exception.SSHException as ssh1Err:
return "Equipment SSH version error : " + str(ssh1Err)
if isinstance(SSHCliente, paramiko.channel.Channel):
SSHCliente.close()
sys.exit()
return None
except Exception as e:
if isinstance(SSHCliente, paramiko.channel.Channel):
SSHCliente.close()
try:
tln = telnetlib.Telnet(ip)
print("Use Telnet Access to " + str(e) + " ### " + str(t))
except Exception as t:
print("Crab! Both Telnet and SSH Connection Failed ! " + str(e) + " ### " + str(t))
return None
So, in above code we try to connect via SSH and if we get an error about SSHException we log it and if we get any error try Telnet (this is optional, we use Telnet for some old devices).
Code (Wait For Prompt: Only HW and Cisco)
#Wait Prompt For The First Connection
def waitForPrompt(cxn):
appendedScrnRslt = ""
lastScrnRslt = ""
routerType = ""
outerLoop = True
timerx = 0
while outerLoop == True:
tempScrn = cxn.recv(65100).decode('ascii')
if(lastScrnRslt != tempScrn):
appendedScrnRslt += tempScrn
lastScrnRslt = tempScrn
if("#" in tempScrn or ">" in tempScrn or "]" in tempScrn):
if("#" in tempScrn):
routerType = "Cisco"
if(("<" in tempScrn and ">" in tempScrn) or ("[" in tempScrn and "]" in tempScrn) ):
routerType = "Huawei"
break
timerx += 1
if(timerx >= 100):
logging.warn("Uppss! No Connection")
routerType = "N/A"
break
return routerType
Waiting prompt is curicial, if you act early your command will not be send to device, and if you act late your cxn might be terminated. So, just checking for prompt (HW: , Cisco: your-router-name#) is better.
Code ( Send and Receive ):
#Send Command and Recevie CIdatafromSQL
def sendCmdToSSH(cxn, cmd, routerType, timeout):
appendedScrnRslt = ""
lastScrnRslt = ""
cxn.send(bytes(cmd+ "\x0D", 'utf-8'))
time.sleep(2)
timery = time.perf_counter()
while time.perf_counter() - timery <= timeout:
if(routerType == "Cisco"):
tempScrn = cxn.recv(65100).decode('ascii')
if(lastScrnRslt != tempScrn):
appendedScrnRslt += tempScrn
lastScrnRslt = tempScrn
arrTmp = tempScrn.split('\r\n')
arrTmp.reverse()
if("#" in arrTmp[0]):
break
arrTmp = []
if(routerType == "Huawei"):
tempScrn = cxn.recv(65100).decode('ascii')
if(lastScrnRslt != tempScrn):
appendedScrnRslt += tempScrn
lastScrnRslt = tempScrn
arrTmp = tempScrn.split('\r\n')
arrTmp.reverse()
if(">" in arrTmp[0] or "]" in arrTmp[0] ):
break
arrTmp = []
return appendedScrnRslt
Send and receive needs a timeout in order to break connection if some error occurs and we definetly need screen results too.
Code (To Get All Running Config From Cisco):
singleSSHCxn = connectToCPESSH(ip, uname, pin, CI_LOCAL_ID, CI_Name,
CI_Org_Name, runIDnull)
sendCmdToSSH(singleSSHCxn, "terminal length 0", "Cisco", 120)
cliResult = sendCmdToSSH(singleSSHCxn, "show running-config", "Cisco", 200)
sendCmdToSSH(singleSSHCxn, "exit", "Cisco", 120)
Hope this will solve your issue.