The cool way to deploy a template on the DNA Center!
- Marco
- May 6, 2022
- 4 min read
Updated: May 11, 2022

I like the template Editor from the DNA Center a lot. Especially if you use the DNA-C as a central controller without a fabric. But even with a SDA fabric, this tool still comes in handy in my opinion.
If you are not familiar with this topic or you want to refresh you knowledge, there is a great how-to series from Adam Radford.
For me this is the best explanation out there! Thank you Adam for this great work!
As a beginner, the GUI is just perfect. Especially if you want to push certain configuration to one kind of devices. For example if you want to configure MacSec within your whole fabric. (let me know if i should share this script here!)
The thing i don´t like much about it is the handling. You need to define tags, create network profiles to bind the template to a site/floor and so on. You can only have one day-n profile per device-type and site. If you want to have multiple switching template for instance, you have to work a lot with tags. These tags have to match with the inventory and every time you want to use the template, you have to redeploy the device. A lot of work if you only want to configure one or a few devices.
configuration example:
And what if you want to use variables defined outside the DNA Center?
Let me show you my favorite way!
the magic happens with the API. It is possible to push variables with the API call and yes, you don´t need any network profiles and tags!
But as a beginner it is not easy to understand. At least in my case.
First of all lets have a look in the docs:

Too keep it as simple as possible, i want to focus on the mandatory fields.
In the targetInfo i will tell the API which device i want to configure.
What kind of information for this task is used is defined in the type. The two most common are MANAGED_DEVICE_IP and MANAGED_DEVICE_HOSTNAME. If you choose hostname,you have to use the hostName field. If you want to use the management ip then... wait? there is nothing stated, but you can use the id field :)
The next step is to search for the UUID of my desired template. Because it does not change, i like to use postman because it is simple and fast.
if you do not have the collections yet, here:
Use the API to list all templates and their informations:
https://{{dnac}}/dna/intent/api/v1/template-programmer/template
search the response for:
"name": "set_hostnames", "projectName": "MarcoK", "projectId": "17873fb2-9426-46da-ad0a-c0f59eb64b65", "templateId": "c3907c9a-ec89-4c4d-8409-872747e5fb5d",
The last required part for this is the params.
For this i configured a dictionary. The keys have to match the variable name within the velocity template. As value a String is required.
'params' : {
'hostname':'switch1',
'domain':'labor.local',
'Mgmt_IP':'192.168.1.250'
}
Let´s try it out!
Create a simple template

Next we figure out the UUID with the help of Postman. Get the Management IP of my desired device and write some python code! I´m using the DNA SDK.
import credentials
from dnacentersdk import api
if __name__ == '__main__':
#Login to the DNA Center and get an access Token
api = api.DNACenterAPI(username=credentials.username,
password=credentials.password, base_url=credentials.base_url,
version='2.2.3.3', verify=False)
TemplateID='5d65f782-8076-4d56-9c98-7b87359bb82e'
DeviceIP='10.76.0.3'
'''
the sdk needs a list. So we build a list but with only a dict.
define in "type" that the given id is the Device Management IP found
in the DNAC inventory. you can also use different ids. Refer to the
doc. within the params define the variables. the dict key-value has to
match with the variable name in the DNAC velocity template
'''
targetinfo = [
{
'id':DeviceIP,
'params': {
'banner':'# you did it mo***er !#'
},
'type': 'MANAGED_DEVICE_IP'
}
]
#use API
api.configuration_templates.deploy_template_v2(templateId=TemplateID,
targetInfo=targetinfo)
checking the result:

great!
Just one last thing to consider. The API allows only a String as the Value. No list!
So how can we do some bulk imports?
I generally merge all values into a CSV, transfer it via the API and split it back again.
In my example i want to deploy multiple Vlans and give them a name.
As data source i will use a spreadsheet.

A sneak peak in the template editor:
The variables are vlans and names in the python script and ";" is the delimiter. Split the CSV in a list and loop through all entries.
I want to execute the template only if every Vlan ID has a name in the spreadsheet. For this reason i compare if both lists are the same length. If not, don´t start the script. At this stage i have no data validation.
#set ($vlan_list = $vlans.split(;))
#set ($vlanlist_length = $vlan_list.size())
#set ($name_list = $names.split(;))
#set ($namelist_length = $name_list.size())
#if ($namelist_length!=$vlanlist_lenght)
#break
#end
#set ($list_length = $vlanlist_length - 1)
#foreach ($i in [0..$list_length])
vlan $vlan_list[$i]
name $name_list[$i]
#end
Again i´m using the DNA Center SDK and openpyxl for processing the spreadsheet.
#!/usr/bin/python
import credentials
import openpyxl
from dnacentersdk import api
this time a list is used instead of a singe IP to quickly adapt the task to multiple devices.
# Login to the DNA Center and geht an access Token
api = api.DNACenterAPI(username=credentials.username,
password=credentials.password, base_url=credentials.base_url,
version='2.2.3.3', verify=False)
#find out the Tamplate ID with Postman for example
TemplateID='c3907c9a-ec89-4c4d-8409-872747e5fb5d'
DeviceIPs=['10.76.0.3']
Now we need to read the spreadsheet. The first row contains the IDs, the second the names. I store the extracted data to a list to further process it later.
worksheet = openpyxl.load_workbook('vlans.xlsx').worksheets[0]
data=[]
VID=''
VName=''
for row in worksheet.iter_rows(values_only=True):
data.append(row)
Now we have all IDs in Index 0 and all names in Index 1.
The next step is to merging them into a CSV Value each.
for id in data[0]:
VID += str(id)
VID += ';'
for name in data[1]:
VName += name
VName += ';'
finally we can proceed as usual.
Loop through all IP Addresses defined in the DeviceIPs list (in this example only one).
for IP in DeviceIPs:
targetinfo = [
{
'id':IP,
'params': {
'vlans':VID,
'names':VName
},
'type': 'MANAGED_DEVICE_IP'
}
]
print(VID)
print(VName)
#use API
api.configuration_templates.deploy_template_v2(templateId=TemplateID, targetInfo=targetinfo)
et voila!

I hope i could give you a good idea of what is possible with this approach.
This is intended do give you some inspiration for your daily challenges.
Comments