diff --git a/galaxy.yml b/galaxy.yml index 6300d24f33..89f01e6c32 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -82,8 +82,8 @@ dependencies: 'git+https://github.com/openstack/ansible-collections-openstack': 'master' 'git+https://github.com/ansible-collections/ansible.netcommon': 'main' 'git+https://github.com/openstack/ansible-config_template': 'master' - 'git+https://github.com/ansible-collections/junipernetworks.junos': '2.10.0' - 'git+https://github.com/ansible-collections/cisco.ios': '3.3.2' + 'git+https://github.com/ansible-collections/junipernetworks.junos': 'main' + 'git+https://github.com/ansible-collections/cisco.ios': 'main' 'git+https://github.com/ansible-collections/mellanox.onyx': 'master' 'git+https://github.com/openshift/community.okd': 'main' 'git+https://github.com/ovirt/ovirt-ansible-collection': 'master' diff --git a/hooks/playbooks/switch_config.yml b/hooks/playbooks/switch_config.yml index 7de1cb517e..c7a16c1842 100644 --- a/hooks/playbooks/switch_config.yml +++ b/hooks/playbooks/switch_config.yml @@ -7,6 +7,7 @@ cifmw_switch_config_packages: - paramiko - ncclient + - xmltodict ansible.builtin.pip: name: "{{ cifmw_switch_config_packages }}" - name: Switches configuration diff --git a/requirements.yml b/requirements.yml index 953b59655f..777038ed61 100644 --- a/requirements.yml +++ b/requirements.yml @@ -37,10 +37,8 @@ collections: - name: https://github.com/openstack/ansible-config_template type: git - name: https://github.com/ansible-collections/junipernetworks.junos - version: 2.10.0 type: git - name: https://github.com/ansible-collections/cisco.ios - version: 3.3.2 type: git - name: https://github.com/ansible-collections/mellanox.onyx type: git diff --git a/roles/switch_config/tasks/ios_config.yml b/roles/switch_config/tasks/ios_config.yml index a4955316ad..3f5eded3b3 100644 --- a/roles/switch_config/tasks/ios_config.yml +++ b/roles/switch_config/tasks/ios_config.yml @@ -14,11 +14,15 @@ when: "'dhcp_relay' in switch_vars" - name: Set VLANs - cisco.ios.ios_vlan: - name: "vlan{{ item }}" - vlan_id: "{{ item }}" - state: present - loop: "{{ vlan_list }}" + vars: + vlan_config: | + {% for vlan in vlan_list %} + - name: "vlan{{ vlan }}" + vlan_id: "{{ vlan }}" + {% endfor %} + cisco.ios.ios_vlans: + config: "{{ vlan_config | from_yaml }}" + state: merged - name: Advanced VLAN Interface Configuration when: "'vlan_interfaces' in switch_vars" @@ -68,46 +72,38 @@ loop: "{{ switch_vars['route_maps'] }}" - name: Set interface description and MTU - cisco.ios.ios_interface: - name: "{{ item.iface }}" - description: "{{ item.description }}" - mtu: "{{ item.mtu |default(omit) }}" - # state: present - loop: "{{ switch_vars.interfaces }}" + vars: + interface_config: | + {% for interface in switch_vars['interfaces'] %} + - name: "{{ interface.iface }}" + description: "{{ interface.description }}" + mtu: "{{ interface.mtu | default(omit) }}" + {% endfor %} + cisco.ios.ios_interfaces: + config: '{{ interface_config | from_yaml }}' + state: merged - name: Configure interfaces - mode (access/trunk), vlans vars: - iface_vlans: "{%- if item.iface_mode == 'trunk' and '-' in item.vlan -%} - {{ item.vlan.split('-') }} - {%- endif -%}" - iface_vlan_range: "{%- if iface_vlans -%} - {{ range(iface_vlans.0 | int, iface_vlans.1 | int + 1) | list }} - {%- endif -%}" - trunk_vlans_list: "{%- if iface_vlan_range[0] is defined -%} - {{ iface_vlan_range.split() }}{% else %}{{ item.vlan }}{% endif %}" - access_vlan: "{% if item.iface_mode == 'access' %}{{ item.vlan }}{% endif %}" - cisco.ios.ios_l2_interface: - name: "{{ item.iface }}" - mode: "{{ item.iface_mode }}" - access_vlan: "{%- if item.iface_mode == 'access' -%} - {{ access_vlan }}{% else %}{{ omit }}{% endif %}" - trunk_vlans: "{%- if item.iface_mode == 'trunk' -%} - {{ trunk_vlans_list }}{% else %}{{ omit }}{% endif %}" - native_vlan: "{%- if item.iface_mode == 'trunk' and 'native_vlan' in item -%} - {{ item.native_vlan | int }}{% else %}{{ omit }}{% endif %}" - state: present - loop: "{{ switch_vars.interfaces }}" - -# TODO: Once moving to 2.9 version, replace the task below with the new ios_l2_interface -# module and merge with the task above. -- name: Set encapsulation on the interface - cisco.ios.ios_config: - lines: - - switchport trunk encapsulation dot1q - - switchport mode trunk - parents: "interface {{ item.iface }}" - loop: "{{ switch_vars.interfaces }}" - when: item.encapsulation is defined and item.encapsulation + interface_config: | + {% for interface in switch_vars['interfaces'] %} + - name: "{{ interface.iface }}" + mode: "{{ interface.iface_mode }}" + {{ interface.iface_mode }}: + {% if interface.iface_mode == 'trunk' and interface.native_vlan is defined %} + native_vlan: "{{ interface.native_vlan }}" + {% endif %} + {% if interface.iface_mode == 'trunk' %} + allowed_vlans: "{{ interface.vlan }}" + encapsulation: dot1q + {% endif %} + {% if interface.iface_mode == 'access' %} + vlan: "{{ interface.vlan }}" + {% endif %} + {% endfor %} + cisco.ios.ios_l2_interfaces: + config: "{{ interface_config | from_yaml }}" + state: merged - name: Save configuration cisco.ios.ios_config: diff --git a/roles/switch_config/tasks/junos_config.yml b/roles/switch_config/tasks/junos_config.yml index 4c266695ec..55604a224d 100644 --- a/roles/switch_config/tasks/junos_config.yml +++ b/roles/switch_config/tasks/junos_config.yml @@ -26,83 +26,77 @@ when: "'switch_banner' in switch_vars" - name: Set VLANs - junipernetworks.junos.junos_vlan: - name: "vlan{{ item }}" - vlan_id: "{{ item }}" - state: present - loop: "{{ vlan_list }}" + vars: + vlans: | + {% for vlan in vlan_list %} + - name: "vlan{{ vlan }}" + vlan_id: "{{ vlan }}" + {% endfor %} + junipernetworks.junos.junos_vlans: + config: "{{ vlans | from_yaml }}" + state: merged - name: Configure interfaces - description, mode (access/trunk), vlans - vars: - iface_vlans: "{%- set iface_vlans = [] -%} - {%- set helper_var = [] -%} - {%- if item.iface_mode == 'trunk'-%} - {%- if ',' in item.vlan -%} - {%- for vlan in item.vlan.replace(' ', '').split(',') -%} {{ helper_var.append(vlan) }} {%- endfor -%} - {%- else -%} - {{ helper_var.append(item.vlan) }} - {%- endif -%} - {%- for vlan in helper_var -%} - {%- if '-' in vlan -%} - {%- for v in range(vlan.split('-')[0] | int, vlan.split('-')[1] | int + 1) -%} - {{ iface_vlans.append(v) }} - {%- endfor -%} - {%- else -%} - {{ iface_vlans.append(vlan | int) }} - {%- endif -%} - {%- endfor -%} - {%- endif -%} - {{ iface_vlans | unique }}" - vlans_string: "{%- if iface_vlans -%} - {% for item in iface_vlans %}vlan{{ item }} {% endfor %} - {%- elif item.vlan == 'all' -%}{{ item.vlan }} - {%- else -%}vlan{{ item.vlan }}{% endif %}" - trunk_vlans_list: "{%- if vlans_string[0] is defined -%} - {{ vlans_string.split() }}{% else %}{{ item.vlan }}{% endif %}" - access_vlan: "{%- if item.iface_mode == 'access' -%} - {{ item.vlan |regex_replace('^(.*)$', 'vlan\\1') }} - {%- endif -%}" - junipernetworks.junos.junos_l2_interface: - name: "{{ item.iface }}" - description: "{{ item.description }}" - mode: "{{ item.iface_mode }}" - access_vlan: "{%- if item.iface_mode == 'access' -%} - {{ access_vlan }}{% else %}{{ omit }}{% endif %}" - trunk_vlans: "{%- if item.iface_mode == 'trunk' -%} - {{ trunk_vlans_list }}{% else %}{{ omit }}{% endif %}" - native_vlan: "{%- if item.iface_mode == 'trunk' and 'native_vlan' in item -%} - {{ item.native_vlan | int }}{% else %}{{ omit }}{% endif %}" - unit: 0 - state: present - loop: "{{ switch_vars.interfaces }}" when: "'interfaces' in switch_vars" + vars: + interface_config: | + {% for interface in switch_vars['interfaces'] %} + {% set helper_var = interface['vlan'].split(',') %} + - name: "{{ interface.iface }}" + {{ interface.iface_mode }}: + {% if interface.iface_mode == 'trunk' and interface.native_vlan is defined %} + native_vlan: "{{ interface.native_vlan }}" + {% endif %} + {% if interface.iface_mode == 'trunk' %} + allowed_vlans: + {% for vlan_range in helper_var %} + {% if '-' in vlan_range %} + {% for vlan in range(vlan_range.split('-')[0] | int, vlan_range.split('-')[1] | int + 1) %} + - "vlan{{ vlan }}" + {% endfor %} + {% else %} + - "vlan{{ vlan_range }}" + {% endif %} + {% endfor %} + {% endif %} + {% if interface.iface_mode == 'access' %} + vlan: "{{ interface.vlan }}" + {% endif %} + {% endfor %} + junipernetworks.junos.junos_l2_interfaces: + config: "{{ interface_config | from_yaml }}" + state: merged - - name: Set MTU value on the interface - junipernetworks.junos.junos_interface: - name: "{{ item.iface }}" - mtu: "{{ item.mtu }}" - state: present - loop: "{{ switch_vars.interfaces }}" - when: item.mtu is defined - - # LACP aggregation can't override existing configuration - # that is not LACP related on the memeber interfaces. - # Required to delete the config before setting the LACP dependency interface. - - name: Reset LACP member interface - junipernetworks.junos.junos_interface: - name: "{{ item.1 }}" - state: absent - loop: "{{ switch_vars.interfaces | subelements('aggr_members', 'skip_missing=True') }}" - when: item.0.aggr_members is defined + - name: Set MTU and description for the interfaces + vars: + interface_config: | + {% for interface in switch_vars['interfaces'] %} + - name: "{{ interface.iface }}" + description: "{{ interface.description }}" + mtu: "{{ interface.mtu | default(omit) }}" + {% endfor %} + junipernetworks.junos.junos_interfaces: + config: '{{ interface_config | from_yaml }}' + state: merged - name: Set aggregation for the interface - junipernetworks.junos.junos_linkagg: - name: "{{ item.iface }}" - description: "{{ item.description }}" - members: "{{ item.aggr_members }}" - mode: active - loop: "{{ switch_vars.interfaces }}" - when: item.aggr_members is defined + when: switch_vars['interfaces'] | selectattr('aggr_members', 'defined') != [] + vars: + interface_config: | + {% for interface in switch_vars['interfaces'] %} + {% if interface.aggr_members is defined %} + - name: "{{ interface.iface }}" + members: + {% for member in interface.aggr_members %} + - member: "{{ member }}" + {% endfor %} + mode: active + {% endif %} + {% endfor %} + junipernetworks.junos.junos_lag_interfaces: + config: '{{ interface_config | from_yaml }}' + state: merged + # For each vlan for which igmp snooping is configured, remove previous # configuration if it exists to ensure that applied configuration is @@ -138,16 +132,34 @@ when: "'layer3_interfaces' in switch_vars" block: - name: Ensure irb Interfae is configured - junipernetworks.junos.junos_l3_interface: - name: irb - unit: "{{ item['unit'] }}" - ipv4: "{{ item['ipv4_address'] }}" - loop: "{{ switch_vars['layer3_interfaces'] }}" + vars: + irb_interfaces: | + {% for interface in switch_vars['layer3_interfaces'] %} + - name: irb + unit: "{{ interface['unit'] }}" + {% if interface['ipv4_address'] is defined %} + ipv4: + address:"{{ interface['ipv4_address'] }}" + {% endif %} + {% if interface['ipv6_address'] is defined %} + ipv6: + address:"{{ interface['ipv4_address'] }}" + {% endif %} + {% endfor %} + junipernetworks.junos.junos_l3_interfaces: + config: "{{ irb_interfaces | from_yaml }}" + state: merged + - name: Assign irb Interface To VLAN Interface - junipernetworks.junos.junos_vlan: - name: "{{ item['vlan_interface'] }}" - l3_interface: "irb.{{ item['unit'] }}" - loop: "{{ switch_vars['layer3_interfaces'] }}" + vars: + vlan_interfaces: | + {% for interface in switch_vars['layer3_interfaces'] %} + - name: "{{ interface['vlan_interface'] }}" + l3_interface: "irb.{{ interface['unit'] }}" + {% endfor %} + junipernetworks.junos.junos_vlans: + config: "{{ vlan_interfaces | from_yaml }}" + state: merged - name: Save configuration junipernetworks.junos.junos_config: