Ansible – Config Generator III

For Part I & Part II of this series.

The goal of this playbook is to be able to generate unique configuration for each switch. In this case, we are configuring a port to work as an access-port for a specific vlan. The port and vlan variable is different for each switch.

config-gen.yml

---
- hosts: 127.0.0.1
  connection: local
  gather_facts: no

  tasks:
  - name: GET DATA
    include_vars: ./host_vars/file.yml

  - name: GENERATE CONFIG
    template:
      src: ./templates/accessvlan.j2
      dest: ./config-output/{{ item.switch }}.conf
    with_items: "{{ file_vlan }}"

file.yml

---
file_vlan:
- { switch: switch-1, port: Gi1/8,  vlan: 395 }
- { switch: switch-1, port: Gi1/23, vlan: 388 }
- { switch: switch-2, port: Gi1/8,  vlan: 395 }
- { switch: switch-2, port: Gi1/23, vlan: 388 }
- { switch: switch-3, port: Gi1/9,  vlan: 395 }
- { switch: switch-3, port: Gi1/24, vlan: 388 }
- { switch: switch-4, port: Gi1/9,  vlan: 395 }
- { switch: switch-4, port: Gi1/24, vlan: 388 }

accessvlan.j2

{% for grouper, host in file_vlan|groupby('switch') %}
{% if item.switch == grouper %}
{% for item in host %}            
int {{ item.port }}                   
switchport access vlan {{ item.vlan }}
{% endfor %}
{% endif %}
{% endfor %}

When the “config-gen.yml” playbook is executed:

ansible-playbook config-gen.yml

we get the following output files:

~/ansible_play/config-output$ cat switch-1.conf 
            
int Gi1/1                   
switchport access vlan 195
            
int Gi1/10                   
switchport access vlan 188
 
~/ansible_play/config-output$ cat switch-2.conf 
            
int Gi1/2                   
switchport access vlan 295
            
int Gi1/20                   
switchport access vlan 288
 
~/ansible_play/config-output$ cat switch-3.conf 
            
int Gi1/3                   
switchport access vlan 395
            
int Gi1/30                   
switchport access vlan 388
 
~/ansible_play/config-output$ cat switch-4.conf 
            
int Gi1/4                   
switchport access vlan 495
            
int Gi1/40                   
switchport access vlan 488

Ansible – Config Generator – II

For the first part of this series, check this – 1st part of this series.

---
- hosts: local
  connection: local
  gather_facts: no

  tasks:
  - name: GET DATA
    include_vars: ./host_vars/file.yml

  - name: GENERATE CONFIG
    template:
      src: ./SVI.j2
      dest: ./{{ item.vlan }}.conf
    with_items: "{{ file_vlan }}"

 

This is the file.yml that is being referenced in the “include_vars”

---
file_vlan:
- { vrf: NET1, vlan: 502, vlanname: VLAN-502-NAME, net: 10.80.120.128/29 }
- { vrf: NET1, vlan: 503, vlanname: VLAN-503-NAME, net: 10.80.120.136/29 }

Compared to the 1st part of this series, we are moving the contents of the “with_items” to a separate YAML file and calling it based on the variable name “file_vlan” that is part of the file content.

Ansible – Config Generator – I

Before proceeding, make sure to install “netaddr” as this is required for “ipaddr()” used in the Jinja2 configuration template.

pip install netaddr

aggr.yml is the playbook that will be utilized for generating L3 SVI configuration:

---
- hosts: local
  connection: local
  gather_facts: no

tasks:
- name: GENERATE CONFIG
  template:
  src: ./SVI.j2
  dest: ./{{ item.vlan }}.conf
  with_items:
  - { vrf: NET1, vlan: 502, vlanname: VLAN-502-NAME, net: 10.80.120.128/29 }
  - { vrf: NET1, vlan: 503, vlanname: VLAN-503-NAME, net: 10.80.120.136/29 }

This is the SVI.j2 Jinja2 template that is being utilized to generate the final configuration:

###### A-Side ######
vlan {{ item.vlan }}
 name {{ item.vlanname }}

interface Vlan {{ item.vlan }}
 description {{ item.vlanname }}
 mtu 9100
 vrf member {{ item.vrf }}
 no ip redirects
 ip address {{ item.net | ipaddr('2') }}
 hsrp version 2
 hsrp 1
 authentication md5 key-string password{{ item.vlan }}
 preempt delay minimum 120
 priority 120
 timers 1 3
 ip {{ item.net | ipaddr('1') | ipaddr('address') }}

###### B-Side ######
vlan {{ item.vlan }}
 name {{ item.vlanname }}

interface Vlan {{ item.vlan }}
 description {{ item.vlanname }}
 mtu 9100
 vrf member {{ item.vrf }}
 no ip redirects
 ip address {{ item.net | ipaddr('3') }}
 hsrp version 2
 hsrp 1
 authentication md5 key-string password{{ item.vlan }}
 preempt delay minimum 120
 priority 110
 timers 1 3
 ip {{ item.net | ipaddr('1') | ipaddr('address') }}

In my setup, the play-book (aggr.yml), source template SVI.j2 file and the destination file exist in the same folder.

Reference Github.