Now it’s time to turn our gaze to the godfather of YANG models and one of the most famous open-source SDN controllers, OpenDaylight. In this post I’ll show how to connect Cisco IOS XE device to ODL and use Yang Development Kit to push a simple BGP configuration through ODL’s RESTCONF interface.
In the previous posts about NETCONF and RESTCONF I’ve demonstrated how to interact with Cisco IOS XE device directly from the Linux shell of my development VM. This approach works fine in some cases, e.g. whenever I setup a new DC fabric, I would make calls directly to the devices I’m configuring. However, it becomes impractical in the Ops world where change is constant and involves a large number of devices. This is where centralised service orchestrators come to the fore. The prime examples of such platforms are Network Services Orchestrator from Tail-f/Cisco and open-source project OpenDaylight. In this post we’ll concentrate on ODL and how to make it work with Cisco IOS XE. Additionally, I’ll show how to use an open-source tool YDK to generate Python bindings for native YANG models and how it compares with pyangbind.
OpenDaylight is a swiss army knife of SDN controllers. At the moment it is comprised of dozens of projects implementing all possible sorts of SDN functionality starting from Openflow controller all the way up to L3VPN orchestrator. ODL speaks most of the modern Southbound protocols like Openflow, SNMP, NETCONF and BGP. The brain of the controller is in the Service Abstraction Layer, a framework to model all network-related characteristics and properties. All logic inside SAL is modelled in YANG which is why I called it the godfather of YANG models. Towards the end users ODL exposes Java function calls for applications running on the same host and REST API for application running remotely.
OpenDaylight has several commercial offerings from companies involved in its development. Most notable ones are from Brocade and Cisco. Here I will allow myself a bit of a rant, feel free to skip it to go straight to the technical stuff.
One thing I find interesting is that Cisco are being so secretive about their Open SDN Controller, perhaps due to the earlier market pressure to come up with a single SDN story, but still have a very large number of contributors to this open-source project. It could be the case of having an egg in each basket, but the number of Cisco’s employees involved in ODL development is substantial. I wonder if, now that the use cases for ACI and ODL have finally formed and ACI still not showing the uptake originally expected, Cisco will change their strategy and start promoting ODL more aggressively, or at least stop hiding it deep in the bowels of cisco.com. Or, perhaps, it will always stay in the shade of Tail-f’s NSC and Insieme’s ACI and will be used only for customer with unique requirements, e.g. to have both OpenStack and network devices managed through the same controller.
We’ll use the same environment we’ve setup in the previous posts, consisting of a CSR1K and a Linux VM connected to the same network inside my hypervisor. IOS XE device needs to have
netconf-yang configured in order to enable the northbound NETCONF interface.
On the same Linux VM, I’ve downloaded and launched the latest version of ODL (Boron-SR2), and enabled NETCONF and RESTCONF plugins.
1 2 3 4 5 6
We’ll use NETCONF to connect to Cisco IOS XE device and RESTCONF to interact with ODL from a Linux shell.
It might be useful to turn on logging in karaf console to catch any errors we might encounter later:
Connecting IOS XE to ODL
According to ODL NETCONF user guide, in order to connect a new device to the controller, we need to create an XML document which will include the IP, port and user credentials of the IOS XE device. Here’s the excerpt from the full XML document:
1 2 3 4 5 6 7
Assuming this XML is saved in a file called new_device.xml.1, we can use
curl to send it to ODL’s netconf-connector plugin:
1 2 3 4
When the controller gets this information it will try to connect to the device via NETCONF and do the following three things:
- Discover device capabilities advertised in the Hello message
- Download all YANG models advertised by the device into the
- Go through all of the imports in each model and verify that they can be satisfied
After ODL downloads all of the 260 available models (can take up to 20 minutes) we will see the following errors in the karaf console:
1 2 3 4
Due to inconsistencies between the advertised and the available models, ODL fails to build the full device YANG schema context, which ultimately results in inability to connect the device to the controller. However, we won’t need all of the 260 models advertised by the device. In fact, most of the configuration can be done through a single Cisco native YANG model,
ned. With ODL it is possible to override the default capabilities advertised in the Hello message and “pin” only the ones that are going to be used. Assuming that ODL has downloaded most of the models at the previous step, we can simply tell it use the selected few with the following additions to the XML document:
1 2 3 4 5 6 7 8
Assuming the updated XML is saved in new_device.xml.2 file, the following command will update the current configuration of CSR1K device:
1 2 3 4 5 6
We can then verify that the device has been successfully mounted to the controller:
The output should look similar to the following with the connection-status set to
connected and no detected
1 2 3 4 5
At this point we should be able to interact with IOS XE’s native YANG model through ODL’s RESTCONF interface using the following URL
The only thing that’s missing is the actual configuration data. To generate it, I’ll use a new open-source tool called YDK.
Yang Development Kit is a suite of tools to work with NETCONF/RESTCONF interfaces of a network device. The way I see it, YDK accomplishes two things:
- Generates API bindings for programming languages (Python and C++) from YANG models
- Creates an abstraction layer to interact with southbound protocols (NETCONF or RESTCONF) in a uniform way
There’s a lot of overlap between the tools that we’ve used before and YDK. Effectively YDK combines in itself the functions of a NETCONF client, a REST client, pyangbind and pyang(the latter is used internally for model verification). Since one of the main functions of YDK is API generation I thought it’d be interesting to know how it compares to Rob Shakir’s pyangbind plugin. The following information is what I’ve managed to find on the Internet and from the comment of Santiago Alvarez below:
|PL support||Python||Python, C++ with Ruby and Go in the pipeline|
|Serialization||JSON, XML||only XML at this stage with JSON coming up in a few weeks|
|Southbound interfaces||N/A||NETCONF, RESTCONF with ODL coming up in a few weeks|
|Support||Cisco’s devnet team||Rob Shakir|
So it looks like YDK is a very promising alternative to pyangbind, however I, personally, would still prefer to use pyangbind due to familiarity, simplicity and the fact that I don’t need the above extra features offered by YDK right now. However, given that YDK has been able to achieve so much in just under one year of its existence, I don’t discount the possibility that I may switch to YDK as it becomes more mature and feature-rich.
Python binding generation with YDK-GEN
One of the first things we need to do is install YDK-GEN, the tools responsible for API bindings generation, and it’s core Python packages on the local machine. The following few commands are my version of the official installation procedure:
1 2 3 4 5
YDK-GEN generates Python bindings based on the so-called bundle profile. This is a simple JSON document which lists all YANG models to include in the output package. In our case we’d need to include a
ned model along with all its imports. The sample below shows only the model specification. Refer to my Github repo for a complete bundle profile for Cisco IOS XE native YANG model.
1 2 3 4 5 6 7 8 9
Assuming that the IOS XE bundle profile is saved in a file called cisco-ios-xe_0_1_0.json, we can use YDK to generate and install the Python binding package:
Configuring BGP with YDK
Now we can start configuring BGP using our newly generated Python package. First, we need to create an instance of BGP configuration data:
The configuration will follow the pattern defined in the original model, which is why it’s important to understand the internal structure of a YANG model. YANG leafs are represented as simple instance attributes. All YANG containers need to be explicitly instantiated, just like the
Bgp classes in the example above. Presence containers (
router in the above example) will be instantiated at the same time as its parent container, inside the
__init__ function of the
Native class. Don’t worry if this doesn’t make sense, use iPython or any IDE with autocompletion and after a few tries, you’ll get the hang of it.
Let’s see how we can set the local BGP AS number and add a new BGP peer to the neighbor list.
1 2 3 4 5
At this point of time all data is stored inside the instance of a
Bgp class. In order to get an XML representation of it, we need to use YDK’s XML provider and encoding service:
1 2 3 4 5 6
All what we’ve got left now is to send the data to ODL:
1 2 3 4 5 6 7 8 9
The controller should have returned the status code
204 No Content, meaning that configuration has been changed successfully.
Back at the IOS XE CLI we can see the new BGP configuration that has been pushed down from the controller.
1 2 3 4
You can find a shorter version of the above procedure in my ODL 101 repo.