cancel
Showing results for 
Search instead for 
Did you mean: 
cancel

Cisco DNA Center APIs -- Initial Exploration

15419
Views
1
Helpful
0
Comments
Cisco Employee

So what?

Maybe you already have your own DNA Center. Maybe you're wondering how, or why to leverage the APIs it supports?

I was thinking the same thing you are --> It better support APIs! OK, then onto the next thought; so what?

I decided to explore a bit. From a bit of discovery with APIs referenced on Devnet for DNA Center, I took notice of the thing called "SWIM". I knew that was a new thing in DNAC, and I also knew of others that wished it could do two more things:

  1. Delete images from network devices.
  2. Add images to network devices for preparation of upgrade later.

It sounds simple, I know. That's OK, I learned that the "Image Repository" application in DNA Center could do many things, that I won't go into details on here. Let's just say it integrates with images available from cisco.com, tags images, helps me upgrade network devices, etc. This maps to the "SWIM" section of the API docs overall. But at the end of the day, I (like some others) couldn't find a way to delete files or add files to individual network devices.

APIs to the Rescue?

Delete an image from a device

OK, so let's go for it. I knew how to login, but not much else. Well, first thing I find (in the "SWIM" section) is an API that might do the job:

/device-image/device/{id}file/{name}

Could it be that simple? OK, so I went and explored how to ascertain the "{id}" and "{name}" I'd need, but here's a literal example:

/network-device 

There's many other places I can get id's of network devices. But I nabbed this response for the Catalyst 3850 I was interested in:

{
  "response": [
  {
  "type": "Cisco Catalyst38xx stack-able ethernet switch",
  "location": null,
  "errorCode": null,
  "family": "Switches and Hubs",
  "tagCount": "0",
  "lastUpdateTime": 1515531756909,
  "softwareType": "IOS-XE",
  "lastUpdated": "2018-01-09 21:02:36",
  "inventoryStatusDetail": "<status><general code=\"SUCCESS\"/></status>",
  "locationName": null,
  "role": "ACCESS",
  "upTime": "43 days, 6:17:40.18",
  "roleSource": "AUTO",
  "snmpLocation": "",
  "tunnelUdpPort": null,
  "waasDeviceMode": null,
  "errorDescription": null,
  "serialNumber": "FOC2008X01Q",
  "softwareVersion": "16.6.2",
  "hostname": "o22-3850-1.cisco.com",
  "apManagerInterfaceIp": "",
  "associatedWlcIp": "",
  "bootDateTime": "2017-11-27 14:42:56",
  "collectionStatus": "Managed",
  "interfaceCount": "59",
  "lineCardCount": "1",
  "lineCardId": "02a7418a-e22c-431e-bca4-b7018a630faa",
  "managementIpAddress": "172.26.170.252",
  "memorySize": "873743704",
  "platformId": "WS-C3850-48U-L",
  "reachabilityFailureReason": "",
  "reachabilityStatus": "Reachable",
  "series": "Cisco Catalyst 3850 Series Ethernet Stackable Switch",
  "snmpContact": "",
  "collectionInterval": "Global Default",
  "macAddress": "00:cc:fc:68:87:80",
  "instanceUuid": "3d4c1d21-94c5-4164-986c-8aff71fb305e",
  "id": "3d4c1d21-94c5-4164-986c-8aff71fb305e"
  }
  ],
  "version": "1.0"
}

See "id": "3d4c1d21-94c5-4164-986c-8aff71fb305e". OK, moving on. Now for the "{name}" .. hmm. Well, look there. Something called "Lists files on a device". OK, I knew the device above contained the image I wanted to delete, and I could have guessed the name but I need determinism. Let's give it a shot (and use the learned id from before):

/device-image/device/3d4c1d21-94c5-4164-986c-8aff71fb305e/file

Yep, that's a bunch of data, so I'm interested in filtering, but let's do that later. Here's a subset of what I got back:

{
  "fileName": "cat3k_caa-universalk9.16.03.05b.SPA.bin",
  "fileSize": "539622403",
  "imageLocation": "flash",
  "fileType": "UNKNOWN",
  "fileStatus": "VALID"
},

