Network Configuration Templating

In this post we'll create a configuration template using the Jinja2 web framework, define variables using a YAML file, and then use Python to render a configuration file.

What is Jinja2?

From Jinja2's website - "Jinja2 is a modern and designer-friendly templating language for Python, modelled after Django’s templates." We're going to create a very simple Cisco Nexus configuration file specifying our variables in Jinja2 expressions. For this exercise we will create a template consisting of hostname, motd banner, and necessary configuration for management access.

hostname {{ hostname }}

vrf context {{ management_vrf }}  
  ip route 0.0.0.0/0 {{ management_gateway }}

interface {{ management_interface }}  
  vrf member {{ management_vrf }}
  description {{ management_int_description }}
  ip address {{ management_ip }}

banner motd $  
Welcome to {{ hostname }} IP address: {{ management_ip }}  
$

In this basic Jinja2 template we defined our variables by the use of the double curly brackets. One thing I find beautiful about Jinja2 is you can define variables anywhere. This attribute of Jinja2 makes it very easy to grab a configuration file, replace unique information with a variable, and voila... a template is born. Let's save our template as NEXUS_BASE.j2.

YAML Ain't Markup Language

YAML provides an easy to read data structure language. For our exercise we'll use key: value pairs with the keys being the variables we defined in our Jinja2 template and the values being the unique data. A YAML file is defined by starting a text document with three hyphens:

---
hostname : N7K_1

management_vrf : management

management_gateway : 10.0.0.1

management_interface : management0

management_int_description : Out-of-Band Management Interface

management_ip : 10.0.0.100/24

As you can see in the file above, we've matched the same user defined variables in our Jinja2 template and then associated those keys with a value to populate into the template. We'll save this file as N7K_VARS.yaml.

Rendering Configuration

Now that we have our Jinja2 template and YAML file created, we can use their associated Python libraries to load and render the configuration file. For this example I'll be using Python 2.7.10. Be sure to install the Jinja2 and pyyaml packages if you would like to try this out:

from jinja2 import Template  
import yaml  
import sys  
import os.path

#Parse the YAML file and produce a Python dict.
yaml_vars = yaml.load(open('C:/VARIABLES/N7K_VARS.yaml').read())

#Load the Jinja2 template into a Python data structure.
template = Template(open('C:/TEMPLATES/NEXUS_BASE.j2').read())

#Render the configuration using the Jinja2 render method using yaml_vars as arg.
rendered_config = template.render(yaml_vars)

#Write the rendered configuration to a text file.
with open('C:/CONFIGS/N7K1_rendered_config.txt', 'w') as config:  
    config.write(rendered_config)

And now let's open our config file:

hostname N7K_1

vrf context management  
  ip route 0.0.0.0/0 10.0.0.1

interface management0  
  vrf member management
  description Out-of-Band Management Interface
  ip address 10.0.0.100/24

banner motd $  
Welcome to N7K_1 IP address: 10.0.0.100/24  
$

So that is the basic introduction to config templating using Jinja2 as our template framework, YAML as our data serialization format, and Python to tie it all together! In the future we'll cover some more useful Jinja2 delimeters such as statements and build a leaf spine network. Thanks for reading!