Asyncio Telnet Support in Scrapli

Its 2020, the year of COVID, lots of fires (US west coast at least), a wild election, and… telnet?! Yes, telnet!

While I am not ever using telnet to manage any production devices or anything like that (and I hope everyone else is not using telnet too!) I recently ended up needing a python telnet client. My use case is to be able to connect to the “console” port of virtual routers to handle initial provisioning and to make sure they are booting up nicely. I could very much see this being a “real life” use case that some other folks may end up having as well – maybe even for bootstrapping real hardware connected with console servers at a new site bring up or something like that. In any case, I ended up having a quick look around PyPI/GitHub to see what was available.

I’d known about telnetlib3 for a while and it ended up looking like the main (only?) option out there. So I took it for a spin to check it out. Telnetlib3 did exactly what it advertised to do, and if you are in need of a telnet library this seems like a fantastic option to have at your disposal. For me, however, I had a another thought in the back of my mind… what about adding an asyncio telnet transport to scrapli? Ultimately, after the initial bring up of the router I basically needed to do “normal” scrapli things anyway, so it would be pretty swell to just have it all wrapped up in a nice little bow for me.

Adding a scrapli transport is a fairly straight forward process – inherit from a base class, implement a few methods to appease the abstract base class, and for the most part thats it. There is a relatively important caveat here though: scrapli “core” has zero external dependencies – this means that any transport needs to be its own library so it can be an optional extra to install. Telnetlib3 is of course a third party package, so if I wanted to make it into a transport for scrapli I would end up needing to create “scrapli_telnetlib3” transport library… perhaps it is just year end laziness, but I just don’t really want to have another package to maintain – especially one that is likely not going to be used by anyone but me :)

Luckily a few weeks back on one of Dmitry Figol’s streams on Twitch he had already gone down this road and done a bit of experimenting with telnetlib3, and, more interestingly (to me at least), building an asyncio telnet client with just the standard library! I was able to catch a good chunk of this stream and as soon as I realized that I didn’t want to build a new transport library this all came back to me in a hurry and I jumped right in to playing with building my own telnet client!

Short story long, I ended up building the scrapli asynctelnet transport with nothing but the Python standard library. As there are no third party requirements I decided to just go ahead and stash this right in the scrapli “core” code. This was not as straight forward as using the already fully functional telnetlib3 library, but thanks to the exploring Dmitry had done I had a fairly decent idea of how to go about getting it working. That plus checking out the standard library sync telnetlib source code got me pretty much all the way there!

At this moment, the asynctelnet support is only in the develop branch, but before year end I will push a new release to PyPI with this support!