See "id": "cat3k_caa-universalk9.16.03.05b.SPA.bin". OK, moving on.

Putting it together

Can I do this in a single API call? Yep:

DELETE /api/v1/device-image/device/3d4c1d21-94c5-4164-986c-8aff71fb305e/file/cat3k_caa-universalk9.16.03.05b.SPA.bin HTTP/1.1

Host: 172.26.170.4:443
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 9c964d21-2895-d8bf-d37d-095858316546

I got a 202 back (I'm using Postman), but it also gave me a JSON response. Like this:

{
  "response": {
  "taskId": "6c6da211-7cf2-4436-9c5b-ca3dc101e6e0",
  "url": "/api/v1/task/6c6da211-7cf2-4436-9c5b-ca3dc101e6e0"
  },
  "version": "1.0"
}

OK, so click that (the url bit)! Wow, postman does the right thing for you here. OK, what's that say?

{
  "response": {
  "version": 1515529765265,
  "data": "delete-image-device",
  "startTime": 1515529765265,
  "endTime": 1515529766709,
  "isError": false,
  "progress": "completed successfully. Success = 1, Failure = 0, Running = 0, Pending = 0, Total = 1",
  "serviceType": "Swim Service",
  "rootId": "6c6da211-7cf2-4436-9c5b-ca3dc101e6e0",
  "id": "6c6da211-7cf2-4436-9c5b-ca3dc101e6e0"
  },
  "version": "1.0"
}

Hmm, so is the image really no longer on my device? I can verify this in CLI all day. Dang, it worked. No big script to write. No providers or credentials to define. No send/expect. 1 API with data, and I'm done. I can already see ways to turn this into Python with some logic to learn from DNAC. I could use Python to extend this and clean up old images not in use to prepare for a fleet upgrade to my golden image. For example, which devices are running which images, at which sites, and if devices are not running the images I want to delete, then I can wipe them out easily.

Add an image to a device

OK, I was on a roll. There's something called "Trigger now or schedule distribution of an image". I would try it directly, but the docs say it needs data:

/image/distribution

[
{
"deviceUuid": "",
"imageUuid": ""
}
]

Well hey, I already know my device id. I just need the imageUuid. Hmm, look there "Get image details with filter". OK, try it. 200 with data. Once again, filtering is a good idea, but here's the image I want everywhere:

"imageUuid": "d3b3ed6e-b453-4403-8462-e2bac32e882d", "name": "cat3k_caa-universalk9.16.06.02.SPA.bin", 
Putting it together

Can I do this in a single API call? Yep:

POST /api/v1/image/distribution HTTP/1.1
Host: 172.26.170.4:443
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 63ccca96-bcea-8ca7-ce62-e97805ac4726

[
{
"deviceUuid": "3d4c1d21-94c5-4164-986c-8aff71fb305e",
"imageUuid": "d3b3ed6e-b453-4403-8462-e2bac32e882d"
}
]

Once again, there's a 202 with data.

{
  "response": {
  "version": 1515537544734,
  "startTime": 1515537544664,
  "endTime": 1515537952867,
  "isError": false,
  "lastUpdate": 1515537544734,
  "progress": "completed successfully. Success = 1, Failure = 0, Running = 0, Pending = 0, Total = 1",
  "serviceType": "Swim Service",
  "rootId": "be978bd7-27ed-4ce2-8cc7-8f2400bac974",
  "additionalStatusURL": "/api/v1/image/task?taskUuid=be978bd7-27ed-4ce2-8cc7-8f2400bac974",
  "id": "be978bd7-27ed-4ce2-8cc7-8f2400bac974"
  },
  "version": "1.0"
}

I can imagine more possibilities now. Integrating with the testing facilities in postman, Python. Did it work? Sure did. The image isn't tiny either, which explains the time delta above. The best part is, DNA Center allowed me to just focus on my outcome. If there was not enough free space in bootflash, or anything else on my device, it would have told me. It made me not have to care so much (which would means I'd probably have to write a script to deal with this too).

This was cool to learn through exploration. The APIs on DNA Center are evolving, but take a look at what's there now. You might find that APIs can help you integrate some of your ideas or use cases as well.