Skip to content

Commit

Permalink
[switch_config] Multiple configs per run
Browse files Browse the repository at this point in the history
  • Loading branch information
pablintino authored and openshift-merge-bot[bot] committed Aug 12, 2024
1 parent f054e58 commit fb1634e
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 151 deletions.
1 change: 1 addition & 0 deletions docs/dictionary/en-custom.txt
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ jira
jmespath
jq
json
junos
jxe
jzxbol
kcgpby
Expand Down
258 changes: 109 additions & 149 deletions roles/switch_config/README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# Switches config
# switch_config

## Description
The switches config role performs the following tasks:

- VLAN configuration access/trunk on the switch port.
- MTU configuration on the switch port.
- LACP configuration on interface and members attach.
- IGMP Snooping configuration

Supported switch platforms:

- Cisco
- Juniper
- Mellanox MLNX-OS (ONYX with JSON API is not supported due to not having access to a compatible switch)
Expand All @@ -18,158 +19,117 @@ We are doing a check to avoid this if the configuration database is open.
It will automatically retry 3 times every 15 minutes if it is not open (by default).
This hack might not be stable.

## Inventory
The play requires an inventory file that will describe switches that the playbook should run on.
**Note** - Switches are static resources that not changing frequently.
As a result the inventory could be static and not generated dynamically.
The inventory for this playbook should be created by the user.
## Privilege escalation

```
[ios]
cisco_switch01 ansible_host=10.10.10.120
[junos]
juniper_switch01 ansible_host=10.10.10.100
juniper_switch02 ansible_host=10.10.10.101
[onyx]
mlx_switch01 ansible_host=10.10.10.131
[switches:children]
ios
junos
onyx
[switches:vars]
ansible_user=root
[ios:vars]
ansible_network_os=ios
ansible_connection=network_cli
ansible_become=yes
ansible_become_method=enable
[junos:vars]
ansible_network_os=junos
ansible_connection=netconf
[onyx:vars]
ansible_user=admin
ansible_password=admin
ansible_become_password=admin
ansible_connection=network_cli
ansible_network_os=onyx
ansible_become=yes
ansible_become_method=enable
```
None

## Variables
The names of the switches in the variables should represent the name of the switch in the inventory.

```YAML
juniper_switch01:
switch_banner: |
MOTD can
span multiple lines
vlans:
- start: 10
end: 20
- start: 50
end: 55
interfaces:
- { description: 'host1_port1', iface: 'xe-0/0/0', iface_mode: 'access', vlan: '10', mtu: '9000' }
- { description: 'host2_port3', iface: 'xe-0/0/1', iface_mode: 'trunk', vlan: '15-20', mtu: '9000' }
- { description: 'host3_port1', iface: 'xe-0/0/4', iface_mode: 'trunk', vlan: '50-53' }
- { description: 'aggregation', iface: 'ae2', iface_mode: 'trunk', vlan: '53-55', mtu: '9192', aggr_members: ['xe-0/0/12', 'xe-0/0/13'] }
igmp_snooping:
- { vlan: '55', ip_address: '10.20.155.5', interfaces: ['ae2'] }

juniper_switch02:
vlans:
- start: 25
end: 30
- start: 70
end: 75
interfaces:
- { description: 'host1_port1', iface: 'xe-0/0/0', iface_mode: 'trunk', vlan: '25-27', mtu: '9000' }
- { description: 'host2_port3', iface: 'xe-0/0/1', iface_mode: 'access', vlan: '29', mtu: '9000' }
- { description: 'host3_port1', iface: 'xe-0/0/4', iface_mode: 'trunk', vlan: '70-75' }
- { description: 'host3_port1', iface: 'xe-0/0/5', iface_mode: 'trunk', vlan: '70' }
# The play assumes that all layer3 interfaces are of type 'irb'
# 'vlan_interface' name is <vlan><vlan_id>
layer3_interfaces:
- unit: '110'
ipv4_address: '192.168.110.254/24'
vlan_interface: 'vlan110'
- unit: '199'
ipv4_address: '192.168.199.254/24'
vlan_interface: 'vlan999'

cisco_switch01:
switch_banner: |
MOTD can
span multiple lines
# Generates the following commands:
# route-map Test-RouteMap permit 10
# match ip address Test-RouteMap-ACL
# set ip next-hop 192.168.20.1
# interface vlan 21
# ip policy route-map Test-RouteMap
route_maps:
- route_map_name: Test-RouteMap
match_ip_address: Test-RouteMap-ACL
ip_next_hop: 192.168.20.1
interface: vlan21
vlans:
- start: 100
end: 105
interfaces:
- { description: 'tigon15', iface: 'GigabitEthernet5/0/6', iface_mode: 'access', vlan: '20' }
- { description: 'tigon16', iface: 'GigabitEthernet5/0/7', iface_mode: 'access', vlan: '20' }
- { description: 'tigon17', iface: 'GigabitEthernet5/0/8', iface_mode: 'access', vlan: '90' }
- { description: 'uplink_port', iface: 'GigabitEthernet5/0/9', iface_mode: 'trunk', vlan: '', encapsulation: true }
vlan_interfaces:
- iface: vlan20
ip_address: 192.168.20.200
netmask: 255.255.255.0
- iface: vlan21
ip_address: 192.168.21.254
netmask: 255.255.255.0
ip_helper_address:
- 192.168.20.1
- 192.168.20.5

mlx_switch01:
switch_banner: |
"MOTD is in double quotes"
vlans:
- start: 110
end: 119
interfaces:
- description: "{'host': 'tigon15', 'nic_biosdevname': 'p6p1', 'nic_kernel_predictable_name': 'enp7s0f0', 'description': 'Mellanox NIC1 port0'}"
iface: 'ethernet 1/1'
iface_mode: 'trunk'
vlan: '110-115'
mtu: 9192
- description: "{'host': 'tigon16', 'nic_biosdevname': 'p6p2', 'nic_kernel_predictable_name': 'enp7s0f1', 'description': 'Mellanox NIC1 port1'}"
iface: 'ethernet 1/2'
iface_mode: 'trunk'
vlan: '110-114, 116'
mtu: 9192
- description: "{'host': 'kodkod01', 'nic_biosdevname': 'p6p2', 'nic_kernel_predictable_name': 'enp7s0f1', 'description': 'Mellanox NIC1 port0'}"
iface: 'ethernet 1/3'
iface_mode: 'acess'
vlan: 118
mtu: 9192
```

