Lab: Docker NSO Part 3 – API’s

Note: throughout this post the NSO and NCS abbreviations may be used interchangeably. NSO is the abbreviation for “Cisco Network Services Orchestrator”. However, inside the commands to interact with the platform all begin with NCS. NCS is leftover from the previous product name “Cisco Prime Network Control System (NCS)”

This is a continuation of Lab: Docker NSO Part 2 – NCS CLI. As with part 2, everything in this post has been tested, however, if you see something that is inaccurate, or needs further description please leave a comment. This will help me and others that may stumble across this post in the future

In this post we will take the netsim devices created in part 1, the NSO configuration from part 2, and interact with them using NSO API’s. This proved harder then I had anticipated. I found the API documentation, especially in relation to RESTCONF to be lacking. With some collaboration with some friends in the RouterGods community we manged to get this figured out. I hope this post will save you some of the struggles we encountered.

Certification Alignment

If you are following along as part of the Cisco Devnet Associate certification, this is where things start getting interesting. Understanding the API’s associated with NSO will be important for section 3.9 and 3.9a

3.9 Construct code to perform a specific operation based on a  set of requirements and given API reference documentation such as these:          
   3.9.a Obtain a list of network devices by using Meraki, Cisco DNA Center, ACI,
   Cisco SD-WAN, or NSO

API Types

There are few northbound API’s available with NSO, including SNMP, REST, NETCONF and RESTCONF. This post will focus on interactions using RESTCONF API’s with Postman. This port will cover the basics of using the RESTCONF API’s to get NSO information, list devices, and specific device configuration. The next post will review adding devices, and update configuration using these API’s.

Getting Started With Postman

For this exploration I will be using Postman. Once I have an understanding of the API’s and how to interact with NSO, then I’ll convert it into Cisco DevNet Network Programmability Basics video course. Specifically Module 2 covers the basic of API’s and Postman.

Postman Setup

Authentication

The API authentication type with NSO is basic authentication. The default username is admin and the default password is admin. For my setup I created an “NSO” collection, with variables for the username and password.

Authentication

Content-Type Headers

The Content-Type header is used to set your preference between XML and JSON. For GET requests the default response will be XML, for POST’s there is not default, content-type must be assigned. To specify XML format use the Content-Type: application/yang-data+xml, for JSON format use the Content-Type: application/yang-data+json.

XML Headers
JSON Headers

In the examples below I will use a mix of XML or JSON format. For many cases I used XML simply because it was the default. However, in many circumstances the output and followup steps will be easier to explain and understand when looking at the JSON format. In most cases both formats will provide the same data read and write capabilities. I encourage you to look at, and become familiar with both formats. When it comes to building the python scripts to interact with the API’s using RESTCONF I will likely standardize on the JSON format, as personally I find it easier to use.

Getting Data

RESTCONF Base URL

First lets examine base URL for our RESTCONF calls: http://127.0.0.1:8080/restconf/

  • http – for the purposes of the lab I am using http, which is enabled by default. https can be enabled in the ncs.conf file, and should be for production use. For lab use however http is sufficient
  • 127.0.0.1 – I am running this lab as a docker image on my local computer, and am accessing it via the localhost IP.
  • :8080 – default port for http access, if using https, the default port in the ncs.conf file is 8888
  • /restconf – the restconf root directory, as per the RESTCONF RFC, his can be discovered using the the host meta file: http://127.0.0.1:8080/.well-known/host-meta
/.well-known/host-meta

A GET request to the RESTCONF root http://127.0.0.1:8080/restconf/ will return two results to pay attention to: data, and operations. These are both API Resources defined by the RESTCONF RFC. To quote the RFC, data is a “mandatory resource [that] represents the combined configuration and state data resources.” This is used to read, write, and update configuration data in NSO and associated devices.

The operations API resource is an “optional resource [that] is a container that provides access to the data-model-specific RPC operations supported by the server.” This is used to trigger activities data synchronization requests.

I will explore the operations section more in the next post. for this post I will focus on reading information from the data resource.

Data

Lets see what is inside the data tag with a GET request to http://127.0.0.1:8080/restconf/data?depth=1. To limit the size of the output I specified the query at the end of ?depth=1 this limits the amount of data returned to 1 subtree deep from data. Throughout this post I will use the ?depth=1 query as it keeps the output smaller, which allows me to capture it in small screenshot, and makes it easier to focus on specific elements. If you are running these along with me in your own lab, try the commands without the depth query to see the full scope of data returned.

On the left side is the default response using XML, on the right hand side I specified the JSON headers. This output shows a list of containers that have information. Had I not specified the depth of 1, this output would have shown the tree full of information. We can drill down into the specific containers by appending the container name to out URL, however, for this next level we also must specify the module namespace. This namespace indicated what YANG model we defines the data.

Namespaces

