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

APIC-EM 1.3 Update – Part 1 - PnP Templates

8293
Views
21
Helpful
24
Comments
Cisco Employee

Background

This blog series covers some of the new API released as part of the APIC-EM 1.3 release of code.

apic-logo.png

This particular blog covers a new feature in the Plug and Play (PnP) application, configuration templates.  Prior to version 1.3, the configuration file was a text file and did not support variables. If you wanted to use a template you needed to use Prime Infrastructure.  In APIC-EM 1.3, template support has been added.

This blog looks at both the UI and API required for templates.

For all of these examples I am using a 3650 switch running 3.6.5 code, but you could use versions of 16.3.1 and 3.7.4 (For other platforms such 2960x please see release notes for details).

Setup

I am going to assume you have seen my earlier blogs Network Automation with Plug and Play (PnP) – Part 1 on the mechanics of PnP and how to configure discover (DHCP, DNS) etc.

image1.png

Templates

A template is identical to a standard configuration file, except it has variables embedded in it. Templates use the "velocity" template language, the same as Prime Infrastructure.  Variables start with the "$" character.  For example there is a "hostname" variable in this example.

hostname $hostname

enable password xxx

!

username sdn password 0 xxx

!

ip http server

ip http secure-server

snmp-server community xxxx RO

!

line con 0

line vty 0 15 

login local 

transport input ssh telnet

end

When you view the template in APIC-EM, there are three views:

  1. Text view: the file above.  Variables have a "$" at the start
  2. Form View: just shows the variables.
  3. Preview: Shows the complete configuration with variables filled in.

template view.png

Templates can be uploaded the same as any other configuration file, through the user interface or the API.

Using the Template – User Interface

Templates are used in PnP rules in exactly the same way as normal configuration files.  One extra step is to fill in the variables. In this example I am going to use a pre-defined rule, but templates work with unclaimed devices as well.

NOTE: You do not need a specific suffix on a template file.  The controller searches the configuration file for variables, and if they are present, the file is treated as a template.

template-view.png

I then need to select the "Form View" to fill in the variables.  This example has only one variable "hostname"

fill-in-template.png

I then need to select "Device Configuration" and scroll down to the bottom of the page to "Add" the Device. 

NOTE: I have also configured some stack parameters.  These are only required as I am also using a stack of switches.

add-rule.png

Now the rule has been added successfully.

final-rule.png

Once the switch has been provisioned you will notice the configuration file has changed.  This will be the rendered template with all of the variables filled in.

final.png

Using the Template – User Interface

In this section I will cover the API that are required to use the template API.  I am going to assume you have seen my earlier blogs for a detailed description of using the PnP API.

  I have already created a project and uploaded the configuration file.  This was covered in an earlier blog Network Automation with Plug and Play (PnP) – Part 2


Templates require two new API "/template" and "/template-config" as shown below:

relationships-api.png

Here is the API call to get the "id" for the template file "3650-dhcp-template.txt".

https://adam-iwan/api/v1/pnp-file/config?name=3650-dhcp-template.txt GET

{

      "nameSpace": "config",

      "name": "3650-dhcp-template.txt",

      "downloadPath": "/file/e8682c6f-e9f7-425b-a8a7-08f37ee2bb2d",

      "fileSize": "281",

      "fileFormat": "text/plain",

      "md5Checksum": "4a733185281e17e15228d5636c921308",

      "sha1Checksum": "0bccd2be238ed74e283c198af1ed7b4291717ce3",

      "id": "e8682c6f-e9f7-425b-a8a7-08f37ee2bb2d"

      },

Configuration files that are templates will have an entry in template table.  I  need to find the template UUID from the fileId (e8682c6f-e9f7-425b-a8a7-08f37ee2bb2d).

https://adam-iwan/api/v1/template?fileId=e8682c6f-e9f7-425b-a8a7-08f37ee2bb2d   GET

