In January 2019, my boss set out the challenge of network automation. I’d dabbled in Python before, writing a beautiful expect script to scrap the number of users connected to a Cisco 5508 WLC and warn when it reached the 6000 client limit. I’d followed the learning labs on Cisco DevNet and thought “that’s interesting”. So I knew there was the mirage of NETCONF, RESTCONF, YAML, YANG, Netmiko, Jinja2, JSON, Nornir and NAPLAM on the horizon. I just didn’t know how it all fit together, what to ignore, and what was relevant. My boss wrote an excellent blog post, Code Every Day, which discusses the scary world of coding and how to over come it. This blog focus on the actual code and how we went about implementing a practical, scalable, and hopefully re-usable solution.
Just to set the record straight, I am not a programmer. To me a tuple is a type of flower, a float is something that happens when the toilet won’t flush properly, an array is something you find in Star Trek. There’s was a lot of trial and error to get to the outcome which was required (or re-write the requirements to fit the outcome), whacking a square peg into the round hole until it fitted or breaking every programming convention out there. You may well think, “why on earth did you do it like that” when it can be achieved “like this”. To reiterate, I am not a programmer, constructive criticism is encouraged but you may have to spell it out as to why.
One thing is clear: Scraping has its limitations and problems! The code may well work day one but it isn’t future-proof. As an example, I wrote a discovery module which attempted to discover facts about the network device; model, version etc using the raw output of ‘show version’. However, nuances between versions meant the output differed. Take for example the difference in output of ‘show version’ between different versions of IOS-XE:
- Cisco 3850 with IOS-XE 03.07.05E: Cisco IOS Software, IOS-XE Software, Catalyst L3 Switch Software (CAT3K_CAA-UNIVERSALK9-M), Version 03.07.05E RELEASE SOFTWARE (fc1)
- Cisco 3850 with IOS-XE 16.6.5: Cisco IOS Software [Everest], Catalyst L3 Switch Software (CAT3K_CAA-UNIVERSALK9-M), Version 16.6.5, RELEASE SOFTWARE (fc3)
Notice the placement (or lack of) of the ‘,’ before the word RELEASE. Hence, I had to write an if/ else statement to handle this nuance. It worked, but who’s to say in Cisco’s next release that that character I was searching on will shift or disappear? This problem is only magnified as the information you’re scraping becomes more detailed and dynamic.
Let’s look at the same problem in this realm of Model Driven Programmability. The following is a NETCONF RPC using the Cisco-IOS-XE-native YANG model:
</rpc-reply message-id="urn:uuid:373294ba-8b38-411c-be9c-c67f3533cfd4" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
<data>
<native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native"> <version>16.9</version>
</native>
</data>
</rpc-reply>
I now have the version number in a structured model, though it is only the major and minor (not the release or build – is this important? Maybe if I want to compare the running version against a desired version?). I’ll go into the detail of how I got to this point, but first we need an overview. For this, we’re going to define a problem, define an objective and layout the solution.
The Problem
Over the years, configuration creep has introduced discrepancies.
The Objective
Re-align configuration to a known gold-standard state. However, we want to know the current configuration state and DIFF with the gold state, report on the differences and then apply the configuration changes.
The Solution
The solution is going to consist of the following distinct elements:
- Environment
- Inventory & Variables (Nornir and YAML)
- Get Configuration (NETCONF, RESTCONF, NXAPI, NetMiko)
- Render Template (Jinja2)
- Compare Template to Configuration
- Push Configuration (NXAPI, NetMiko)
- Conclusion
Road Map
Note that this is Version 0 which is only focusing on global configuration commands (e.g. AAA, NTP, SNMP). Version 1 will focus on nested configuration (e.g. Interfaces, ACL, Routing). Version 2, who knows…?
Further Reading and Source Code
We’ll shortly be releasing the eBook. I’ll provide a link once its available.
In the meantime, you can contact us through the #NetworkBorg Twitter Channel and view our source code on GitHub:
https://github.com/FrancisCrickInstitute/network_borg_blog
Health Warning! “With great power comes great stupidity” [Google Search]. Be warned, scripting can trash your network. From the onset I’ve written in a -commit flag. Without this flag in the CLI argument, the final push configuration will not happen, it will just report on what would have happened. Use it before unleashing these BETA scripts on your production network! The authors take no responsibility for you finding a P45/W2 (aka “you’re fired!) in the post!