So, there I was, innocently browsing the OpenDaylight wiki after listening to Show 148 – Talking With OpenDaylight Leadership when I came across the OpenDaylight Command Line Interface page. I’ve not gone through the entire 118 pages (if I were to print it) worth of content, but I’ve scanned through a fair chunk and read the CLI Concepts section in full. What a disappointment. I’m genuinely shocked; it reads like a guide to the ancient, baggage laden and surely universally despised Cisco CLI with a few added sprinkles of Linux-like utilities mixed in to sweeten the bitter taste in your mouth.
Is this what Cisco has brought to OpenDaylight? Of course, I know there is more but still, an open source Cisco-mimicking CLI is still a rubbish CLI. Perhaps I’ve been spoiled by F5’s Traffic Management SHell (tmsh) which was built from the ground up with modern computing and networking firmly in mind. It was designed in the 21st century (released in 2009), not in the distant past, and boy you can tell the difference. Forgetting Cisco’s direct input, but perhaps not its influence, who thought this was a good idea? Perhaps, as just about every networking vendor’s CLI mimics Cisco’s, no one thought there was a better way, a better design.
UPDATE: Brent Salisbury responded to my comments around this stating, “There is a good amount of consolidating code sets initially to get the initial framework before sexyness happens,” which is understandable considering the age of the project. Hopefully I can influence some of that ‘sexyness’ starting with this article.
I’ve seen far better, and I really expect more where something as critical as an SDN controller is concerned. So, if nothing else, here’s my list of attributes (a combination of most of them anyway) that make a great CLI. If I can have a more direct influence (I don’t have the time but hey, when do I ever?) I’ll seize the opportunity and perhaps one day you’ll all experience the joys (no really) of a truly modern, well thought-out, hierarchical and powerful CLI.
Update – January 2015: I’ve now integrated the four sets of updates I’ve made to this article based on comments (thanks as ever), experience and other factors. It’s quite a long list now.
Also, I discovered that Terry Slattery is probably the man to blame for the design of the Cisco IOS CLI. He’s also the first CCIE (#1026) ever, so he can’t be all bad.
Use a Hierarchical Command and Object Structure
Not in a painful and convoluted way as with the typical configuration requirement of enable [RETURN] > conf t [RETURN] > interface x/x [RETURN] > ip address x.x.x.x [RETURN] but with commands and objects where this approach is useful and not with actual configuration where it is not.
Let’s say you are doing some troubleshooting. You’re likely to be entering a shed-load of show commands. Rather than entering show or sh every time, how about you just enter the command show and then you’re in show mode and every following command is interpreted as a show command (interface, log, etc.). If you need to enter a few non-show commands, that’s fine, you can, in a Linux file system style refer to the root of the command structure. Say they were debug commands, you could do something like this: /debug arp packets and then continue not using the show command to show you stuff! To exit from show command mode just use /; show xxx is still usable too if you prefer it that way.
This approach can be extended even further and applied to collections of configuration objects in a useful way. This could be done based on customer or client (i.e. multi-tenancy) or anything else that might make sense. tmsh uses a file system structure (and commands) to group and separate collections of configuration objects.
On the flip side, you really shouldn’t be forced to specify, one level at a time, the configuration path to an object. Taking the example above you should be able to do this all on a single line; modify interface x/x ip address x.x.x.x.
Avoid Similarly Named Commands
Shortcuts would be rather more handy if command names were considered a bit more deeply. The show port and show port-channel commands should not both exist when you can clearly use something else for one or the other (like interface or channel). Brocade Vyatta vRouter is a great example of a poor implementation; the configure command clashes with the configsync command meaning you need to type at least configu before you can enter configuration mode, syncconfig might have been a better choice.
Dump the Legacy
Really, configure terminal and enable? Is there a point to these commands other than to waste your time? In most cases your access and privileges are specified and confirmed by some remote system when you log in. Why waste time requesting something you already have? Why do you need to inform the system you’re making configuration changes? We’d all be better off if re-authentication was required when using potentially damaging commands (reboot, debug and so on). On a related note, why have the spanning-tree command when stp would suffice? You get the idea.
Allow for Useful Matching & Filtering
There is a difference and this should be pretty simple to use. If you’re using a show or list (or similar) command and want to match and display information on specific groups of objects – say all interfaces that have an IP address starting with 192 – something like show interface ip address 192* should be available. Note that I’m expecting the full interface configuration for each matching interface to be displayed, not just the IP address(es).
If you want to filter the output of a command, that should be just as easy using standard tools such as grep in combination with globs or regular expressions. Unlike matching, filtered output will only show lines (status or configuration related) containing the filter expression, at least unless specified otherwise.
Allow for Scripting & File Input
Always make a quiet option, not requiring input, available. Allow sets of commands to be run from an input file, local or remote and provide a variety of options around error handling and output. Who doesn’t want their script-foo to be easier and more powerful?
Allow for File Output
Local and remote output to a file should be standard options. Who wants to copy and paste the output of a show tech or configure their client to save it? Again, this is the 21st century you know.
Admit When Your Wrong
It seemed like a good idea at the time, but your users have told you it doesn’t make sense or is overly complex. Have the courage to admit you were wrong and implement something better (perhaps still accommodating the original commands for a while). Alternatively, stand firm against the complaints because you are certain the short term pain is worth the long term benefit – for the user, not you. Either way, explain yourself, consult and where necessary, change and improve.
Support Multiple Commands On One Line
Simple enough, it saves a few key presses and in some ways helps you define what you want to see (or do) before any command output might distract you from that goal.
Support Comprehensive Keyboard Shortcuts
One area where I can’t complain in relation to the OpenDaylight CLI, Readline provides a host of keyboard shortcuts and other facilities that put most vendors to shame. These are invaluable time savers. It might not seem important, but when the pressure is high and money is at stake, things like this make a real difference (see Programming 101 for Network Engineers – Preparation).
Support Customisations, Simply
I want to see things the way I want or need to. I should have the option to tweak output and the CLI itself easily. If I want to see port numbers rather than service names that should be something I can configure. If I want to see subnet masks express in prefix notation or unmolested, full-length IPv6 addresses, I should be able to specify that. Colour and control over it would be really nice too.
Meaningful Command Names & Negation
When you’re deleting or removing configuration, perhaps it would help if it was linguistically clear as you were doing it. Using no to remove something isn’t my idea of clarity and doesn’t really stand out as much as the delete command would.
Similarly, when you’re creating something, shouldn’t you be required to explicitly state that using a command called create? This would also remove a bit of risk. Create ip address x.x.x.x wouldn’t work if the interface already had an IP address; I’d need to use the modify command instead. Equally, show would display state, list would display configuration – no ambiguity remains. Any extra typing is easily mitigated through the benefits of a Hierarchical Command and Object Structure (described earlier).
An Edit Function
This would allow you to modify entire sections of configuration by editing the configuration text rather than using commands (available in tmsh and the Mikrotik CLI – thanks to Matthew Walster).
Single Line Input
Enter one long command rather than following a nested structure and having to use loads (available in tmsh – thanks to Nuno). The same applies when displaying configuration.
Show Command Output Formatting Options
What a boon it would be to have some level of control on the format of output. Options might include; summary, list, table, tree and one-line (summary available with the Cisco CLI – thanks to Octavio Alvarez)
A Common Output Field Delimiter
For when you’re scraping, scripting, exporting and so on. This could possibly be globally configurable so you could specify all show command output is delimited by commas or something else entirely (it could also be an option per command).
On-box Configuration Scripts
I’m not talking about Tcl or programming, just the ability to run a series of commands (a script) from a text file stored on the box. This would be a real boon to those performing pre and post-change ‘standard’ tasks, troubleshooting or frequent tasks of any kind (available with tmsh and probably others – thanks to Mike Bushong).
On-box Command Output Storage
This would allow you to compare pre and post-change show command output for instance, which leads us to the next feature (thanks to Mike Bushong). I kind of covered this but wanted to be more explicit. This could be in-memory and indexed.
Functions allowing comparison of stored configurations, show command output or anything else (thanks to Mike Bushong).
Validation and Linking
Perhaps more suited to GUI tools but there’s still some utility in this, for instance automatically running a suitable show command after you’ve changed the configuration of something, or forcing the display of log entries/events related to something you’ve just configured (an interface going down, a duplex mismatch, an OSPF neighbour failure etc.) (thanks to Mike Bushong).
Configuration Commit and Rollback
The benefits are obvious (available with Juniper, Vyatta and VyOS – thanks to Paul Boot)
Without requiring a reboot (available with tmsh).
Simples. Supported by most I think.
I have to add Russ’ two points found in the comments below (thanks Russ); I’d overlooked these but I think they are both essential.
This may seem picky or downright obscure but I believe this is important even if it’s effects are only subconscious perhaps. This relates to my points about commands being meaningful but extends it somewhat. Every command, no matter where you might be in the hierarchy should use consistent grammar unless doing so negates the use of that hierarchy. My ideal would be verb/action, noun/subject1, noun/subject2…, noun/data(if required) | noun/state(if required) and adjective/option/parameter/filter.
Greg Ferro’s article here makes it clear there’s even more to consider such as avoiding double negatives, consistency with negative and positive commands (enable, disable, shutdown) and so on. There’s also some good thoughts in this piece from Julian Dunn of Chef.
Consistent Command Structure
This relates to the previous point but also includes other elements. If something is enabled or disabled then all objects should adhere to this; interfaces shouldn’t be shutdown or downed, they should be enabled and disabled or restarted and so on.
Multiple Action Commands
This leads on from the previous point (although it’s not mentioned by Russ). The ‘restart’ command should be available rather than having to use disable and enable and the like.
Don’t confuse this with transaction consistency or similar concepts. This simply means that any multiple action commands ‘roll back’ unless each command is successful. Additionally, any ‘risky’ single action commands can have a default rollback period (say two minutes) in which time if the user doesn’t confirm success the modification is reversed. This would avoid the need for ‘reload in 5’ and similar.
Ivan’s related article here and Mike Bushong‘s comments in particular got me thinking on the subject of standardisation; A simple concept but what a difference it would make. Standard commands, output, structure, facuilities, colouring and so on would make everything so much easier. Surely I don’t need to explain the ‘standard’ benefits of why this would be amazing and help everyone. Anyone want to help me write an RFC?
A Consistent Data Model
This and the next came to mind as I considered The Attributes of a Great Network Device API
A seemingly very simple requirement, express all output data in a consistent format. Don’t use a status of UP in one place and ENABLED in another. Use status or state, don’t switch between the two randomly. All time data should be in the same format, output in bits, bytes or Mb and so on.
Machine Readable Output
Provide an option to have command output formatted in a machine friendly way, JSON, XML, simple CSV, it doesn’t really matter. Just something that I don’t have to fiddle with too much to feed it into Excel, a database or whatever else I’m forced to use.
Auto-complete Possibility Rotation
This one comes from the Minecraft command editor, courtesy of one of my kids. If auto-complete doesn’t find an unambiguous match, instead of just doing nothing, cycle through the possibilities if there are say, ten or less. This could be made even more useful by applying some ‘intelligence’ so rather that working alphabetically, instead the most likely commands are cycled through first.
I could go on. I’m sure there are other time saving & useful functions and approaches that I haven’t come across which could be applied to the OpenDaylight CLI and many others. If you know of any, do let me know in the comments section below. There must be more out there, and I’m very keen to learn about it. And perhaps (just maybe) you and I can influence the future just a little.
Some interesting points on the CLI and Unix/Linux commands here: https://mkremins.github.io/blog/unix-not-acceptable-unix/