diff --git a/ansible/roles/kolla-ansible/tasks/config.yml b/ansible/roles/kolla-ansible/tasks/config.yml index d28c64025..55849026c 100644 --- a/ansible/roles/kolla-ansible/tasks/config.yml +++ b/ansible/roles/kolla-ansible/tasks/config.yml @@ -1,4 +1,31 @@ --- +# NOTE: We're not looping over the two inventory files to avoid having the file +# content displayed in the ansible-playbook output. + +- name: Check whether the legacy Kolla overcloud inventory files exist + stat: + path: "{{ item }}" + get_attributes: no + get_checksum: no + get_mime: no + register: inventory_stat + with_items: + - "{{ kolla_seed_inventory_path }}" + - "{{ kolla_overcloud_inventory_path }}" + loop_control: + label: "{{ item | basename }}" + +- name: Ensure the legacy Kolla overcloud inventory file is absent + file: + path: "{{ item.item }}" + state: absent + with_items: "{{ inventory_stat.results }}" + when: + - item.stat.exists + - item.stat.isreg + loop_control: + label: "{{ item.item | basename }}" + - name: Ensure the Kolla Ansible configuration directories exist file: path: "{{ item }}" @@ -9,7 +36,8 @@ become: True with_items: - "{{ kolla_config_path }}" - - "{{ kolla_config_path }}/inventory" + - "{{ kolla_seed_inventory_path }}/host_vars" + - "{{ kolla_overcloud_inventory_path }}/host_vars" - "{{ kolla_node_custom_config_path }}" - name: Ensure the Kolla global configuration file exists @@ -18,21 +46,42 @@ dest: "{{ kolla_config_path }}/globals.yml" mode: 0640 -# NOTE: We're not looping over the two inventory files to avoid having the file -# content displayed in the ansible-playbook output. - - name: Ensure the Kolla seed inventory file exists copy: content: "{{ kolla_seed_inventory }}" - dest: "{{ kolla_config_path }}/inventory/seed" + dest: "{{ kolla_seed_inventory_path }}/hosts" mode: 0640 +- name: Ensure the Kolla seed host vars files exist + template: + src: host-vars.j2 + dest: "{{ kolla_seed_inventory_path }}/host_vars/{{ host }}" + mode: 0640 + with_inventory_hostnames: "seed" + vars: + host_vars: "{{ kolla_seed_inventory_pass_through_host_vars }}" + host_vars_map: "{{ kolla_seed_inventory_pass_through_host_vars_map }}" + loop_control: + loop_var: host + - name: Ensure the Kolla overcloud inventory file exists copy: content: "{{ kolla_overcloud_inventory }}" - dest: "{{ kolla_config_path }}/inventory/overcloud" + dest: "{{ kolla_overcloud_inventory_path }}/hosts" mode: 0640 +- name: Ensure the Kolla overcloud host vars files exist + template: + src: host-vars.j2 + dest: "{{ kolla_overcloud_inventory_path }}/host_vars/{{ host }}" + mode: 0640 + with_inventory_hostnames: "{{ kolla_overcloud_top_level_groups }}" + vars: + host_vars: "{{ kolla_overcloud_inventory_pass_through_host_vars }}" + host_vars_map: "{{ kolla_overcloud_inventory_pass_through_host_vars_map }}" + loop_control: + loop_var: host + - name: Ensure the Kolla passwords file exists kolla_passwords: src: "{{ kolla_ansible_passwords_path }}" diff --git a/ansible/roles/kolla-ansible/templates/host-vars.j2 b/ansible/roles/kolla-ansible/templates/host-vars.j2 new file mode 100644 index 000000000..eecc2eabf --- /dev/null +++ b/ansible/roles/kolla-ansible/templates/host-vars.j2 @@ -0,0 +1,7 @@ +--- +{% for hv_name in host_vars %} +{% set host_hv=hostvars[host] %} +{% if hv_name in host_hv %} +{{ host_vars_map.get(hv_name, hv_name) }}: {{ host_hv[hv_name] | to_json }} +{% endif %} +{% endfor %} diff --git a/ansible/roles/kolla-ansible/templates/overcloud-top-level.j2 b/ansible/roles/kolla-ansible/templates/overcloud-top-level.j2 index 6edf26dc5..ab736c1b8 100644 --- a/ansible/roles/kolla-ansible/templates/overcloud-top-level.j2 +++ b/ansible/roles/kolla-ansible/templates/overcloud-top-level.j2 @@ -4,26 +4,17 @@ # Components define groups of services, e.g. nova or ironic. # Services define single containers, e.g. nova-compute or ironic-api. -{% set top_level_groups = kolla_overcloud_inventory_top_level_group_map.values() | - selectattr('groups', 'defined') | - map(attribute='groups') | - sum(start=[]) | - unique | - list %} - -{% for group in top_level_groups %} +{% for group in kolla_overcloud_top_level_groups %} # Top level {{ group }} group. [{{ group }}] # These hostnames must be resolvable from your deployment host {% for host in groups.get(group, []) %} -{% set host_hv=hostvars[host] %} -{{ host }}{% for hv_name in kolla_overcloud_inventory_pass_through_host_vars %}{% if hv_name in host_hv %} {{ kolla_overcloud_inventory_pass_through_host_vars_map.get(hv_name, hv_name) }}='{{ host_hv[hv_name] | to_json }}'{% endif %}{% endfor %} - +{{ host }} {% endfor %} {% endfor %} [overcloud:children] -{% for group in top_level_groups %} +{% for group in kolla_overcloud_top_level_groups %} {{ group }} {% endfor %} diff --git a/ansible/roles/kolla-ansible/templates/seed.j2 b/ansible/roles/kolla-ansible/templates/seed.j2 index 0cc06ce45..18aa56610 100644 --- a/ansible/roles/kolla-ansible/templates/seed.j2 +++ b/ansible/roles/kolla-ansible/templates/seed.j2 @@ -1,9 +1,7 @@ # Simple inventory for bootstrapping Kolla seed node. [seed] {% for seed in groups.get('seed', []) %} -{% set seed_hv=hostvars[seed] %} -{{ seed }}{% for hv_name in kolla_seed_inventory_pass_through_host_vars %}{% if hv_name in seed_hv %} {{ kolla_seed_inventory_pass_through_host_vars_map.get(hv_name, hv_name) }}='{{ seed_hv[hv_name] | to_json }}'{% endif %}{% endfor %} - +{{ seed }} {% endfor %} [seed:vars] diff --git a/ansible/roles/kolla-ansible/tests/main.yml b/ansible/roles/kolla-ansible/tests/main.yml index e387e8baf..1451fa324 100644 --- a/ansible/roles/kolla-ansible/tests/main.yml +++ b/ansible/roles/kolla-ansible/tests/main.yml @@ -1,7 +1,5 @@ --- # TODO: -# - Check inventory file. -# - Add hosts to inventory. # - Seed custom inventory # - Overcloud custom inventory # - Group map diff --git a/ansible/roles/kolla-ansible/tests/test-defaults.yml b/ansible/roles/kolla-ansible/tests/test-defaults.yml index 0593afbcb..2771b7bef 100644 --- a/ansible/roles/kolla-ansible/tests/test-defaults.yml +++ b/ansible/roles/kolla-ansible/tests/test-defaults.yml @@ -123,7 +123,9 @@ path: "{{ temp_path ~ '/etc/kolla/inventory/' ~ item }}" with_items: - seed + - seed/host_vars - overcloud + - overcloud/host_vars register: inventory_stat - name: Validate inventory files diff --git a/ansible/roles/kolla-ansible/tests/test-extras.yml b/ansible/roles/kolla-ansible/tests/test-extras.yml index 84fba00cd..a7add8640 100644 --- a/ansible/roles/kolla-ansible/tests/test-extras.yml +++ b/ansible/roles/kolla-ansible/tests/test-extras.yml @@ -371,7 +371,7 @@ - name: Check whether inventory files exist stat: - path: "{{ temp_path ~ '/etc/kolla/inventory/' ~ item }}" + path: "{{ temp_path ~ '/etc/kolla/inventory/' ~ item ~ '/hosts' }}" with_items: - seed - overcloud @@ -398,7 +398,7 @@ assert: that: item in inventory_lines with_items: - - test-seed ansible_host='"1.2.3.4"' api_interface='"eth0"' bifrost_network_interface='"eth1"' + - test-seed - name: Validate overcloud inventory file contents vars: @@ -406,8 +406,72 @@ assert: that: item in inventory_lines with_items: - - test-controller ansible_host='"1.2.3.5"' network_interface='"eth0"' api_interface='"eth2"' storage_interface='"eth3"' cluster_interface='"eth4"' provision_interface='"eth8"' ironic_dnsmasq_interface='"eth9"' dns_interface='"eth5"' tunnel_interface='"eth10"' kolla_external_vip_interface='"eth1"' neutron_external_interface='"eth6,eth7"' neutron_bridge_name='"br0,br1"' - - test-compute ansible_host='"1.2.3.6"' network_interface='"eth0"' api_interface='"eth2"' storage_interface='"eth3"' tunnel_interface='"eth6"' neutron_external_interface='"eth4,eth5"' neutron_bridge_name='"br0,br1"' + - test-controller + - test-compute + + - name: Check whether inventory host vars files exist + stat: + path: "{{ temp_path ~ '/etc/kolla/inventory/' ~ item }}" + with_items: + - seed/host_vars/test-seed + - overcloud/host_vars/test-controller + - overcloud/host_vars/test-compute + register: host_vars_stat + + - name: Validate inventory host vars files + assert: + that: + - item.stat.exists + - item.stat.size > 0 + msg: > + Inventory file {{ item.item }} was not found. + with_items: "{{ host_vars_stat.results }}" + + - name: Read inventory host vars files + slurp: + src: "{{ item.stat.path }}" + with_items: "{{ host_vars_stat.results }}" + register: host_vars_slurp + + - name: Validate inventory host vars file contents + assert: + that: + - host_vars_content is defined + - host_vars_content == item.1 + with_together: + - "{{ host_vars_slurp.results }}" + - "{{ expected_contents }}" + vars: + host_vars_content: "{{ item.0.content | b64decode }}" + expected_contents: + - | + --- + ansible_host: "1.2.3.4" + api_interface: "eth0" + bifrost_network_interface: "eth1" + - | + --- + ansible_host: "1.2.3.5" + network_interface: "eth0" + api_interface: "eth2" + storage_interface: "eth3" + cluster_interface: "eth4" + provision_interface: "eth8" + ironic_dnsmasq_interface: "eth9" + dns_interface: "eth5" + tunnel_interface: "eth10" + kolla_external_vip_interface: "eth1" + neutron_external_interface: "eth6,eth7" + neutron_bridge_name: "br0,br1" + - | + --- + ansible_host: "1.2.3.6" + network_interface: "eth0" + api_interface: "eth2" + storage_interface: "eth3" + tunnel_interface: "eth6" + neutron_external_interface: "eth4,eth5" + neutron_bridge_name: "br0,br1" always: - name: Ensure the temporary directory is removed diff --git a/ansible/roles/kolla-ansible/vars/main.yml b/ansible/roles/kolla-ansible/vars/main.yml index 9cb6d9d50..378e464a4 100644 --- a/ansible/roles/kolla-ansible/vars/main.yml +++ b/ansible/roles/kolla-ansible/vars/main.yml @@ -51,6 +51,21 @@ kolla_overcloud_inventory_default: | # of the top level, component, and service inventories. kolla_overcloud_inventory: "{{ kolla_overcloud_inventory_custom or kolla_overcloud_inventory_default }}" +# List of names of all top level groups in the inventory. +kolla_overcloud_top_level_groups: > + {{ kolla_overcloud_inventory_top_level_group_map.values() | + selectattr('groups', 'defined') | + map(attribute='groups') | + sum(start=[]) | + unique | + list }} + +# Path to the kolla ansible seed inventory directory. +kolla_seed_inventory_path: "{{ kolla_config_path }}/inventory/seed" + +# Path to the kolla ansible overcloud inventory directory. +kolla_overcloud_inventory_path: "{{ kolla_config_path }}/inventory/overcloud" + ############################################################################### # Feature configuration. diff --git a/kayobe/kolla_ansible.py b/kayobe/kolla_ansible.py index 4aa9c94d3..312ed78ec 100644 --- a/kayobe/kolla_ansible.py +++ b/kayobe/kolla_ansible.py @@ -87,11 +87,16 @@ def _validate_args(parsed_args, inventory_filename): sys.exit(1) inventory = _get_inventory_path(parsed_args, inventory_filename) - result = utils.is_readable_file(inventory) + result = utils.is_readable_dir(parsed_args.kolla_venv) if not result["result"]: - LOG.error("Kolla inventory %s is invalid: %s", - inventory, result["message"]) - sys.exit(1) + # NOTE(mgoddard): Previously the inventory was a file, now it is a + # directory to allow us to support inventory host_vars. Support both + # formats for now. + result_f = utils.is_readable_file(inventory) + if not result_f["result"]: + LOG.error("Kolla inventory %s is invalid: %s", + inventory, result["message"]) + sys.exit(1) result = utils.is_readable_dir(parsed_args.kolla_venv) if not result["result"]: diff --git a/releasenotes/notes/kolla-inventory-host-vars-7f9dc14c82e3ea20.yaml b/releasenotes/notes/kolla-inventory-host-vars-7f9dc14c82e3ea20.yaml new file mode 100644 index 000000000..b3b0c6bf5 --- /dev/null +++ b/releasenotes/notes/kolla-inventory-host-vars-7f9dc14c82e3ea20.yaml @@ -0,0 +1,7 @@ +--- +fixes: + - | + Fixes an issue where if a host has the same name as a group that it is in, + configuration of kolla ansible inventory host variables could fail to + override the defaults. See `story 2004418 + `__ for details.