Variables
At the heart of any template is the concept of a “variable”. Variables allow parts of configuration to be customized for a specific device, while ensuring other parts are standardized across all devices. A single configuration template can be applied to many devices. In Velocity, variables begin with “$”. If you need to have a variable embedded in a string, you can use ${var} to denote the variable.
To configure a hostname for a network device, the cli command “hostname adam-router” is used. “adam-router” is the name of the device. When applying this template to a set of devices, the only thing that changes is the variable (${hname}). By setting the variable hname = “adam”, “adam-router” would be rendered.
hostname ${hname}-router
Bound Variables
It is possible to access information about the device (from DNAC perspective) using a binding. Attributes about the device, such as it’s model number can by linked to a variable. For example in the following template I want to set ${device} to the device product ID (PID) from the inventory.
hostname ${hname}-${device}
When the template is defined in template programmer, click on the variable section.
Selecting the Variables for Template
Then click the variable (device) and bind to source (bottom right). Select Source = “Inventory”, Entity = “Device” and Attribute = “platformId”. This indicates this variable should come from the inventory, specifically data about the device. The attribute is optional, but in this case just the “platformId” (model number) is required. For a stack this will be a comma separated list.
Binding the Variable
This will render as hostname adam-WS-C3650-48PQ-E when applied to a 3650 switch.
Conditionals
Most programming languages provide if-else constructs. In Velocity, this is simple, #if #end statements denote a simple condition. There are a number of use cases for if statements.
Optional Variables
Sometimes a variable may be optional, and the configuration line should only be rendered if the variable is set. In the example below, if the $data_vlan variable is empty, the vlan configuration would be skipped
#if($data_vlan != "")
vlan $data_vlan
name userdata
#end
Related Variables
Based on one variable, you may want to set some others. This reduces the number of variables needed in the template. #set is used to assign a variable. In the example below, if the value of $hostname is “switch01” then the variable $loopback is set to “10.10.100.1”.
#if ($hostname == "switch01")
#set ($loopback = "10.10.100.1")
#elseif ($hostname == "switch02")
#set ($loopback = "10.10.100.2")
#end
int lo0
ip address $loopback 255.255.255.255
Enable/Disable Trigger
Another example is to trigger a feature to be either enabled or disabled. For example, a variable could be used to toggle enabling/disabling netflow. To simplify the example, assume the definition of the netflow collector is also in the template. The interface name could also be a variable. In this example “apply” is set to “true” to enable netflow on the interface, and anything else will disable netflow.
int g1/0/10
;#if ($apply == "true")
ip flow monitor myflow input
#else
no ip flow monitor myflow input
#end
Regular Expressions
The if statements above showed an exact match of a string. How would a pattern match be done? Fortunately, regular expression (regexp) are supported. A detailed discussion of regexp is outside the scope of this post, as there are lots of other places to find tutorials on regexp.
For example, a single template could do something specific for 9300 switches and still be applied to non-9300 switches. The model number of the switch (from the inventory) is available via a bound variable. As seen in the section above. 9300 series switches have a model number structured as 9300-NNXXX or 9300L-NNXXX-YY. For example, C9300-24UB, C9300-48UXM, C9300L-24P-4G.
The regular expression is “C9300L?-[2|4][4|8].*”. The first part is just a string match “C9300”. The “L?” means “L” is optional, sometimes it is present, sometimes not. “-” is just a match. “[2|4]” means either 2 or 4, and the same with “[4|8]”. Finally, “.*” matches any remaining letters. The variable is $model and $model.matches() will return true is the regular expression matches.
#if ($model.matches("C9300L?-[2|4][4|8].*") )
#set ($var = "9300")
#end
The other way regular expressions can be used is to replace parts of a string. In this example, I want to extract the number of ports on the switch from the model number.
I am using “replaceAll” vs “match”. ReplaceAll takes a regular expression, as well as an argument to specify what to replace it with. In this case “$1” is going to replace the contents of the regular expression. The regular expression is identical to above, with one difference “([2|4][4|8])“. The () saves the pattern inside, and it can be later referenced as “$1”. This pattern is the number of ports. It will match 24 or 48. $ports would be set to either 24 or 48.
#set($ports = $model.replaceAll("C9300L?-([2|4][4|8]).*","$1"))
$ports
If $model = ” C9300L-24P-4G”, then $ports will be set to 24.