{

"response": [

{

      "fileId": "e8682c6f-e9f7-425b-a8a7-08f37ee2bb2d",

      "id": "d1fd02d0-c9cf-4fad-b706-1332a891ca18"

}

],

The next step is to create a configuration file from the template. I use the UUID of the template (d1fd02d0-c9cf-4fad-b706-1332a891ca18) obtained above.

https://adam-iwan/api/v1/template-config  POST

[{"templateId":"d1fd02d0-c9cf-4fad-b706-1332a891ca18", "configProperty":{"hostname":"stack-template"}}]

Because this is an asynchronous operation, a task will be returned.

{

"response": {

"taskId": "8a82c03f-b746-41e6-b7b1-23be1c552ebe",

"url": "/api/v1/task/8a82c03f-b746-41e6-b7b1-23be1c552ebe"

},

"version": "1.0"

}

I need to poll the status of the task (8a82c03f-b746-41e6-b7b1-23be1c552ebe") and get the UUID of the rendered template (13c6b9cf-f91c-429d-8489-46d81263d1a2)

https://adam-iwan/api/v1/task/8a82c03f-b746-41e6-b7b1-23be1c552ebe   GET

{

"response": {

"startTime": 1477824534405,

"endTime": 1477824534424,

"version": 1477824534405,

"progress": "{\"message\":\"Successfully added the Ztd Template Config\",\"id\":\"13c6b9cf-f91c-429d-8489-46d81263d1a2\"}",

"serviceType": "Ztd Service",

"isError": false,

"rootId": "8a82c03f-b746-41e6-b7b1-23be1c552ebe",

"id": "8a82c03f-b746-41e6-b7b1-23be1c552ebe"

},

"version": "1.0"

}

I have successfully created a new template with the variable hostname":"stack-template"

In order to create a rule in the project (named "template), I also need the UUID of the project.

https://adam-iwan/api/v1/pnp-project?siteName=template  GET

{

      "state": "PRE_PROVISIONED",

      "siteName": "template",

      "tftpServer": "",

      "tftpPath": "",

      "deviceCount": 0,

      "pendingDeviceCount": 0,

      "provisionedBy": "admin",

      "provisionedOn": "2016-10-29 02:35:26",

      "id": "d168aa1a-bf61-46c9-b5d6-7ae4e27c48c8"

}

I can now create a rule in my project using the configuration template i created earlier.  The items in red, are specifically for a stack deployment.

https://adam-iwan/api/v1/pnp-project/d168aa1a-bf61-46c9-b5d6-7ae4e27c48c8/device POST

[{

"hostName":"switch",

"platformId":"WS-C3650-48FQ",

"serialNumber":"FDO1735Q0G5",

"pkiEnabled":"false",

"sudiRequired":"false",

"templateConfigId":"13c6b9cf-f91c-429d-8489-46d81263d1a2",

"memberCount":"2",

"licenseLevel":"ipservices",

"eulaAccepted":"true"

}]

Again, get the task body to see the task was successful.  This also returns the UUID of the newly created rule.

https://adam-iwan/api/v1/task/9ba76c24-4db1-44f4-a9bd-e3f8b6507e33 GET

{

"response": {

"startTime": 1477824968481,

"endTime": 1477824968527,

"version": 1477824968481,

"progress": "{\"message\":\"Success creating new site device(rule)\",\"ruleId\":\"234f2700-62b2-4721-8780-a6ccb79900e0\"}",

"serviceType": "Ztd Service",

"isError": false,

"rootId": "9ba76c24-4db1-44f4-a9bd-e3f8b6507e33",

"id": "9ba76c24-4db1-44f4-a9bd-e3f8b6507e33"

},

"version": "1.0"

}

The User Interface shows the rule has been defined successfully.

api-provisioning.png

This can be also be verified through an API call:  NOTE: the "templateConfigId": and the ruleID which matches that returned by the task above (234f2700-62b2-4721-8780-a6ccb79900e0)

https://adam-iwan/api/v1/pnp-project/d168aa1a-bf61-46c9-b5d6-7ae4e27c48c8/device   GET

{

"response": [

{

      "hostName": "switch",

      "platformId": "WS-C3650-48FQ",

      "serialNumber": "FDO1735Q0G5",

      "site": "template",

      "templateConfigId": "13c6b9cf-f91c-429d-8489-46d81263d1a2",

      "pkiEnabled": false,

      "sudiRequired": false,

      "apCount": "0",

      "isMobilityController": "false",

      "memberCount": 2,

      "licenseLevel": "ipservices",

      "eulaAccepted": true,

      "state": "PENDING",

      "stateDisplay": "Pending",

      "authStatus": {

        "type": "Unknown",

        "status": "None",

        "errorMessage": null,

        "timestamp": 1477824995539,

        "certInfo": null

      },

      "aliases": [],

      "id": "234f2700-62b2-4721-8780-a6ccb79900e0"

}

],

"version": "1.0"

Summary

Here is a summary of the API calls above. NOTE the section in RED is the only difference compared to a standard configuration file.

summary-api.png

What Next?

This blog covered configuration templates for PnP, native in APIC-EM.  My next blog will cover some of the new EasyQoS API.

In the meantime, if you would like to learn more about this, you could come hang out with us in The Cisco Devnet DNA Community. We’ll have a continuous stream of blogs like this and you can ask questions and we’ll get you answers.  In addition, we have a Github repository where you can get examples related to PnP.

Thanks for reading,

  @adamradford123

24 Comments
Enthusiast

If you enter this in the template:

#foreach ($foo in $bar)
  $foo
#end


How would the form view react?  What about requiring a list of hashes for a given object?


Beginner

Hi Adam,

Thanks for this article. I am brand new in APIC-EM world, I played a bit with Ansible and templates, and I am wondering if templates in apic-em could support on the fly if, for loops statements ? I have plenty of templates in j2 I would like to use, but inside are lots of variables calculation and if,else.... What are my possiblities to integrate this with apic-em. I like the way to be able to put in the "form view" the values of the variables, but what about "calculating" dynamically other variables.

Thanks for your help,

Olivier

Cisco Employee

Thanks Jason,

we only support basic constructs are present.  For example the following.  More sophisticated are in the works

#foreach($i in [1..4])

    $i

#end

Cisco Employee

Hi Oliver,

only basic constructs like the following right now.  More sophisticated are in the works

#foreach($i in [1..4])

    $i

#end

Beginner

Hi Adam,

Thanks,  I got it. Thanks to your scripts I got now the possibility to include my ansible templates into Apic-em. Works like a charm

I just would like to know which parameter I can "tune" to assign the default IOS image to the device when I create the rule. I found imageID, imagePreference, but I don't know exactly what to do with

Many thanks again for your help,

Regards,

Olivier

Cisco Employee

Hi Oliver,

imageId is used to download an IOS image to the device.  You upload the IOS image to file/image (via POST, just the same as you would /file/config).

When the device contacts the controller, if it is running an IOS image other than the one that is specified, it is upgraded.

Adam

Cisco Employee

BTW, If you just use API and not UI, advanced templates are supported.

I can give some examples if you wish?

Cisco Employee

BTW, If you just use API and not UI, advanced templates are supported.

I can give some examples if you wish?

Beginner

Well I thought more about having already uploaded the images, they are configured to match certain types of device's model, and then, when creating the rule via API, just "assigning" the default image to the device. Is there a parameter "default" I can use, or should I gather first the name of the bin image and push it into the script ?

This would be more difficult to do as I have to do some "if... else..." blabla to assign the right IOS image.

Regarding the "advanced" templates, I think I have already some quite complicated ^^. I will keep them and as you said, I will continue using the API to ppopulate the APIC COnfig, so I can keep these templates

Cisco Employee

Oh yes, you can have a default image for devices too.

/pnp-file/image  will take a list of platforms.

for example - to provide a default image for the following 1900 router platforms:

POST api/v1/pnp-file/image

  1. [{"imageId":"dd76d5aa-f1b3-4ec9-a1dc-83f4509c4859","platform":[{"platformName":"ISR1900","productId":["C1921-4G-V-SEC/K9","C1921-4SHDSL-EA/K9","C1921-AX/K9","C1921-VA/K9","C1921VAM/K9","CISCO1921-SEC/K9","CISCO1921-T1SEC/K9","CISCO1921/K9","CISCO1921DC/K9","CISCO1941/K9","CISCO1941W-A/K9","CISCO1941W-C/K9","CISCO1941W-I/K9","CISCO1941W-N/K9","CISCO1941W-P/K9","CISCO1941W-T/K9"]}]}]
Beginner

OK I wrote a list_images.py based on your list_files.py script, and adapt the create_rules.py to send this parameter with. I tested with a C2960X switch and works perfectly.

Now I face an issue with a C2921 router. This bloody device has CCP installed from factory, and it seems that it doesn't do pnp. I don't find any information about this case. I don't want to have to change any "boostrap" config with a console cable Have you already seen such issue ? otherwise I will call the TAC ^^

Beginner

well you know what ? forget the question about CCP... I will simply buy future routers without it I found in the ordering SKUs the line I have to change to get a brand new Cisco router without this piece of (crap) software on it

Last but not least: Many thanks for your great help and your great work !!! I'll keep an eye on your future posts !

Cisco Employee

Sorry Olivier,

CCP is not compatible with PnP. 

I have asked the team to document this.

Beginner

Hi Adam,

me again...

I got an issue buy upgrading stack switches. It seems that the update takes longer as the 40min timeout set in APIC-EM... bad. Anyway I currently create rules for standalone switches, and I wanted to manually update one of the rule to add stack config like license, number of Sw in stack and EULA agreement, but this doesn't work. (I thought taht maybe with stack config the timeout value would be higher... who knows...:)

But I got a message that EULA agreement failed, even if I click it.... any idea why ? is there a mechanism which blocks update if we primarily created the device's rule by API ?

Thanks

Cisco Employee

Hi Oliver,

yes today the upgrade timeout is 40mins.

for the stack conversion, are you using the UI to do this?  I think there is a bug which i have asked the team to address.  For some reason the UI leaves out the eulaAccepted parameter.

You can do this via API and it should work.

<project-id> and <device-id> will be specific to your environment...

https://adam-iwan/apic/api/v1/pnp-project/<project-id>/device PUT

[{

"id" : <device-id>,

"memberCount":"2",

"licenseLevel":"ipservices",

"eulaAccepted":"true"

}]

Content for Community-Ad
June's Community Spotlight Awards
This widget could not be displayed.