At Cisco's GSX conference at the start of FY17, the DevNet team made a programming scavenger hunt by posting daily challenges that required using things like containers, Python, and RESTful APIs in Cisco software in order to solve puzzles. In order to submit an answer, the team created an API that contestants had to use (in effect creating another challenge that contestants had to solve).

This post contains the artifacts I created while solving some of the challenges.

Tools used:

  • Postman
  • Browser (for reading docs and such)
  • Python 2.7 (for Challenge 2)

Challenge 2: UCS Manager API

Your customer has been asked by their Help Desk Manager to make it easier on his first line engineers when requests come in related to UCS Server problems. Today, they have to train engineers on UCS Manager to get details like blade status, firmware levels, and uptime. He is asking how they could embed those details in their help desk system. Create some sample code leveraging the Python SDK for UCS Manager.

  • There is a Service Profile with a dn of org-root/ls-gsx-minihack1. Find its int_id.
Challenge 2 Answer

Challenge 5: ACI REST API

Congratulations! Your customer has selected ACI as their next generation data center network. Their application teams are looking forward to integrating infrastructure details into their deployment workflows. Demonstrate the ability to fully configure and administrate Application Policy via the REST API.

  • There is a Tenant in the sandbox called gsx-minihack that has a single Application Policy Configured. Determine the REST API call you would make to GET the details of that Application Policy.
Challenge 5 Answer

I admit, I did some weird reverse logic on this one. I'm not familiar with the APIC data model at all and had limited time, so I feel like I brute-forced this. This method wouldn't work in ‘real life'.

I used the APIC Visore Object Browser interface to quickly query APIC and figure out which API endpoint I needed to call. I did use the APIC Data Model Reference to find the class name for Application Profiles: fvAp.

Doing a query in the Visore for class fvAp gave a list of every single App Profile. I then did a quick search in the browser to find one that was a child of gsx-minihack by looking in the dn property.

APIC Visore Query

The resulting API endpoint is pretty simple to build: /api/node/mo/uni/tn-gsx-minihack/ap-DevNet-Rocks.json

Challenge 5 Results

Challenge 6: CMX RESTful API

A customer asks you demonstrate a few of the CMX 10.2 REST APIs to show how organizations can develop solutions that utilize real-time intelligence gathered from the Wi-Fi network to enable devices, people and technology to interact more effectively by integrating business processes with real-time contextual information about items such as location, temperature, availability of a user or mobile asset.

  1. What are the names of all the floors in the CMX system?
  2. What is the floor size of DevNetZone?
  3. How many access points are on the DevNetZone floor?
  4. How many active clients are on the floors?
  5. What is the specific location of client with macAddress 00:00:2a:01:00:05? Use the result of the mapCoordinate property as your answer. You will need to escape the JSON to submit.
Answer: Task 1

CMX has really good documentation for the API that can be accessed at http://CMX_IP/apidocs/. For task 1, I used the Configuration API docs to find the API endpoint to list all floor names: /api/config/v1/maps/floor/list and from there it was easy to plug into Postman.

Challenge 6a Query
Answer: Task 2

Same as before, I used the Configuration API docs and took a guess that if I queried the API for a specific floor, it might return information such as the floor's dimentions. The API endpoint to list a specific floor is /api/config/v1/maps/info/:campusName/:buildingName/:floorName so I queried /api/config/v1/maps/info/DevNetCampus/DevNetBuilding/DevNetZone and indeed got back the dimensions I was looking for!

Challenge 6b Query
Answer: Task 3

This one doesn't actually require using a different API endpoint. The data returned from the /api/config/v1/maps/info/DevNetCampus/DevNetBuilding/DevNetZone endpoint includes a list of APs on the floor. Counting the number of elements in the accessPoints list gives the correct answer.

Challenge 6c Query
Answer: Task 4

This one required looking at the Location API docs and focusing on the Active Clients API. Plugging /api/location/v2/clients/count into Postman reveals the answer.

Challenge 6d Query
Answer: Task 5

This again required the Location API and the Clients History API. There's a specific API endpoint that allows querying a client's location history by passing in the MAC address of the client. This endpoint can return thousands of rows, depending on how much location history CMX has stored for the client. The endpoint returns a list of objects, where each object describes the client's location at a given point in time. The trick with this task is to look at the first (ie, latest) object in the list and use the mapCoordinate property for the answer.

