Something I feel like I don’t see enough of is information on interpreting YANG models and building XML documents to be used for network configuration. When I first began exploring NETCONF building a proper XML document was a struggle for me. I found YANG to be difficult to interpret and often I came up short when searching google for help. So I wanted to talk about a few methods I used to help understand YANG. The intent of this post is to demonstrate a few methods to interpret a YANG model and begin creating an XML document. I will not go in depth about NETCONF/RESTCONF or automation tools in this post. This is also not a deep dive into YANG, though I will touch on some things as it is necessary.
A Brief YANG Introduction to Set the Stage
YANG is a data modeling language. It can be used to model both configuration data and operational data. You can think of YANG as a set of rules detailing how data should be structured and what type the data is. When configuring network gear with NETCONF or RESTCONF the data you send must be of the proper type and structure that the router can understand, this is what YANG helps with. YANG its self is not sent to a network device, rather an XML document or JSON object is created based on a YANG model.
There are a few vendors that write YANG models such as IETF, openconfig, cisco, juniper, etc. IETF and openconfig aim to create industry standard vendor agnostic YANG models. Ideally this would mean, for example, an openconfig YANG model for configuring an interface on a router would be exactly the same wether you are configuring a juniper router, cisco routers, or some other vendor. A single XML document could be constructed and sent to any router that supports openconfig YANG models and we could expect it to apply the configuration. In reality, this is still fragmented and not fully realized. Vendors such as cisco need to fully implement these standard YANG models on their devices and the maintainers of the YANG models need to create a model to cover all configurations. Of course every vendor will have proprietary features that can be configured, so in this case it’s up to that vendor to extend and augment the openconfg YANG model to cover any proprietary features.
One last thing I want to note before we jump in is that Cisco seems to be incrementally implementing YANG models on their devices. Particularly with XE I have noticed that they seem to add a little bit more functionality with each release. I have ran into situations where I was unable to configure something via NETCONF simply because there wasn’t a YANG model implemented for it in the XE version the router was running. So if you aren’t finding a YANG model for something you want to configure, it’s possible it’s just not implemented in the software version of your device or perhaps not yet implemented in any version.
Pyang, a Command Line Tool
For viewing YANG
One way to look at YANG models is with a python application called pyang. This tool can help you visualize YANG models in several ways. I will be demonstrating the tree output and the sample XML skeleton output. Pyang can be installed via pip. In addition to install pyang you will want to clone the git repository with the YANG model files. Below is the url for the git repository containing several YANG models.
Using pyang tree Format
Lets take a look at pyangs tree format. See the example command below.
pyang -f tree -p ./yang_models/yang/vendor/cisco/xe/1693 Cisco-IOS-XE-native.yang >> xe-native-tree.txt
We use the “-f” flag to indicate we want the “tree” format. The “-p” flag is used to set the base directory in which pyang should search for other YANG models. This should be set because YANG models often reference other models and pyang needs to be able to find the other YANG files to create a complete output. I have noticed that I still get some errors when running this command on IOS XE YANG models, although the output still looks complete to me. Following this is the name of the YANG file that we want to convert to the tree format, “Cisco-IOS-XE-native.yang” in this case. We are then just redirecting the output to a text file as the output will be quite large and its more difficult to view in a terminal as opposed to a text editor.
The command can take several seconds to run, but once complete you should have the text file. Open this in a text editor to view. See the below excerpt from the output. I have edited some portions out for brevity.
module: Cisco-IOS-XE-native +--rw native +--rw username* [name] | +--rw name string | +--rw privilege? uint8 | +--rw view? string | +--rw one-time? empty | +--rw password | | +--rw encryption? enumeration | | +--rw password? string | +--rw secret | +--rw encryption? enumeration | +--rw secret? string
This model describes the configuration necessary to create a user on a cisco IOS XE router. We can see how the data is structured thanks to the +— and spaces. We can see the models begins with native which contains a username. Under username we can see multiple data elements and their data type. For example we can see data element “name” is a string and we can see data element “privilege” is uint8. As uint8 may be unfamiliar, this means the value for the data element must be an unsigned integer (think of it as a number without and sign, such as a negative “-“ sign) with a maximum of an 8 bit value. Remember your subnetting here, we should know that the largest number you can have with 8 bits is 255. However, we should also know that cisco’s user privilege level only goes to 15, so realistically we also have that constraint although its not obvious from the model. Note that most of the elements have a ? beside them. Thats means they are optional. Technically you can create a user on a cisco router with just “username seth”, which you can see the “name” element is the only required one.
From this we can see how to construct an XML document that could be transmitted to the router to create a user, see below.
<config> <native xmlns=“http://cisco.com/ns/yang/Cisco-IOS-XE-native”> <username> <name>seth</name> <privilege>15</privilege> <password> <password>agoodpass!</password> <encryption>0</encryption> </password> </username> </native> </config>
Note that I have added the <config> and <native> tags here although it doesn’t really show that in the tree output. These tags are necessary when sending configuration to an IOS XE device.
Another tip for looking at a yang model, use the –tree-depth=TREE_DEPTH flag. If we set that value to 2, we can get an overview of all the elements under native, which can help us find the configuration element we are looking for while reducing the output from the tree output. See the output below, trimmed for brevity.
pyang -f tree -p ./yang_models/yang/vendor/cisco/xe/1693 --tree-depth=2 Cisco-IOS-XE-native.yang module: Cisco-IOS-XE-native +--rw native +--rw default | ... +--rw bfd +--rw version? string +--rw stackwise-virtual! +--rw boot-start-marker? empty +--rw boot < ... > +--rw interface | ... +--rw route-map* [name] | ... +--rw route-tag +--rw table-map* [name]
You can quickly scan the list for what you want to configure, then refer back to the full tree output using a find in your text editor to search for the element.
Using pyang sample-xml-skeleton Format
You can also generate a sample xml document with pyang. This format is closer to what we will actually send to the router when making configuration changes. See the below command and example output, again trimmed for brevity.
pyang -f sample-xml-skeleton -p ./yang_models/yang/vendor/cisco/xe/1693 Cisco-IOS-XE-native.yang >> xe-xml-skele.txt <?xml version='1.0' encoding='UTF-8'?> <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native"> <banner> <exec> <banner/> </exec> <login> <banner/> </login> <prompt-timeout> <banner/> </prompt-timeout> <motd> <banner/> </motd> </banner> </native> </data>
With the xml skeleton output, we can more clearly see the document format we need to create to configure something. In this case, we are looking at the xml structure to describe the components necessary to configure banners such as a login banner or a MOTD banner. With this view, you dont see the data types and wether elements are optional or not like we could with the previous tree output. Something to point out here that a forward slash at the end of a tag (like “<banner/>”) is a short hand way to open and close a tag. If you need to open and immediately close a tag with no value this works, however it would need to be expanded to “<banner>My MOTD Here</banner>” to actually send configuration data. Also note that the xml version tag and the data tag are not necessary to include when sending configuration to an IOS XE device, however the entire document should begin with a <config> tag and end with a </config> tag.
ANX, A GUI for Viewing YANG Models
ANX is another tool for interpreting YANG models. This tool requires connectivity to a live NETCONF enabled device and provides a friendly GUI for viewing YANG. The GIT page has excellent instructions for installing it, so I will skip the explanation just give you the link below.
ANX is quite easy to use so lets just take a brief look. After getting ANX up and running you will see the screen below. Simply fill our your device IP, username and password and click login. ANX will take a few minutes as it discovers all the YANG models available on the device.
Once logged in, at the top left you will see a couple drop downs. The first one shows a list of YANG models discovered on the device and allows you to view or download them. This is similar to the YANG models we downloaded from github earlier, however these are pulled from your actual device so what you see here is sure to represent the devices actual models. The second dropdown will show a list of the devices netconf capabilities.
On the right side, you can explore a sort of interactive map of the yang model similar to the tree output from pyang. Here I have searched for ‘native’ as that was the model used in the previous examples.
Back on the left side (shown below), you can see some further information about items you highlight on the right side of the screen (shown above). You can also see the subtree filter which could be used in a NETCONF get-config to retrieve the specified section of the device configuration.
A ‘Quick and Dirty’ Method to Automating
Another method, and honestly this is less interpreting and more of a way to get quick results, is to just simply retrieve the configuration via NETCONF from a device and look at it. Maybe not the “proper” thing to do but it works. If you have a lab device, manually configure a sample of what you would like to configure with NETCONF and use your tool of choice to retrieve the configuration. Honestly, I find this to be the easiest and quickest way to begin building an XML document to configure a device. It’s also important to use the previous methods to get a better understanding of how all of this works. However, in a lab, trial and error can be a great way to learn as well.
To do this I want to call out one more feature of ANX, the NETCONF Console. You may have already noticed this button from the previous section so let’s take a look. After clicking the NETCONF Console button a new window pops up. At the top of the window you can prepare NETCONF commands to be sent to the router. A warning here, you can also use ANX to send configuration changes to a device so be careful if you are viewing a production device. This isn’t a NETCONF tutorial so I won’t be going into detail on using it. Using the below get RPC with only the <native> filter will retrieve the entire configuration of the device and display it in the bottom pane. The full configuration is cut off here to keep the image size reasonable but its all there and can be copied out to a text editor.
As I mentioned near the beginning of this post, not all classic CLI commands may be available with NETCONF/YANG, so I always suggest to use one of the above methods (and lab it!) to ensure your device supports the configuration you want to apply.
I am sure there are more methods than what I have described here, and perhaps some better ones. Everyone learns in different ways and often I find myself looking for that certain spark to get my brain moving in the right direction. That spark has often come from a blog post I came across while searching for answers so I hope documenting my thoughts will help someone else in a similar way.