Automating tasks on devices with no vendor API/library support is really hard work, but it can also be the most useful code you write. In this example the devices have no API, SDK and the CLI structure is so different to network equipment that standard automation techniques won't work.
The Problem
My most recent coding task started with a classic requirement: Change the same config on a large number devices of the same type and firmware version. Straight out of a textbook on network automation. Though in this case the device type wasn’t the normal switch or router and the vendor is a decade away from implementing APIs or python libraries. That last point hints at the source of my woes.
The primary goal was simply to change the username/passwords on all managed PDUs in the data centres. We use the same device model everywhere (PX3) and had recently upgraded all firmware. So a straight forward task of do the same CLI task a couple of hundred times. Easy. Right?
With no external libraries or even good documentation about CLI commands I had to first learn to do this the hard way. The CLI is weird. There is a config mode and a non-config mode, similar to every switch. ‘config’ to enter the mode and ‘apply’ to exit (and make the change live). There is help with a ? at the end of a line. So some familiarity. But the commands to achieve config are odd. For example, here is how to add an admin:
user create <username> enable <role>
After which the prompt asks for the password (on a new line, without the standard prompt), and again to confirm. For those that have to mangle CLI outputs a lot in code, the lack of a standard prompt on these lines screams ‘problem’. Its basically like the classic “are you sure you want to do this?” question some CLI commands ask on switches for which you have to enter “y”.
The next thing I noticed was that if you attempt to add a user that exists, or for which there is no role, this is not permitted and the rejection isn’t a simple return to the prompt with an error message. You get an error message and everything you’ve typed is still there. In other words you cannot paste a line of config and ignore the fact said line is already present (compare adding a static route to a switch). If you use nornir then careful use of ignore prompt and ignore command arguments is needed.
So one could simply attempt to delete the user and paste over, ignoring if the user was present or not. That doesn’t work as it complains in the opposite direction.
After performing my normal “press every button til it works” method I found that ctrl-c got me back to the standard prompt.
So…
With the Raritan CLI I paste ctrl-c before doing any single task. Every line sent from python has this at the start, to ensure the line I’m pasting will be used as sent. For the task of creating an admin user you need to send multiple commands in a netmiko_multiline method. Here is an example with the escape character for ctrl-c at the start and end of the line. Note also that after the apply (should it be successful) I had to put a cancel. The means that if the string isn’t accepted after the apply, it returns the prompt back to a known place. Every command to configure something looks like this with the end result to return back to the prompt as if first logged in.
The following example creates a user from variable pduUser with the password from variable pduPassword.
["\x03", "config", "user create " + pduUser + " enable Admin",pduPassword,pduPassword,"apply","\x03","cancel","\x03"]
To delete a user:
["\x03", "config", "user delete " + user ,"apply","apply","\x03","cancel","\x03"]
These are just examples but give a hint at how to handle automation of strange devices. A key point is that if the user can type a deterministic set of keystrokes to achieve a goal then it can be replicated with python automation. Using this technique a was able to create a set of scripts that allowed to add/delete/modify/check the most common aspects of the raritan CLI, and importantly do this consistently for 160 PDUs, and in less than a minute.
Leave a comment