Table of Contents

Python Jinja2 template also has loops, conditionals, and some other features in addition to the variable substitution discussed in the previous section.

In this section, we demonstrate a jinja2 configuration template with all these features.

Python Jinja2 Template Fundamental

Usually, when we send the configuration to multiple devices, the configuration of the devices are not exactly the same and some configuration data may be different for network devices.

Jinja2 Template Application
Jinja2 Template Application

For example, the network number in the routing protocol, the access rules in the access list, and the AS number are some of the configuration data that are usually different among network devices.

With jinja2 Template we can generate a single configuration template in which variables are used instead of configuration data.

When the configuration template is applied to the network devices, the variables are replaced with configuration data related to each device which is retrieved from the automation data structure.

But unlike the example demonstrated in the previous section, variable substitution alone cannot always produce an efficient configuration template.

In this simple example of OSPF configuration in device1 and device2, I used a “for loop” in addition to “variable substitution” to generate an efficient configuration template that covers the OSPF configuration of both devices.

This figure shows the main features of the jinja2 template.

python Jinja2 Configuration Template Features
python Jinja2 Configuration Template Features

In variable substitution, we use variables in the place of configuration data that differ between network devices.

With condition we can apply a configuration based on a condition, for example, version number of the operating system, the routing protocol used in network device, AS number of the device, the device vendor and many other conditions.

With loop, as we saw in the example, we can iterate through something like access rules in the access list, or network numbers is a routing protocol.

You will find the most advanced features of the jinja2 template on this website, which is highly recommended. Here are many practical examples of the jinja2 template’s capabilities.

Review Inventory Files

Before we check the automation script and the jinja2 configuration template example, let’s review the inventory files and the Nornir data structure.

They’re just like the previous section and don’t need any further explanation, but let’s just go through them quickly once again.

There is only one device, “R1”, configured within “hosts.yaml” that is part of the “cisco” group.

The files “groups.yaml” and “defaults.yaml” are as usual and there is nothing special to talk about.

majid@devnet:~/devnet/pyhton_nornir/2023/10.jinja2_template$ cat hosts.yaml
---

R1:
  hostname: "192.168.2.91"
  username: "rayka"
  password: "rayka-co.com"
  groups:
    - cisco
	
majid@devnet:~/devnet/pyhton_nornir/2023/10.jinja2_template$ cat groups.yaml
---

cisco:
  platform: ios

majid@devnet:~/devnet/pyhton_nornir/2023/10.jinja2_template$ cat defaults.yaml
---

username: "rayka"
platform: "ios"

Review Configuration Data

The Nornir data structure is exactly what we talked about in the previous section.

We have three files, “R1.yaml” in the “host_vars” directory, which contain configuration data for the R1 router. “cisco.yaml” and “all.yaml” within “group_vars” directory keep the configuration data shared between devices within the cisco group and between all devices.

majid@devnet:~/devnet/pyhton_nornir/2023/10.jinja2_template$ cat host_vars/R1.yaml
---

snmp:
  community: "rayka"
ntp:
  server: 1.1.1.1
  servers:
    - 1.1.1.1
    - 11.11.11.11
  authentication:
    hash: md5
    key:
      - rayka1
      - rayka2
majid@devnet:~/devnet/pyhton_nornir/2023/10.jinja2_template$ cat group_vars/cisco.yaml
---

ntp:
  server: 3.3.3.3
  servers:
    - 3.3.3.3
    - 33.33.33.33

majid@devnet:~/devnet/pyhton_nornir/2023/10.jinja2_template$ cat group_vars/all.yaml
---
snmp:
  community: "raykag"
ntp:
  server: 5.5.5.5
  servers:
    - 5.5.5.5
    - 55.55.55.55

The SNMP community and NTP server variables were used in the jinja2 template used in the previous section. In this section, we use a list of NTP servers and authentication key information in the jinja2 configuration template.

NTP servers list are defined in all three files, “R1.yaml”, “cisco.yaml” and “all.yaml”.  But authentication key information including authentication protocol and authentication keys are only defied in “R1.yaml” file.

Python Nornir Automation Script using Ninja2 Template

