0

I want to access two Cisco IOS switches (192.168.2.11 and 2.12) and get facts from them (with help of 'pyntc' library) concurrently using asyncio, I'm using Python 3.8.2.

I did a test in another script WITHOUT using asyncio, it took 25 seconds in total to get the work done, each switch took roughtly 12.5 seconds to be processed.

I was expecting that below script should take around 13.5 seconds in total (with an additional second from "await asyncio.sleep(1)") to get the facts from both switches, but it ended up taking 27 seconds in total.

I'm new to asyncio, and couldn't figure out why it's not working as expected.

import asyncio
from pyntc import ntc_device as NTC
import json
import time

async def SW1():
    SW = NTC(host='192.168.2.11', username='user', password='pass', device_type='cisco_ios_ssh')
    SW.open()
    print ('Successfully logined to 192.168.2.11.')
    await asyncio.sleep(1)
    print (json.dumps(SW.facts, indent=4))

async def SW2():
    SW = NTC(host='192.168.2.12', username='user', password='pass', device_type='cisco_ios_ssh')
    SW.open()
    print ('Successfully logined to 192.168.2.12.')
    await asyncio.sleep(1)
    print (json.dumps(SW.facts, indent=4))

async def main():
    task1 = asyncio.create_task(SW1())
    task2 = asyncio.create_task(SW2())
    start_time = time.time()
    await task1
    await task2
    print ("Time elapsed: %.2f"%(time.time()-start_time))

asyncio.run(main())
Parry Wang
  • 115
  • 8
  • I'm afraid your expectations are misplaced, unless the Cisco library you are using (pyntc) provides awaitable objects that take advantage of asyncio capability. The only time you can use asyncio to speed up a program is when the app has to wait for some resource, and there is something useful for it to do in the meantime. Otherwise you are just adding useless time delays, which as you observed doesn't speed up anything. It's possible that multithreading or multiprocessing could help, but only if you are not network-limited. – Paul Cornelius May 23 '20 at 02:25
  • Thank you Aaron, you are right, I tried 'await SW.open()' and got "TypeError: object dict can't be used in 'await' expression", I just found another library called 'Netdev' which supports asynchronous interactoin with network devices. Multithreading is indeed another option to speed up the work, I will give it a shot to find out which is better for network engineer to perform bulk configuraiton on multiple network equipments. – Parry Wang May 23 '20 at 13:24

1 Answers1

0

Seem that NTC or NTC.open block the thread of the event loop.

You may use loop.run_in_executor to run the synchronous function on other threads.

import asyncio
from pyntc import ntc_device as NTC
import json
import time


def SW1():
    SW = NTC(host='192.168.2.11', username='user', password='pass', device_type='cisco_ios_ssh')
    SW.open()
    print('Successfully logined to 192.168.2.11.')
    time.sleep(1)
    print(json.dumps(SW.facts, indent=4))


def SW2():
    SW = NTC(host='192.168.2.12', username='user', password='pass', device_type='cisco_ios_ssh')
    SW.open()
    print('Successfully logined to 192.168.2.12.')
    time.sleep(1)
    print(json.dumps(SW.facts, indent=4))


async def main():
    loop = asyncio.get_running_loop()
    task1 = loop.run_in_executor(None, SW1)
    task2 = loop.run_in_executor(None, SW2)
    start_time = time.time()
    await task1
    await task2
    print("Time elapsed: %.2f" % (time.time() - start_time))
Aaron
  • 1,255
  • 1
  • 9
  • 12
  • Thank you Aaron, I tried "asyncio.get_running_loop()" but no luck, looks like the 'pyntc' library does not provide awaitable objects. I just found another library called 'Netdev' which supports asynchronous interactoin with network devices. – Parry Wang May 23 '20 at 13:19