f639ad0b35
By default, Ansible injects a variable for every fact, prefixed with ansible_. This can result in a large number of variables for each host, which at scale can incur a performance penalty. Ansible provides a configuration option [0] that can be set to False to prevent this injection of facts. In this case, facts should be referenced via ansible_facts.<fact>. This change updates all references to Ansible facts within Kayobe from using individual fact variables to using the items in the ansible_facts dictionary. This allows users to disable fact variable injection in their Ansible configuration, which may provide some performance improvement. This change disables fact variable injection in the ansible configuration used in CI, to catch any attempts to use the injected variables. [0] https://docs.ansible.com/ansible/latest/reference_appendices/config.html#inject-facts-as-vars Story: 2007993 Task: 42464 Depends-On: https://review.opendev.org/c/openstack/kolla-ansible/+/791276 Change-Id: I14db53ed6e57d37bbd28dd5819e432e3fe6628b2
232 lines
10 KiB
YAML
232 lines
10 KiB
YAML
---
|
|
# This playbook is intended to bootstrap network configuration of the iDRACs on
|
|
# a set of Dell servers. By default, iDRACs have a known static IP address
|
|
# configured. Since all iDRACs have the same default IP address, we need a way
|
|
# to isolate a single iDRAC while we set its network configuration. We do this
|
|
# using a temporary VLAN accessible from one of the controllers.
|
|
#
|
|
# We use the following procedure:
|
|
# 1. Create a VLAN interface on the controller node with IP in the iDRAC
|
|
# default subnet.
|
|
# 2. Create the temporary bootstrap VLAN on the switch, accessible by the
|
|
# controller and trunked to all switches within the network.
|
|
# 3. For each iDRAC switch port in turn, flip to the temporary VLAN and
|
|
# configure the iDRAC's IP address, before returning the port to the iDRAC
|
|
# management VLAN.
|
|
# 4. Remove the temporary bootstrap VLAN from the switch.
|
|
# 5. Remove the VLAN interface on the controller node.
|
|
|
|
# Playbook variables:
|
|
#
|
|
# idrac_limit: Colon-separated list of names of idracs to limit bootstrappping
|
|
# to. These names should be present in the variable
|
|
# idrac_network_ips. If omitted all idracs will be bootstrapped.
|
|
|
|
- name: Ensure the iDRAC switches are supported
|
|
hosts: "{{ idrac_bootstrap_switch_group }}"
|
|
gather_facts: no
|
|
vars:
|
|
supported_switch_types:
|
|
- dellos6
|
|
tasks:
|
|
- name: Ensure switch type is supported
|
|
fail:
|
|
msg: >
|
|
The iDRAC bootstrap process currently only supports DellOS6 switches.
|
|
when: switch_type not in supported_switch_types
|
|
|
|
# 1. Create a VLAN interface on the controller node with IP in the iDRAC
|
|
# default subnet.
|
|
- name: Ensure the controller bootstrap network is configured
|
|
hosts: "{{ idrac_bootstrap_controller_group ~ '[0]' }}"
|
|
tasks:
|
|
# Install Dell server admin tools.
|
|
- block:
|
|
- name: Ensure wget is installed
|
|
package:
|
|
name: wget
|
|
state: present
|
|
cache_valid_time: "{{ apt_cache_valid_time if ansible_facts.os_family == 'Debian' else omit }}"
|
|
update_cache: "{{ True if ansible_facts.os_family == 'Debian' else omit }}"
|
|
|
|
- name: Ensure Dell srvadmin repository is installed
|
|
shell: "wget -q -O - http://linux.dell.com/repo/hardware/latest/bootstrap.cgi | bash"
|
|
|
|
- name: Ensure Dell srvadmin-idrac7 package is installed
|
|
package:
|
|
name: srvadmin-idrac7
|
|
state: present
|
|
|
|
# Configure access to the temporary network on a controller.
|
|
- block:
|
|
# Clear any previous state.
|
|
- name: Ensure iDRAC bootstrap network namespace is deleted from the controller
|
|
command: "ip netns delete {{ idrac_bootstrap_net_namespace }}"
|
|
args:
|
|
removes: "/var/run/netns/{{ idrac_bootstrap_net_namespace }}"
|
|
|
|
- name: Ensure iDRAC bootstrap network namespace exists on controller
|
|
command: "ip netns add {{ idrac_bootstrap_net_namespace }}"
|
|
|
|
- name: Ensure bootstrap VLAN interface exists on the controller
|
|
command: "ip link add link {{ idrac_bootstrap_controller_interface }} name {{ idrac_bootstrap_controller_vlan_interface }} type vlan id {{ idrac_bootstrap_vlan }}"
|
|
|
|
- name: Ensure bootstrap VLAN interface is in network namespace
|
|
command: "ip link set {{ idrac_bootstrap_controller_vlan_interface }} netns {{ idrac_bootstrap_net_namespace }}"
|
|
|
|
- name: Ensure the bootstrap VLAN interface is active
|
|
command: "ip netns exec {{ idrac_bootstrap_net_namespace }} ip link set {{ idrac_bootstrap_controller_vlan_interface }} up"
|
|
|
|
- name: Ensure the bootstrap VLAN interface IP address is configured
|
|
command: "ip netns exec {{ idrac_bootstrap_net_namespace }} ip address add {{ idrac_bootstrap_controller_ip }}/24 dev {{ idrac_bootstrap_controller_vlan_interface }}"
|
|
rescue:
|
|
- name: Rescue | Ensure the bootstrap network namespace is removed from the controller
|
|
command: "ip netns delete {{ idrac_bootstrap_net_namespace }}"
|
|
|
|
- name: Rescue | Fail playbook execution on error
|
|
fail:
|
|
msg: >
|
|
Failed to configure access to temporary iDRAC bootstrap
|
|
network on controller.
|
|
become: True
|
|
|
|
# 2. Create the temporary bootstrap VLAN on the switch, accessible by the
|
|
# controller and trunked to all switches within the network.
|
|
- name: Ensure the bootstrap VLAN is configured on switches
|
|
hosts: "{{ idrac_bootstrap_switch_group }}"
|
|
gather_facts: no
|
|
vars:
|
|
switch_interface_config_bootstrap_trunk:
|
|
config:
|
|
- "switchport trunk allowed vlan add {{ idrac_bootstrap_vlan }}"
|
|
# Initialise the switch interface configuration.
|
|
switch_interface_config_bootstrap: {}
|
|
pre_tasks:
|
|
- name: Update facts about switch trunk interfaces
|
|
set_fact:
|
|
switch_interface_config_bootstrap: >
|
|
{{ switch_interface_config_bootstrap | combine({item.key: switch_interface_config_bootstrap_trunk}) }}
|
|
with_dict: "{{ switch_interface_config }}"
|
|
when: >
|
|
{{ item.value.description | default == groups[idrac_bootstrap_controller_group][0] or
|
|
item.value.description | default | replace('-trunk', '') in groups[idrac_bootstrap_switch_group] }}
|
|
|
|
roles:
|
|
# Configure bootstrap VLAN on the switch and add controller and trunk
|
|
# interfaces to it.
|
|
- role: dell-switch
|
|
dell_switch_type: "{{ switch_type }}"
|
|
dell_switch_provider: "{{ switch_dellos_provider }}"
|
|
dell_switch_config:
|
|
- "vlan {{ idrac_bootstrap_vlan }}"
|
|
dell_switch_interface_config: "{{ switch_interface_config_bootstrap }}"
|
|
when: switch_interface_config_bootstrap != {}
|
|
|
|
# 3. For each iDRAC switch port in turn, flip to the temporary VLAN and
|
|
# configure the iDRAC's IP address, before returning the port to the iDRAC
|
|
# management VLAN.
|
|
- name: Ensure iDRACs are bootstrapped
|
|
hosts: "{{ idrac_bootstrap_switch_group }}"
|
|
gather_facts: no
|
|
vars:
|
|
# Set this to a colon-separated list of idrac hostnames to bootstrap.
|
|
# If unset, all idracs will be bootstrapped.
|
|
idrac_limit: ""
|
|
idrac_limit_list: "{{ idrac_limit.split(':') }}"
|
|
# This is a separate play so that we can apply the serial keyword.
|
|
serial: 1
|
|
tasks:
|
|
- name: Initialise facts containing successful, unchanged and failed iDRACs
|
|
set_fact:
|
|
idrac_bootstrap_success: []
|
|
idrac_bootstrap_unchanged: []
|
|
idrac_bootstrap_failed: []
|
|
|
|
# Iterate over each switch port with an iDRAC attached in turn.
|
|
- name: Ensure iDRACs are (sequentially) bootstrapped
|
|
include_tasks: idrac-bootstrap-one.yml
|
|
vars:
|
|
dell_switch_type: "{{ switch_type }}"
|
|
dell_switch_provider: "{{ switch_dellos_provider }}"
|
|
switch_interface_name: "{{ item.key }}"
|
|
idrac_port_description: "{{ item.value.description }}"
|
|
idrac_network_ip: "{{ idrac_network_ips[idrac_port_description] }}"
|
|
idrac_bootstrap_controller: "{{ hostvars[groups[idrac_bootstrap_controller_group][0]].ansible_host }}"
|
|
with_dict: "{{ switch_interface_config }}"
|
|
when: >
|
|
{{ item.value.description | default in idrac_network_ips and
|
|
(not idrac_limit or item.value.description | default in idrac_limit_list) }}
|
|
|
|
# 4. Remove the temporary bootstrap VLAN from the switch.
|
|
- name: Ensure the bootstrap VLAN is removed from switches
|
|
hosts: "{{ idrac_bootstrap_switch_group }}"
|
|
gather_facts: no
|
|
vars:
|
|
switch_interface_config_bootstrap_trunk:
|
|
config:
|
|
- "switchport trunk allowed vlan remove {{ idrac_bootstrap_vlan }}"
|
|
# Initialise the switch interface configuration.
|
|
switch_interface_config_bootstrap: {}
|
|
pre_tasks:
|
|
- name: Update facts about switch trunk interfaces
|
|
set_fact:
|
|
switch_interface_config_bootstrap: >
|
|
{{ switch_interface_config_bootstrap | combine({item.key: switch_interface_config_bootstrap_trunk}) }}
|
|
with_dict: "{{ switch_interface_config }}"
|
|
when: >
|
|
{{ item.value.description | default == groups[idrac_bootstrap_controller_group][0] or
|
|
item.value.description | default | replace('-trunk', '') in groups[idrac_bootstrap_switch_group] }}
|
|
roles:
|
|
# Remove bootstrap VLAN from the switch and remove controller and trunk
|
|
# interfaces from it.
|
|
- role: dell-switch
|
|
dell_switch_type: "{{ switch_type }}"
|
|
dell_switch_provider: "{{ switch_dellos_provider }}"
|
|
dell_switch_config:
|
|
- "no vlan {{ idrac_bootstrap_vlan }}"
|
|
dell_switch_interface_config: "{{ switch_interface_config_bootstrap }}"
|
|
when: switch_interface_config_bootstrap != {}
|
|
|
|
# 5. Remove the VLAN interface on the controller node.
|
|
- name: Ensure the controller bootstrap network is cleaned up
|
|
hosts: "{{ idrac_bootstrap_controller_group ~ '[0]' }}"
|
|
tasks:
|
|
# This should also delete the network interface within the namespace.
|
|
- name: Ensure the bootstrap network namespace is removed from the controller
|
|
command: "ip netns delete {{ idrac_bootstrap_net_namespace }}"
|
|
become: True
|
|
|
|
- name: Display the results of the iDRAC bootstrap procedure
|
|
hosts: "{{ idrac_bootstrap_switch_group }}"
|
|
gather_facts: no
|
|
tasks:
|
|
- name: Display a list of failed iDRACs
|
|
set_fact:
|
|
idrac_bootstrap_failed_port_descriptions: "{{ idrac_bootstrap_failed | map(attribute='port description') | list }}"
|
|
when: idrac_bootstrap_failed | length > 0
|
|
|
|
- name: Display a list of successfully bootstrapped iDRACs
|
|
debug:
|
|
var: idrac_bootstrap_success
|
|
|
|
- name: Display a list of iDRACs that did not require bootstrapping
|
|
debug:
|
|
var: idrac_bootstrap_unchanged
|
|
|
|
- name: Display a list of failed iDRACs
|
|
debug:
|
|
var: idrac_bootstrap_failed_port_descriptions
|
|
when: idrac_bootstrap_failed | length > 0
|
|
|
|
- name: Display a list of failed iDRACs with debug output for the failed tasks
|
|
debug:
|
|
var: idrac_bootstrap_failed
|
|
when: idrac_bootstrap_failed | length > 0
|
|
|
|
- name: Fail if there were any iDRAC bootstrapping failures
|
|
fail:
|
|
msg: >
|
|
One or more iDRACs failed to bootstrap, see the list above for
|
|
details.
|
|
when: idrac_bootstrap_failed | length > 0
|