This is the automation script that uses the jinja2 template configuration template to resolve and apply the configuration of each network device.

import logging
from nornir import InitNornir
from nornir_scrapli.tasks import send_configs
from nornir_utils.plugins.functions import print_result
from nornir_jinja2.plugins.tasks import template_file
from nornir_utils.plugins.tasks.data import load_yaml

nr = InitNornir(config_file="config.yaml")

def load_data(task):
  hosts_data = task.run(task=load_yaml, file=f"./host_vars/{task.host}.yaml")
  cisco_groups_data = task.run(task=load_yaml, file=f"./group_vars/cisco.yaml")
  all_data = task.run(task=load_yaml, file=f"./group_vars/all.yaml")
  task.host["hdata"] = hosts_data.result
  task.host["ciscodata"] = cisco_groups_data.result
  task.host["alldata"] = all_data.result

def jinja2_template_example(task):
    template = task.run(task=template_file, template=f"{task.host.platform}-ntp-.j2", path="./templates/", severity_level=logging.DEBUG)
    task.host["config"]=template.result
    configurations=task.host["config"].splitlines()
    task.run(task=send_configs, configs=configurations)

nr.run(task=load_data)
results = nr.run(task=jinja2_template_example)
print_result(results)

This is very similar to what we have demonstrated in the previous section. Here we use the template file, “ios-ntp-.j2”, to be resolved and applied to network devices. Shortly we will check inside the template file.

This script uses “load_yaml” to load data stored in “R1.yaml” into host variable with “hdata” key, “cisco.yaml” data into host variable with “ciscodata” key, and finally “all .yaml” into the host variable with “alldata” as the key.

Then the template file “ios-ntp-.j2” is converted to the final configuration list based on the loaded data and sent to the network devices using the nornir scrapli plugin.

Now let’s check inside the jinja2 configuration template used in automation script.

Jinja2 Template with Loop and Condition

This is the Jinja2 template we’ll be using in this section, and it includes all three of Jinja2’s main features: variable substitution, conditional, and looping.

majid@devnet:~/devnet/pyhton_nornir/2023/10.jinja2_template$ cat templates/ios-ntp-.j2
{% for server in host.hdata.ntp.servers %}
ntp server {{ server }}
{% endfor %}

{% for server in host.ciscodata.ntp.servers %}
ntp server {{ server }}
{% endfor %}

{% for server in host.alldata.ntp.servers %}
ntp server {{ server }}
{% endfor %}


{% if host.hdata.ntp.authentication is defined %}
ntp authenticate
{% for key in host.hdata.ntp.authentication.key %}
ntp authentication-key {{loop.index}} md5 {{ key }}
{% endfor %}
{% endif %}

We iterate over all the NTP server lists loaded in the “hdata”, “ciscodata”, and “alldata” keys and apply them to the network devices via the “ntp server” command.

Then with “if condition”, we check if NTP authentication information is defined in the loaded data.

When NTP authentication is defined, we enable NTP authentication with the command “ntp authenticate” and iterate over authentication keys with “for loop” and enable the keys.

This example is just a simple jinja2 template with variable substitution, conditionals and loops. But the jinja2 template has many other features that you can find with examples on the “https://ttl255.com” website.

Now let’s run the script to see how the list of NTP servers and optionally NTP authentication configured in “R1.yaml”, “cisco.yaml”, and “all.yaml” run on network devices.

majid@devnet:~/devnet/pyhton_nornir/2023/10.jinja2_template$ python3 10.2.nornir_jinja2_template_advanced.py
jinja2_template_example*********************************************************
* R1 ** changed : True *********************************************************
vvvv jinja2_template_example ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- send_configs ** changed : True -------------------------------------------- INFO
ntp server 1.1.1.1
ntp server 11.11.11.11

ntp server 3.3.3.3
ntp server 33.33.33.33

ntp server 5.5.5.5
ntp server 55.55.55.55


ntp authenticate
ntp authentication-key 1 md5 rayka1
ntp authentication-key 2 md5 rayka2

^^^^ END jinja2_template_example ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Back to: CLI based Network Automation using Python Nornir > Python Jinja2 Template

Leave a Reply

Your email address will not be published. Required fields are marked *


Post comment