kayobe/ansible/kolla-ansible.yml
Mark Goddard 5bf96da187 Performance: avoid set_fact in Kolla Ansible host vars
When generating host variable files for Kolla Ansible, we have some
heavy usage of set_fact to set variables for network interfaces, in a
play targeted at all hosts. There are also tasks using the fail action
plugin to perform verification.

At scale this has a significant impact, due to the number of tasks
executed against all hosts. These tasks are executed at the beginning of
many commands, so the scope is broad.  There is also some tricky logic
involved, which is difficult to express in Ansible/Jinja.

This change replaces the use of set_fact with a custom Ansible action
plugin. The plugin executes locally on the Ansible controller, and
returns a dict of Ansible facts to set for each host. The plugin is
executed once for each overcloud host, and returns all relevant facts.
The plugin also performs verification. Extraction into a Python module
allows for unit testing.

This has been shown to have a significant improvement on execution time,
particularly as the number of hosts reaches 100 or more.

Story: 2007993
Task: 40641

Change-Id: I443da1ae05fcca2d7d8dff7db563eeda37e9f502
2020-10-01 09:49:28 +00:00

235 lines
10 KiB
YAML

---
- name: Gather facts for localhost
hosts: localhost
gather_facts: true
tags: always
- name: Validate configuration options for kolla-ansible
hosts: localhost
tags:
- kolla-ansible
- config-validation
tasks:
- name: Validate serial console configuration
block:
- name: Check ipmitool-socat is in enabled in kolla_ironic_enabled_console_interfaces
fail:
msg: >
kolla_ironic_enabled_console_interfaces must contain ipmitool-socat if you set
ironic_serial_console_autoenable to true
when:
- kolla_ironic_enabled_console_interfaces is defined
- "'ipmitool-socat' not in kolla_ironic_enabled_console_interfaces"
when: ironic_serial_console_autoenable | bool
- name: Ensure Kolla Ansible is configured
hosts: localhost
tags:
- kolla-ansible
gather_facts: false
vars:
# We need to reference configuration for the network node.
# We pick the first host from the group for this. It is possible that at
# this point these groups have no hosts in, and we should handle that case
# gracefully.
network_host: "{{ groups['network'][0] }}"
pre_tasks:
# Configuration of extra user-provided Kolla globals.
- block:
- name: Check whether a Kolla extra globals configuration file exists
stat:
path: "{{ kayobe_config_path ~ '/kolla/globals.yml' }}"
get_checksum: False
get_md5: False
mime: False
register: globals_stat
- name: Read the Kolla extra globals configuration file
set_fact:
kolla_extra_globals: "{{ lookup('template', kayobe_config_path ~ '/kolla/globals.yml') | from_yaml }}"
when: globals_stat.stat.exists
tags:
- config
# Configuration and validation of network host networking.
- block:
- name: Set facts containing the VIP addresses and FQDNs
set_fact:
kolla_internal_vip_address: "{{ internal_net_name | net_vip_address }}"
kolla_internal_fqdn: "{{ internal_net_name | net_fqdn or internal_net_name | net_vip_address }}"
kolla_external_vip_address: "{{ public_net_name | net_vip_address }}"
kolla_external_fqdn: "{{ public_net_name | net_fqdn or public_net_name | net_vip_address }}"
when: kolla_enable_haproxy | bool
- name: Set facts containing the VIP addresses and FQDNs
set_fact:
kolla_internal_vip_address: "{{ internal_net_name | net_ip(network_host) }}"
kolla_internal_fqdn: "{{ internal_net_name | net_ip(network_host) }}"
kolla_external_vip_address: "{{ public_net_name | net_ip(network_host) }}"
kolla_external_fqdn: "{{ public_net_name | net_ip(network_host) }}"
when: not kolla_enable_haproxy | bool
- name: Validate Kolla Ansible API address configuration
fail:
msg: >
The Kolla Ansible variable {{ item.var_name }}
({{ item.description }}) is invalid. Value:
"{{ hostvars[inventory_hostname][item.var_name] | default('<undefined>') }}".
when:
- item.required | bool
- hostvars[inventory_hostname][item.var_name] is not defined or not hostvars[inventory_hostname][item.var_name]
with_items:
- var_name: "kolla_internal_vip_address"
description: "Internal API VIP address"
required: True
- var_name: "kolla_internal_fqdn"
description: "Internal API Fully Qualified Domain Name (FQDN)"
required: True
- var_name: "kolla_external_vip_address"
description: "external API VIP address"
required: True
- var_name: "kolla_external_fqdn"
description: "External API Fully Qualified Domain Name (FQDN)"
required: True
when: groups['network'] | length > 0
tags:
- config
- config-validation
- import_role:
name: kolla-ansible
vars:
kolla_ansible_install_epel: "{{ dnf_install_epel }}"
kolla_external_fqdn_cert: "{{ kolla_config_path }}/certificates/haproxy.pem"
kolla_internal_fqdn_cert: "{{ kolla_config_path }}/certificates/haproxy-internal.pem"
kolla_ansible_passwords_path: "{{ kayobe_config_path }}/kolla/passwords.yml"
kolla_overcloud_group_vars_path: "{{ kayobe_config_path }}/kolla/inventory/group_vars"
kolla_ansible_certificates_path: "{{ kayobe_config_path }}/kolla/certificates"
# NOTE: This differs from the default SELinux mode in kolla ansible,
# which is permissive. The justification for using this mode is twofold:
# 1. it avoids filling up the audit log
# 2. it avoids an issue seen when using diskimage-builder in the bifrost
# container.
# We could look at making the SELinux mode configurable in future.
kolla_selinux_state: disabled
kolla_inspector_dhcp_pool_start: "{{ inspection_net_name | net_inspection_allocation_pool_start }}"
kolla_inspector_dhcp_pool_end: "{{ inspection_net_name | net_inspection_allocation_pool_end }}"
kolla_inspector_default_gateway: "{{ inspection_net_name | net_inspection_gateway or inspection_net_name | net_gateway }}"
kolla_inspector_extra_kernel_options: "{{ inspector_extra_kernel_options }}"
kolla_enable_host_ntp: false
docker_daemon_mtu: "{{ public_net_name | net_mtu | default }}"
- name: Generate Kolla Ansible host vars for the seed host
hosts: seed
tags:
- config
- config-validation
- kolla-ansible
gather_facts: False
tasks:
- name: Set Kolla Ansible host variables
kolla_ansible_host_vars:
interfaces:
- var_name: "kolla_bifrost_network_interface"
description: "Bifrost provisioning network"
network: "{{ provision_oc_net_name }}"
required: True
# Strictly api_interface is not required but kolla-ansible currently
# references it in prechecks.
- var_name: "kolla_api_interface"
description: "Bifrost provisioning network"
network: "{{ provision_oc_net_name }}"
required: True
- import_role:
name: kolla-ansible-host-vars
vars:
kolla_ansible_pass_through_host_vars: "{{ kolla_seed_inventory_pass_through_host_vars }}"
kolla_ansible_pass_through_host_vars_map: "{{ kolla_seed_inventory_pass_through_host_vars_map }}"
kolla_ansible_inventory_path: "{{ kolla_config_path }}/inventory/seed"
- name: Generate Kolla Ansible host vars for overcloud hosts
hosts: overcloud
tags:
- config
- config-validation
- kolla-ansible
gather_facts: False
tasks:
- name: Set Kolla Ansible host variables
vars:
require_ironic_networks: >-
{{ kolla_enable_ironic | bool and
inventory_hostname in groups['controllers'] }}
ironic_networks:
- network: "{{ provision_wl_net_name }}"
required: "{{ require_ironic_networks }}"
- network: "{{ cleaning_net_name }}"
required: "{{ require_ironic_networks }}"
require_provider_networks: >-
{{ kolla_enable_neutron | bool and
(inventory_hostname in groups['network'] or
(kolla_enable_neutron_provider_networks | bool and inventory_hostname in groups['compute'])) }}
# This expression generates a list containing an item for each network
# in external_net_names, in the format required by the
# external_networks argument of the kolla_ansible_host_vars action
# plugin.
provider_networks: >-
{{ dict(external_net_names |
zip_longest([], fillvalue=require_provider_networks)) |
dict2items(key_name='network', value_name='required') }}
kolla_ansible_host_vars:
interfaces:
- var_name: "kolla_network_interface"
description: "Default network"
network: "{{ internal_net_name }}"
required: True
- var_name: "kolla_api_interface"
description: "API network"
network: "{{ internal_net_name }}"
required: True
- var_name: "kolla_storage_interface"
description: "Storage network"
network: "{{ storage_net_name }}"
required: False
- var_name: "kolla_cluster_interface"
description: "Cluster network"
network: "{{ storage_mgmt_net_name }}"
required: False
- var_name: "kolla_swift_storage_interface"
description: "Swift storage network"
network: "{{ swift_storage_net_name }}"
required: False
- var_name: "kolla_swift_replication_interface"
description: "Swift storage replication network"
network: "{{ swift_storage_replication_net_name }}"
required: False
- var_name: "kolla_provision_interface"
description: "Bare metal provisioning network"
network: "{{ provision_wl_net_name }}"
required: "{{ kolla_enable_ironic | bool and inventory_hostname in groups['controllers'] }}"
- var_name: "kolla_inspector_dnsmasq_interface"
description: "Bare metal introspection network"
network: "{{ inspection_net_name }}"
required: "{{ kolla_enable_ironic | bool and inventory_hostname in groups['controllers'] }}"
- var_name: "kolla_dns_interface"
description: "DNS network"
network: "{{ public_net_name }}"
required: False
- var_name: "kolla_tunnel_interface"
description: "Tunnel network"
network: "{{ tunnel_net_name }}"
required: False
- var_name: "kolla_external_vip_interface"
description: "External network"
network: "{{ public_net_name }}"
required: "{{ inventory_hostname in groups['network'] }}"
external_networks: "{{ ironic_networks + provider_networks }}"
- import_role:
name: kolla-ansible-host-vars
vars:
kolla_ansible_pass_through_host_vars: "{{ kolla_overcloud_inventory_pass_through_host_vars }}"
kolla_ansible_pass_through_host_vars_map: "{{ kolla_overcloud_inventory_pass_through_host_vars_map }}"
kolla_ansible_inventory_path: "{{ kolla_config_path }}/inventory/overcloud"