* `cifmw_switch_config_task_retry_delay`: (int) The delay time between retries when DB is locked, defaults to `900`.
* `cifmw_switch_config_task_retries`: (int) Number of retries when DB is locked, defaults to `3`.
## Parameters

* `cifmw_switch_config_task_retry_delay`: (Integer) The delay time between retries when DB is locked, defaults to `900`.
* `cifmw_switch_config_task_retries`: (Integer) Number of retries when DB is locked, defaults to `3`.
* `cifmw_switch_config_scenario_name`: (String) The scenario to use to configure the switches. Defaults to `default`.


## Example
Example on applying switch configuration
## Inventory

This role is prepared to target `switches` based on their `ansible_network_os`. Each target host must define the variable
and it should match one of these values:

- junos
- ios
- onyx

A complete inventory that covers all the supported types follows:

```yaml
---
switches:
hosts:
junos-01-sw:
ansible_user: root
ansible_host: junos-01-sw.lab.example.com
ansible_network_os: junos
ansible_connection: netconf
ios-01-sw:
ansible_user: root
ansible_host: ios-01-sw.lab.example.com
ansible_network_os: ios
ansible_connection: network_cli
ansible_become: yes
ansible_become_method: enable
onyx-01-sw:
ansible_user: root
ansible_host: onyx-01-sw.lab.example.com
ansible_network_os: onyx
ansible_connection: network_cli
ansible_become: yes
ansible_become_method: enable
```
ansible-playbook -i /path/to/inventory switch_config.yml -e @vars_file_config.yml
## Config
The role uses a common format to hold the configuration details of the switches, despite of their manufacturer.
The configuration can be passed to the role by one of these approaches:
- By passing the configuration using a dictionary named as the switch host is named in the inventory. If the
variable exists for a given switch the next approach will be ignored.
- By using the `cifmw_switch_config_scenarios` variable in conjunction with `cifmw_switch_config_scenario_name`.
This approach. This approach allows the caller to run the role multiple times with different configurations by just
toggling the `cifmw_switch_config_scenario_name`. The format of the scenario dictionary is identical to the one of
the previous approach.

Example:

```yaml
---
cifmw_switch_config_scenarios:
default:
junos-01-sw:
layer3_interfaces:
- unit: "50"
ipv4_address: "172.29.0.254/16"
vlan_interface: "vlan50"
- unit: "51"
ipv4_address: "192.168.51.254/24"
vlan_interface: "vlan51"
vlans:
- start: 50
end: 51
interfaces:
- description: "Inteface 0"
iface: "ge-0/0/20"
iface_mode: "trunk"
native_vlan: "51"
vlan: "50-51"
mtu: "9192"
- description: "Inteface 1"
iface: "ge-0/0/21"
iface_mode: "access"
vlan: "50"
mtu: "9192"
second-scenario:
junos-01-sw:
layer3_interfaces:
- unit: "50"
ipv4_address: "172.29.0.254/16"
vlan_interface: "vlan50"
- unit: "51"
ipv4_address: "192.168.51.254/24"
vlan_interface: "vlan51"
vlans:
- start: 50
end: 51
interfaces:
- description: "Inteface 0"
iface: "ge-0/0/20"
iface_mode: "trunk"
native_vlan: "51"
vlan: "50-51"
mtu: "9192"
- description: "Inteface 1"
iface: "ge-0/0/21"
iface_mode: "access"
vlan: "50"
mtu: "1500"
```
4 changes: 4 additions & 0 deletions roles/switch_config/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Amount of retries to supported tasks
cifmw_switch_config_task_retries: 3
cifmw_switch_config_task_retry_delay: 900
cifmw_switch_config_scenario_name: default

# Optional parameters:
# cifmw_switch_config_scenarios
18 changes: 16 additions & 2 deletions roles/switch_config/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
---
- name: Load switch configuration
ansible.builtin.set_fact:
switch_vars: "{{ (lookup('vars', inventory_hostname, default='')) }}"
switch_vars: >-
{{
lookup('vars', inventory_hostname, default={}) |
default(
(
(
(
hostvars[inventory_hostname]["cifmw_switch_config_scenarios"]
[cifmw_switch_config_scenario_name] | default({})
)[inventory_hostname] | default({})
)
)
if ("cifmw_switch_config_scenarios" in hostvars[inventory_hostname]) else {}
, true)
}}
- name: Create VLANs list
ansible.builtin.set_fact:
Expand All @@ -11,4 +25,4 @@

- name: "Include tasks: {{ ansible_network_os }}"
ansible.builtin.include_tasks: "{{ ansible_network_os }}_config.yml"
when: switch_vars
when: switch_vars | length > 0

0 comments on commit fb1634e

Please sign in to comment.