I'm having a hard time trying to make asyncio working with telnetlib for interrogate some hardware.
I think I clearly don't understand the way asyncio is working and I'm a completely lost in all of this. It's really unclear.
My basic version (which is synchrone) is working well but interrogating the complete list of equipments takes 6 hours actually and a large part of the equipements are not responding because they are unreachable.
Since Asyncio make us able to parallelize the connections without waiting for each timeout to trigger I would like to transform my code in proper asynchrone code, without success.
Here is what I tried :
import telnetlib
import time
import datetime
import asyncio
from env.fonctions import *
from env.variables import *
first_cmds = ['term length 0', \
              'show run', \
              'exit']
#create lists to iterate through
hosts = ['router-1', 'router-2', 'router-3', 'router-4', 'router-5']
async def main(hosts, user_rw_hw ,password_rw_hw, first_cmds):
    class ContinueI(Exception):
        pass
    continue_i = ContinueI()
    for host in hosts:
        print(f'{host} | Trying to connect...')
        try:
            tn = await async_establish_telnet_connexion(user_rw_hw ,password_rw_hw, host, 23, 0.5, True)
        except:
            continue
        print(f'{host} | Checking if equipment is not Nexus')
        tn.write('show version'.encode('ascii') + b"\n")
        sh_ver = await async_read_telnet_output(tn)
        if 'Nexus' in sh_ver or 'NX-OS' in sh_ver or 'nexus' in sh_ver:
            print(f'{host} | Equipment is Nexus, closing connection...')
            tn.write('exit'.encode('ascii') + b"\n")
            continue
        tn.write(''.encode('ascii') + b"\n")
        try:
            for cmd in first_cmds:
                tn.write(cmd.encode('ascii') + b"\n")
                if not 'exit' in cmd:
                    response = await async_read_telnet_output(tn)
                    if '\r\n% Invalid' in response:
                        print(f'{host} | Commande "{cmd}" pas reconnue')
                        raise continue_i
                else:
                    print(f'{host} | Commands are accepted')
        except ContinueI:
            tn.write(b"exit\n")
            tn.write(b"exit\n")
            print(f'{host} | Logout for command not recognized')
            continue
if __name__ == "__main__":
    try:
        loop = asyncio.get_event_loop()
        loop.set_debug(1)
        loop.run_until_complete(main(hosts, user_rw_hw ,password_rw_hw, first_cmds))
    except Exception as e:
        pass
    finally:
        loop.close()
and functions :
async def async_read_telnet_output(tn, timeout=2, timestep=0.1):
   timer = 0
   data = b''
   while timer <= timeout:
       new_datas = tn.read_very_eager()
       if len(new_datas) != 0:
           timer = 0
           data += new_datas
       await asyncio.wait(timestep)
       timer += timestep
   return data.decode('utf-8')
async def async_establish_telnet_connexion(user_rw_hw, password_rw_hw, host, port=23, timeout=1, debug=False):
   try:
       tn = telnetlib.Telnet(host, port)    # Here I don't know how to make it awaitable, if I put await before the IDE said that this method is not an awaitable, btw even if I put an awaitable like "asyncio.sleep" the behavior is still the same so it's not the only point bad
   except:
       if debug == True:
           print(f"{host} | Telnet not responding.")
       raise Exception
   if debug == True:
       print(f"{host} | Telnet is responding.")
   response = loop.create_task(async_read_telnet_output(tn, 15))
   if not 'Username:' in response and not 'login' in response:
       if debug == True:
           print(f"{host} | Don't see Username asked by equipment.")
       raise Exception
   else:
       tn.write(user_rw_hw.encode('ascii') + b"\n")
   if debug == True:
       print(f"{host} | Username entered.")
   try:
       await tn.read_until(b"Password: ", timeout)
   except:
       if debug == True:
           print(f"{host} | Don't see Password asked by equipment.")
       raise Exception
   finally:
       tn.write(password_rw_hw.encode('ascii') + b"\n")
       response = await async_read_telnet_output(tn, 10)
       if '% Authentication failed' in response or 'Rejected' in response:
           if debug == True:
               print(f"{host} | Connection failed bad credentials.")
           raise Exception
       if debug == True:
           print(f"{host} | Connection succeed waiting for commands.")
       return tn
If some people know where I fail I would be grateful i'm stuck since one week on it... Reading some books and youtube tutos but nothing help me..
Thank you by advance !
 
    