kayobe/ansible/overcloud-introspection-rul...

136 lines
6.2 KiB
YAML

---
# Some Dell switch OSs (including Dell Network OS 9.10(0.1)) do not support
# sending interface port description TLVs correctly. Instead of sending the
# interface description, they send the interface name (e.g. TenGigabitEthernet
# 1/1/1). This breaks the discovery process which relies on Ironic node
# introspection data containing the node's name in the interface port
# description. We work around this here by creating an introspection rule for
# each ironic node that matches against the switch system and the relevant
# interface name, then sets the node's name appropriately.
#
# Note that some Dell switches running Dell Networking OS version 9.11(2.0P1)
# and newer do *not* need this workaround. The interface description can be
# sent using the following configuration:
#
# (conf-if-interface)#protocol lldp
# (conf-if-interface-lldp)#advertise interface-port-desc description
- name: Check whether Ironic is enabled
hosts: controllers
gather_facts: False
tags:
- introspection-rules
- introspection-rules-dell-lldp-workaround
tasks:
- name: Create controllers group with ironic enabled
group_by:
key: "controllers_for_introspection_rules_dell_lldp_workaround_{{ kolla_enable_ironic | bool }}"
changed_when: false
- name: Group controller hosts in systems requiring the workaround
hosts: controllers_for_introspection_rules_dell_lldp_workaround_True
gather_facts: False
tags:
- introspection-rules
- introspection-rules-dell-lldp-workaround
tasks:
- name: Group controller hosts in systems requiring the Dell switch LLDP workaround
group_by:
key: "controllers_require_workaround_{{ groups[inspector_dell_switch_lldp_workaround_group] | default([]) | length > 0 }}"
changed_when: false
- name: Ensure introspection rules for Dell switch LLDP workarounds are registered in Ironic Inspector
# Only required to run on a single host.
hosts: controllers_require_workaround_True[0]
tags:
- introspection-rules
- introspection-rules-dell-lldp-workaround
vars:
all_switch_interfaces: []
ironic_inspector_rules: []
# This rule template is used in a with_subelements loop.
inspector_interface_mapping_rule:
description: "Set {{ item.1.1.description }} node name from {{ inspector_rule_var_lldp_switch_port_interface }} LLDP switch port description"
conditions:
- field: "data://all_interfaces.{{ inspector_rule_var_lldp_switch_port_interface }}"
op: "is-empty"
invert: True
- field: "data://all_interfaces.{{ inspector_rule_var_lldp_switch_port_interface }}.lldp_processed"
op: "is-empty"
invert: True
- field: "data://all_interfaces.{{ inspector_rule_var_lldp_switch_port_interface }}.lldp_processed.switch_port_description"
op: "is-empty"
invert: True
- field: "data://all_interfaces.{{ inspector_rule_var_lldp_switch_port_interface }}.lldp_processed.switch_system_name"
op: "is-empty"
invert: True
# Match against the interface name.
- field: "data://all_interfaces.{{ inspector_rule_var_lldp_switch_port_interface }}.lldp_processed.switch_port_description"
op: "eq"
# Our interface names may be of a shortened form e.g. Te1/1/1, but
# the port description will contain the full interface name. Use a
# regex to expand to the full form.
value: "{{ item.1.0 | regex_replace('^Te([a-zA-z ]*)([0-9/]+)$', 'TenGigabitEthernet \\2') }}"
# Match against the switch system name.
- field: "data://all_interfaces.{{ inspector_rule_var_lldp_switch_port_interface }}.lldp_processed.switch_system_name"
op: "eq"
value: "{{ item.0.host }}"
actions:
- action: "set-attribute"
path: "name"
value: "{{ item.1.1.description }}"
inspector_rule_var_lldp_switch_port_interface: "{{ inspector_lldp_switch_port_interface_map.get(item.1.1.description, inspector_lldp_switch_port_interface_default) }}"
pre_tasks:
- name: Validate OpenStack password authentication parameters
fail:
msg: >
Required OpenStack authentication parameter {{ item }} is
{% if item in openstack_auth %}empty{% else %}not present{% endif %}
in openstack_auth. Have you sourced the environment file?
when:
- openstack_auth_type == 'password'
- item not in openstack_auth or not openstack_auth[item]
with_items: "{{ openstack_auth_password_required_params }}"
tags:
- config-validation
# We build up the rules using a 2-step process. First we build a list of
# relevant switch hosts and their interface configuration (in list form).
# This allows us to use with_subelements in the next task to iterate over
# the interfaces for each switch.
- name: Update a fact containing switch interface configuration
set_fact:
all_switch_interfaces: >
{{ all_switch_interfaces +
[{'host': item.key,
'interface_config': item.value.switch_interface_config.items()}] }}
with_dict: "{{ hostvars }}"
when: item.key in groups[inspector_dell_switch_lldp_workaround_group]
- name: Update a fact containing Ironic Inspector rules
set_fact:
ironic_inspector_rules: >
{{ ironic_inspector_rules +
[inspector_interface_mapping_rule] }}
with_subelements:
- "{{ all_switch_interfaces }}"
- interface_config
when:
- item.1.1.description is defined
# Ignore VLAN interfaces.
- "'vlan' not in item.1.0"
# Ignore trunk links.
- "'-trunk' not in item.1.1.description"
roles:
- role: ironic-inspector-rules
os_openstacksdk_install_epel: "{{ dnf_install_epel }}"
os_openstacksdk_upper_constraints_file: "{{ openstacksdk_upper_constraints_file }}"
ironic_inspector_venv: "{{ virtualenv_path }}/openstacksdk"
ironic_inspector_upper_constraints_file: "{{ pip_upper_constraints_file }}"
ironic_inspector_auth_type: "{{ openstack_auth_type }}"
ironic_inspector_auth: "{{ openstack_auth }}"
ironic_inspector_cacert: "{{ openstack_cacert }}"
ironic_inspector_interface: "{{ openstack_interface }}"