Use host vars files for kolla ansible inventory
Kayobe writes out several host variables to the Kolla ansible inventory files, etc/kolla/inventory/seed and etc/kolla/inventory/overcloud. These include ansible_host, and network interfaces such as api_interface, ironic_dnsmasq_interface, etc. In Ansible, these should have a higher precedence than the kolla ansible group variables in ansible/group_vars/all.yml that set the defaults. However, in Ansible 2.4+, if the host has the same name as a group that it is in, the group variables now take precedence, meaning that it is not possible to override them. This was observed when using the kayobe-config-dev repo for testing, where the seed host is in the seed group. Admittedly ansible does tell you not to do this: [WARNING]: Found both group and host with same name: localhost The solution used here is to use a separate host_vars file for each host. Alternatively we could enforce that hostnames and groups do not overlap. Change-Id: I349c8279d85a591689ac8108bce14d96889440fe Story: 2004418 Task: 28065
This commit is contained in:
parent
62aa5d015f
commit
8dc7ba7889
@ -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
|
- name: Ensure the Kolla Ansible configuration directories exist
|
||||||
file:
|
file:
|
||||||
path: "{{ item }}"
|
path: "{{ item }}"
|
||||||
@ -9,7 +36,8 @@
|
|||||||
become: True
|
become: True
|
||||||
with_items:
|
with_items:
|
||||||
- "{{ kolla_config_path }}"
|
- "{{ kolla_config_path }}"
|
||||||
- "{{ kolla_config_path }}/inventory"
|
- "{{ kolla_seed_inventory_path }}/host_vars"
|
||||||
|
- "{{ kolla_overcloud_inventory_path }}/host_vars"
|
||||||
- "{{ kolla_node_custom_config_path }}"
|
- "{{ kolla_node_custom_config_path }}"
|
||||||
|
|
||||||
- name: Ensure the Kolla global configuration file exists
|
- name: Ensure the Kolla global configuration file exists
|
||||||
@ -18,21 +46,42 @@
|
|||||||
dest: "{{ kolla_config_path }}/globals.yml"
|
dest: "{{ kolla_config_path }}/globals.yml"
|
||||||
mode: 0640
|
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
|
- name: Ensure the Kolla seed inventory file exists
|
||||||
copy:
|
copy:
|
||||||
content: "{{ kolla_seed_inventory }}"
|
content: "{{ kolla_seed_inventory }}"
|
||||||
dest: "{{ kolla_config_path }}/inventory/seed"
|
dest: "{{ kolla_seed_inventory_path }}/hosts"
|
||||||
mode: 0640
|
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
|
- name: Ensure the Kolla overcloud inventory file exists
|
||||||
copy:
|
copy:
|
||||||
content: "{{ kolla_overcloud_inventory }}"
|
content: "{{ kolla_overcloud_inventory }}"
|
||||||
dest: "{{ kolla_config_path }}/inventory/overcloud"
|
dest: "{{ kolla_overcloud_inventory_path }}/hosts"
|
||||||
mode: 0640
|
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
|
- name: Ensure the Kolla passwords file exists
|
||||||
kolla_passwords:
|
kolla_passwords:
|
||||||
src: "{{ kolla_ansible_passwords_path }}"
|
src: "{{ kolla_ansible_passwords_path }}"
|
||||||
|
7
ansible/roles/kolla-ansible/templates/host-vars.j2
Normal file
7
ansible/roles/kolla-ansible/templates/host-vars.j2
Normal file
@ -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 %}
|
@ -4,26 +4,17 @@
|
|||||||
# Components define groups of services, e.g. nova or ironic.
|
# Components define groups of services, e.g. nova or ironic.
|
||||||
# Services define single containers, e.g. nova-compute or ironic-api.
|
# Services define single containers, e.g. nova-compute or ironic-api.
|
||||||
|
|
||||||
{% set top_level_groups = kolla_overcloud_inventory_top_level_group_map.values() |
|
{% for group in kolla_overcloud_top_level_groups %}
|
||||||
selectattr('groups', 'defined') |
|
|
||||||
map(attribute='groups') |
|
|
||||||
sum(start=[]) |
|
|
||||||
unique |
|
|
||||||
list %}
|
|
||||||
|
|
||||||
{% for group in top_level_groups %}
|
|
||||||
# Top level {{ group }} group.
|
# Top level {{ group }} group.
|
||||||
[{{ group }}]
|
[{{ group }}]
|
||||||
# These hostnames must be resolvable from your deployment host
|
# These hostnames must be resolvable from your deployment host
|
||||||
{% for host in groups.get(group, []) %}
|
{% for host in groups.get(group, []) %}
|
||||||
{% set host_hv=hostvars[host] %}
|
{{ 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 %}
|
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
[overcloud:children]
|
[overcloud:children]
|
||||||
{% for group in top_level_groups %}
|
{% for group in kolla_overcloud_top_level_groups %}
|
||||||
{{ group }}
|
{{ group }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
# Simple inventory for bootstrapping Kolla seed node.
|
# Simple inventory for bootstrapping Kolla seed node.
|
||||||
[seed]
|
[seed]
|
||||||
{% for seed in groups.get('seed', []) %}
|
{% for seed in groups.get('seed', []) %}
|
||||||
{% set seed_hv=hostvars[seed] %}
|
{{ 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 %}
|
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
[seed:vars]
|
[seed:vars]
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
---
|
---
|
||||||
# TODO:
|
# TODO:
|
||||||
# - Check inventory file.
|
|
||||||
# - Add hosts to inventory.
|
|
||||||
# - Seed custom inventory
|
# - Seed custom inventory
|
||||||
# - Overcloud custom inventory
|
# - Overcloud custom inventory
|
||||||
# - Group map
|
# - Group map
|
||||||
|
@ -123,7 +123,9 @@
|
|||||||
path: "{{ temp_path ~ '/etc/kolla/inventory/' ~ item }}"
|
path: "{{ temp_path ~ '/etc/kolla/inventory/' ~ item }}"
|
||||||
with_items:
|
with_items:
|
||||||
- seed
|
- seed
|
||||||
|
- seed/host_vars
|
||||||
- overcloud
|
- overcloud
|
||||||
|
- overcloud/host_vars
|
||||||
register: inventory_stat
|
register: inventory_stat
|
||||||
|
|
||||||
- name: Validate inventory files
|
- name: Validate inventory files
|
||||||
|
@ -371,7 +371,7 @@
|
|||||||
|
|
||||||
- name: Check whether inventory files exist
|
- name: Check whether inventory files exist
|
||||||
stat:
|
stat:
|
||||||
path: "{{ temp_path ~ '/etc/kolla/inventory/' ~ item }}"
|
path: "{{ temp_path ~ '/etc/kolla/inventory/' ~ item ~ '/hosts' }}"
|
||||||
with_items:
|
with_items:
|
||||||
- seed
|
- seed
|
||||||
- overcloud
|
- overcloud
|
||||||
@ -398,7 +398,7 @@
|
|||||||
assert:
|
assert:
|
||||||
that: item in inventory_lines
|
that: item in inventory_lines
|
||||||
with_items:
|
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
|
- name: Validate overcloud inventory file contents
|
||||||
vars:
|
vars:
|
||||||
@ -406,8 +406,72 @@
|
|||||||
assert:
|
assert:
|
||||||
that: item in inventory_lines
|
that: item in inventory_lines
|
||||||
with_items:
|
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-controller
|
||||||
- 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-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:
|
always:
|
||||||
- name: Ensure the temporary directory is removed
|
- name: Ensure the temporary directory is removed
|
||||||
|
@ -51,6 +51,21 @@ kolla_overcloud_inventory_default: |
|
|||||||
# of the top level, component, and service inventories.
|
# of the top level, component, and service inventories.
|
||||||
kolla_overcloud_inventory: "{{ kolla_overcloud_inventory_custom or kolla_overcloud_inventory_default }}"
|
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.
|
# Feature configuration.
|
||||||
|
|
||||||
|
@ -87,8 +87,13 @@ def _validate_args(parsed_args, inventory_filename):
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
inventory = _get_inventory_path(parsed_args, inventory_filename)
|
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"]:
|
if not result["result"]:
|
||||||
|
# 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",
|
LOG.error("Kolla inventory %s is invalid: %s",
|
||||||
inventory, result["message"])
|
inventory, result["message"])
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -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
|
||||||
|
<https://storyboard.openstack.org/#!/story/2004418>`__ for details.
|
Loading…
Reference in New Issue
Block a user