Dynamic Multi-Vendor Network Configuration#

In the previous section, we used the same Jinja2 template for configuration. However, in a multi-vendor network, different devices may require different templates. Let’s explore how to handle multi-vendor configurations using another example.

Example Scenario#

In the previous lab, we had two Cisco routers with IP addresses 172.16.10.11 and 172.16.10.14. Suppose the router at 172.16.10.14 is a Juniper device and requires a different configuration. To achieve this, we need to add a key in the host_vars file to reference in the playbook.

For Router 172.16.10.14:

# host_vars/172.16.10.14.yaml
ospf:
  process_id: 10
  router_id: 1.1.1.1

device_vendor: "juniper"

Here, we define the key device_vendor: "juniper" for the Juniper device.

For Router 172.16.10.11:

# host_vars/172.16.10.11.yaml
ospf:
  process_id: 10
  router_id: 2.2.2.2

device_vendor: "cisco"

In this host file, we use the same key name with a different value device_vendor: "cisco". It’s important that the key names are the same but the values are different.

Creating Vendor-Specific Templates#

In the templates directory, create two files named cisco.j2 and juniper.j2.

juniper.j2 Template:

set protocols ospf area {{ ospf.process_id }} interface ge-0/0/0.0
set protocols ospf area {{ ospf.process_id }} router-id {{ ospf.router_id }}

cisco.j2 Template:

router ospf {{ ospf.process_id }}
  router-id {{ ospf.router_id }}

Updating the Playbook#

Amend the playbook to accommodate the new configuration:

---
- name: Load Jinja2 Template
  hosts: 172.16.10.11, 172.16.10.14
  gather_facts: false

  tasks:
    - name: Generate OSPF Configuration
      template:
        src: "templates/{{ device_vendor }}.j2"
        dest: "/path/to/output/ospf_config_{{ inventory_hostname }}.conf"

Directory Structure#

Ensure your directory structure looks like this:

your_project/
├── ansible.cfg
├── host_vars
│   ├── 172.16.10.11.yaml
│   └── 172.16.10.14.yaml
├── inventory.cfg
├── templates
│   ├── cisco.j2
│   └── juniper.j2
└── ospf_config.yaml

Running the Playbook#

Execute the playbook with Ansible:

ansible-playbook ospf_config.yaml

Sample output:

PLAY [Load Jinja2 Template] ************************************************************

TASK [Generate OSPF Configuration] *****************************************************
changed: [172.16.10.14]
changed: [172.16.10.11]

PLAY RECAP *****************************************************************************
172.16.10.11               : ok=1    changed=1    unreachable=0    failed=0    skipped=0
172.16.10.14               : ok=1    changed=1    unreachable=0    failed=0    skipped=0

Resulting Configurations#

The configurations will be generated and saved on the control node, not pushed directly to the devices.

For Router 172.16.10.14 (Juniper):

set protocols ospf area 10 interface ge-0/0/0.0
set protocols ospf area 10 router-id 1.1.1.1

For Router 172.16.10.11 (Cisco):

router ospf 10
  router-id 2.2.2.2

By using different Jinja2 templates and referencing them dynamically in the Ansible playbook, you can efficiently manage multi-vendor network configurations. This approach ensures that each device gets the correct configuration, reducing errors and streamlining the network management process.

The generated configurations are saved on the control node, allowing you to review them before applying them to the devices.