1

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)
S. Me
  • 31
  • 1
  • 9
  • You have added `sleep` calls after the `connect`, so how could it prevent the connect? What exact error do you get? Where do you get that error? – Martin Prikryl Nov 27 '19 at 15:22
  • No error from the idle, i juste have in result for each Host : "Host ssh nok telnet nok erreur " i use those print for know if ssh was used or telnet. So i have a empty configuration for each switchs ... – S. Me Nov 27 '19 at 15:57
  • https://stackoverflow.com/q/1483429/850848 – Martin Prikryl Nov 27 '19 at 16:04
  • Thanks u ! So i Can get all exception with this? Let's débug then ! Any tips for optimization ? – S. Me Nov 27 '19 at 16:22
  • So I put some exception to know what happen, but I've an error, but i don't know where it come from... list index out of range [WinError 10061] Aucune connexion n’a pu être établie car l’ordinateur cible l’a expressément refusée 10.250.171.251 : SSH NOK TELNET NOK ERREUR File "C:\Users\XXXXXXXXXXX\Desktop\conf switch python\prog.py", line 26, in time.sleep(1) – S. Me Nov 28 '19 at 07:26
  • Can you connect to that IP (10.250.171.251) anyhow? With a trivial Python script (no `hosts.txt`, no `sleep`, no `send`)? Or with any SSH/Telnet client? – Martin Prikryl Nov 28 '19 at 07:34
  • Using PuTTy Yes I Can, i just found the solution... I reduce too much the time to wait before getting the running-config I add time.sleep(3) before the resp_run in SSH connection.... but I still don't understant why before i get the connection refused from each SSH and telnet – S. Me Nov 28 '19 at 07:50
  • i don't understand why you are using just paramiko. why not using netmiko which handles all your session stuff. check that out: https://pynet.twb-tech.com/blog/automation/netmiko.html – tgyger Nov 30 '19 at 22:15

1 Answers1

1

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.

furkanayd
  • 811
  • 7
  • 19
  • Thanks for your help I'm gonna take a look at your code which is much better than mine. – S. Me Feb 17 '20 at 07:43