Challenge 6e Query

Now the task says to submit the entire property (which points to an object) in the answer and to do so, the object needs to be escaped so that the quotation marks don't cause a syntax error with the JSON you're using to submit the answer to the answer API.

{\"x\": 177.06102,\"y\": 48.294262,\"z\": 0,\"unit\": \"FEET\"}

Challenge 8: APIC REST API

Now that your customer has adopted ACI, the operations team is struggling to adapt to the change from traditional Cisco network operations. Show them the power of programmability with ACI by quickly generating a full inventory report of the entire fabric.

  • Create a REST API call that will return a list of all switches (spines and leaves) in configured in the fabric.
Challenge 8 Answer

If you use the APIC Visore Object Browser (http://CONTROLLER/visore.htm) it actually defaults to showing an inventory list as soon as you load it. The call it uses is /api/node/class/fabricNode.xml. Now that's cool but it also includes the APIC controller in the results. The instructions specifically say to return a list of all switches so I wanted to find a way to filter the results from this API call.

Fortunately APIC provides such a facility. By using the filter boxes at the top of the Visore page, you can get the syntax for filtering the returned data:

/api/node/class/fabricNode.xml?query-target-filter=and(eq(fabricNode.role,"spine"))
Challenge 8 Visore Filtering

Now this filter isn't quite right since it's only looking for a spine, but with some manipulation we can get a list of spines and leaves.

/api/node/class/fabricNode.xml?query-target-filter=or(eq(fabricNode.role,"spine"),eq(fabricNode.role,"leaf"))
Challenge 7 List of Switches

Side note: to have APIC return the data in JSON format, change fabricNode.xml to fabricNode.json.

Challenge 8 Official Answer

The answer posted by the DevNet team used a different API call, choosing instead to query the list of DHCP clients and filter for spines/leaves. Both calls return very similar data.

/api/node/class/topology/pod-1/node-1/dhcpClient.json?query-target-filter=or(eq(dhcpClient.nodeRole,"leaf"),eq(dhcpClient.nodeRole,"spine"),eq(dhcpClient.nodeRole,"unsupported"))

Challenge 9: APIC-EM REST API

Can APIC-EM be used to display a network topology? Yes it can! Your job is to prove how it's done via the APIs.

  1. Give the IP of the host that connects to switch Campus-Access1
  2. Explain which APIs you used to figure it out
Challenge 9 Answer

Use the /network-device API endpoint to get a list of switches; find the switch with hostname CAMPUS-Access1 and note its id property (24ac6aa8-7759-44d5-90a3-00c83e96583d).

Challenge 9, List of Switches

Then use the /host API endpoint and find the host with connectedNetworkDeviceId equal to the network-device id and find the host's IP address of 212.1.10.20.

Challenge 9, IP of Host
Challenge 9 Official Answer

The official answer from the DevNet team was to use the <span class="font-size-medium author-219237064 font-color-000000">/topology/physical-topology</span> API endpoint. Similar to my answer above, you need to look up the id of the switch (24ac6aa8-7759-44d5-90a3-00c83e96583d) in the links array to find the link that goes to the host.

I'm not really sure how you'd determine which link in the array goes to a host and which goes to a switch without doing a lot of cross referencing amoung the endPointID values and the node id. By just looking at it, this one was the best candidate:

{
 "source": "24ac6aa8-7759-44d5-90a3-00c83e96583d",
 "startPortID": "81373176-c263-4284-9970-1cb5d72414fa",
 "target": "12f9c920-24fa-4d32-bf39-4c63813aecd8",
 "linkStatus": "UP"
}

This target translates to this object in the node list:

{
 "deviceType": "wired",
 "label": "212.1.10.20",
 "ip": "212.1.10.20",
 "nodeType": "HOST",
 "family": "WIRED",
 "role": "HOST",
 "customParam": {},
 "id": "12f9c920-24fa-4d32-bf39-4c63813aecd8"
}

From this we get the same IP address as above, 212.1.10.20.

Reference Material


Disclaimer: The opinions and information expressed in this blog article are my own and not necessarily those of Cisco Systems.