In the XML output the xmlns attribute defines the XML Name Space that is used for each of the containers. In some cases this this is in a URL format (xmlns=”http://tail-f.com/ns/ncs”) in others it is in a URN format (xmlns=”urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring”). Neither of these formats is what we need for our RESTCONF URL.

I struggled with this a bit, how do we know what namespace to use? Well, best I could find (and there may be a better way) is do the http://127.0.0.1:8080/restconf/data call again, without the depth filter. At the top of the output is the module-state container, This is a list of modules. If you look through this module list you will eventually find one with the namespace that matches our xmlns attribute, here the <name> tag in that module contains the namespace we will use is the RESTCONF URL

This is where JSON output makes things much easier. If you look back at the JSON output you’ll see the format of JSON data is "namespace:container": {... in this case the namespace is provided using the module name, in the same format we will use in our RESTCONF URL.

Devices

Now that we know how to find the name space, lets look at what is inside the devices container with a GET request to http://127.0.0.1:8080/restconf/data/tailf-ncs:devices?depth=1. Again I am limiting the output with the ?depth=1 query command. For this request, lets look at both the XML and JSON outputs.

NOTE: If I did not specify the “tailf-ncs:” namespace I would have received an error back "missing module name for 'devices'".

XML ouput
JSON output

So this gives is a list of sub-containers within devices container. In the xml output you see there are two “device” tags. This will be the two devices we added in Lab: Docker NSO Part 2 – NCS CLI, ios0 and iosxr0. In the JSON output however you see there is just a single device tag, but that it contains a list (as indicated by the square brackets []). If you change the depth to 2, or just remove the query you’ll get a response that includes some information on the devices (name, ip address, port, etc.).

Device List

If you want just a list of devices, you should be able to add on the /device to the url right? So what happens if you GET 127.0.0.1:8080/restconf/data/tailf-ncs:devices/device. Well if you have it set to JSON it works exactly as you expect. However if you use the default xml format you will get an error back <error-message>too many instances: 2</error-message> (2 in this case as we had 2 devices). At the time of writing this I have not found a way to get the list of devices with XML, although I did not try very hard, as JSON just works.

Device=ios0

This time we are going to expand the URl a bit further. To focus on a single device, I specify this by adding an equal sign and the device name. I focus on device with the name ios0 with the URL : http://127.0.0.1:8080/restconf/data/tailf-ncs:devices/device=ios0?depth=1.

Here, showing the JSON output, which contains the information NSO has about the device. We can see the name, address, port, and authgroup that we specified when adding the device to NSO. You can continue to drill down into these containers to see more information (or just remove the depth query). Lets look at the configuration next.

Device Config

The output below of the GET http://127.0.0.1:8080/restconf/data/tailf-ncs:devices/device=ios0/config?depth=1 shows the configuration elements NSO has stored.

Once again you will notice all the elements have module namespace listed. if you remove the depth query you’ll see information from these containers, but you can not drill down further unless you specify the namespace

Drilling Down In The Configuration

At this point we have reached as deep as we can go with the tailf-ncs namespace. To go further into the configuration we need to again specify a namespace based on the device model. For this device the namespace we will use is tailf-ned-cisco-ios. The iosxr0 device, would use the namespace tailf-ned-cisco-ios-xr.

If you looked at the configuration in the previous GET statement with the JSON format, this is easy to see, as it shows the name space in the configuration output, for example, the interface section shows tailf-ned-cisco-ios:interface.

If you look at the XML output however this is a bit harder to figure out, as the XML output is <interface xmlns="urn:ios">. How do we align the XML Namespace to the RESTCONF name space required? Once again, I struggled with this for a while as I was not looking at the JSON outputs. But this is what I found, and believe to be correct. If you go up a level and look at GET http://127.0.0.1:8080/restconf/data/tailf-ncs:devices/device=ios0, in this output you will see three “capability” sections. Of particular interest is this one:

<capability>
    <uri>urn:ios</uri>
    <revision>2015-03-16</revision>
    <module>tailf-ned-cisco-ios</module>
</capability>

Here the value in the uri tags matches the xmlns tags, and the value in the module tag matches the RESTCONF module namespace we need to use. This also appears to be listed in the config section. GET http://127.0.0.1:8080/restconf/data/tailf-ncs:devices/device=ios0/config/ at the end of the output is a couple modules listed:

<module>
    <name>tailf-ned-cisco-ios</name>
    <revision>2015-03-16</revision>
    <namespace>urn:ios</namespace>
    <conformance-type>implement</conformance-type>
</module>

In this output the namespace tag matches the xmlns, and the name tag matches the RESTCONF module namespace required.

Configuration Loopback Details

So, now that we know what name spaces to use we can drill down and look at individual components of the configuration.

We can look at the interfaces with GET http://127.0.0.1:8080/restconf/data/tailf-ncs:devices/device=ios0/config/tailf-ned-cisco-ios:interface

Using JSON we can look at just the Loopback interfaces with http://127.0.0.1:8080/restconf/data/tailf-ncs:devices/device=ios0/config/tailf-ned-cisco-ios:interface/Loopback. Trying this with XML content type however will generate an error, as this is a list of 4 interfaces.

We can look at a specific loopback using = and the name (or number) http://127.0.0.1:8080/restconf/data/tailf-ncs:devices/device=ios0/config/tailf-ned-cisco-ios:interface/Loopback=50

Following this format you can keep drilling until you get back a single element of data: http://127.0.0.1:8080/restconf/data/tailf-ncs:devices/device=ios0/config/tailf-ned-cisco-ios:interface/Loopback=50/ip/address/primary/address

Summary

In this post I explored reading the NSO RESTCONF API’s using Postman. I showed how the output varies using the XML vs JSON format. In my experience going through this I found the JSON format to be more intuitive and easier to follow. In the next post I will show how to use the API’s to add or delete devices and device configuration.

Sharing is caring!

2 comments

  1. Thanks a lot, Denis Pointer for creating this tutorial/walk-through. It cemented the concepts I learned about NSO through DevNet. Installing NSO (along with netsim) is a breeze using your container approach. I struggled to install netsim after natively installing NSO on my mac.

    We can collaborate and create further blogs on NSO use-cases and tutorials by doing ourselves in the lab first. Let me know if I can help.

    Thanks again Denis.

    1. Thanks for the feedback I’m happy it was able to help. I do have some more planned in this series going more in depth on API’s w/ postman and python, and bringing it into a lab environment such as GNS3

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.