From bea399ef81c3f0280ff51cb0558c8c02422fcbaf Mon Sep 17 00:00:00 2001 From: Mark Goddard Date: Fri, 13 Apr 2018 14:39:00 +0100 Subject: [PATCH] Per-host network interface configuration Adds support for configuration of per-host network interfaces in Kolla Ansible. Previously, all interfaces were configured in globals.yml, meaning that all hosts used the same interface names. Now, interfaces are configured for each host via inventory files. This does have the drawback that host entries in the inventory are rather long and not too readable. An improvement on this could be to generate host_vars files. With a little more intelligence, it would be possible to use group_vars files or even globals.yml when interfaces are uniform within a group or globally. Change-Id: I95a128d762ff9faf70467f83cb276a5ab619d1ea Story: 2001658 Task: 6691 --- ansible/kolla-ansible.yml | 278 ++++++++++-------- ansible/roles/kolla-ansible/defaults/main.yml | 88 +++--- .../kolla-ansible/templates/globals.yml.j2 | 32 +- .../templates/overcloud-top-level.j2 | 2 +- ansible/roles/kolla-ansible/templates/seed.j2 | 3 +- .../kolla-ansible/tests/test-defaults.yml | 38 +-- .../roles/kolla-ansible/tests/test-extras.yml | 130 ++++++-- .../per-host-interfaces-6e548331fa3a4244.yaml | 7 + 8 files changed, 325 insertions(+), 253 deletions(-) create mode 100644 releasenotes/notes/per-host-interfaces-6e548331fa3a4244.yaml diff --git a/ansible/kolla-ansible.yml b/ansible/kolla-ansible.yml index 4b355d94b..5eaab07ab 100644 --- a/ansible/kolla-ansible.yml +++ b/ansible/kolla-ansible.yml @@ -3,13 +3,86 @@ hosts: overcloud tags: - config + - config-validation - kolla-ansible gather_facts: False + vars: + 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'])) }} tasks: - - name: Set API interface + - name: Set API network interface set_fact: + kolla_network_interface: "{{ internal_net_name | net_interface | replace('-', '_') }}" kolla_api_interface: "{{ internal_net_name | net_interface | replace('-', '_') }}" when: internal_net_name in network_interfaces + + - name: Set storage network interface + set_fact: + kolla_storage_interface: "{{ storage_net_name | net_interface | replace('-', '_') }}" + when: storage_net_name in network_interfaces + + - name: Set cluster network interface + set_fact: + kolla_cluster_interface: "{{ storage_mgmt_net_name | net_interface | replace('-', '_') }}" + when: storage_mgmt_net_name in network_interfaces + + - name: Set provision network interface + set_fact: + kolla_provision_interface: "{{ provision_wl_net_name | net_interface | replace('-', '_') }}" + when: provision_wl_net_name in network_interfaces + + - name: Set inspector dnsmasq network interface + set_fact: + kolla_inspector_dnsmasq_interface: "{{ inspection_net_name | net_interface | replace('-', '_') }}" + when: inspection_net_name in network_interfaces + + - name: Set DNS network interface + set_fact: + kolla_dns_interface: "{{ public_net_name | net_interface | replace('-', '_') }}" + when: public_net_name in network_interfaces + + - name: Set tunnel network interface + set_fact: + kolla_tunnel_interface: "{{ tunnel_net_name | net_interface | replace('-', '_') }}" + when: tunnel_net_name in network_interfaces + + - name: Set external VIP interface + set_fact: + kolla_external_vip_interface: "{{ public_net_name | net_interface | replace('-', '_') }}" + when: public_net_name in network_interfaces + + - name: Initialise facts containing the network host interfaces + set_fact: + # Initialise the following lists. + kolla_neutron_bridge_interfaces: [] + kolla_neutron_bridge_names: [] + kolla_neutron_external_interfaces: [] + + # When these networks are VLANs, we need to use the underlying tagged + # bridge interface rather than the untagged interface. We therefore + # strip the . suffix of the interface name. We use a union here + # as a single tagged interface may be shared between these networks. + - name: Set a fact containing the bridges to be patched to the Neutron OVS bridges + set_fact: + kolla_neutron_bridge_interfaces: > + {{ kolla_neutron_bridge_interfaces | + union([item | net_interface | replace('.' ~ item | net_vlan | default('!nomatch!'), '')]) | + list }} + with_items: "{{ [provision_wl_net_name, cleaning_net_name] + external_net_names | unique | list }}" + when: item in network_interfaces + + - name: Set facts containing the Neutron bridge and interface names + set_fact: + kolla_neutron_bridge_names: > + {{ kolla_neutron_bridge_names + + [item ~ network_bridge_suffix_ovs] }} + kolla_neutron_external_interfaces: > + {{ kolla_neutron_external_interfaces + + [network_patch_prefix ~ item ~ network_patch_suffix_ovs] }} + with_items: "{{ kolla_neutron_bridge_interfaces }}" + - name: Validate overcloud host Kolla Ansible network configuration fail: msg: > @@ -23,20 +96,91 @@ - var_name: "kolla_api_interface" description: "API network interface name" required: True + - var_name: "kolla_external_vip_interface" + description: "External network interface name" + required: "{{ inventory_hostname in groups['network'] }}" + - var_name: "kolla_provision_interface" + description: "Bare metal provisioning network interface name" + required: "{{ kolla_enable_ironic | bool and inventory_hostname in groups['controllers'] }}" + - var_name: "kolla_inspector_dnsmasq_interface" + description: "Bare metal introspection network interface name" + required: "{{ kolla_enable_ironic | bool and inventory_hostname in groups['controllers'] }}" + - var_name: "kolla_neutron_bridge_names" + description: "List of Neutron bridge names" + required: "{{ require_provider_networks }}" + - var_name: "kolla_neutron_external_interfaces" + description: "List of Neutron interface names" + required: "{{ require_provider_networks }}" + + - name: Validate Kolla Ansible Neutron bridge and interface configuration + fail: + msg: > + The Kolla Ansible variable {{ item.0.var_name }} + ({{ item.0.description }}) is invalid. Value: + "{{ item.1 | default('') }}". + when: + - item.0.required | bool + - item.1 is not defined or not item.1 + with_subelements: + - - var_name: "kolla_neutron_bridge_names" + value: "{{ kolla_neutron_bridge_names }}" + description: "List of Neutron bridge names" + required: "{{ require_provider_networks }}" + - var_name: "kolla_neutron_external_interfaces" + value: "{{ kolla_neutron_external_interfaces }}" + description: "List of Neutron interface names" + required: "{{ require_provider_networks }}" + - value + + # Kolla ansible expects these variables to be comma-separated lists. + - name: Update facts containing the Neutron bridge and interface names + set_fact: + kolla_neutron_bridge_names: "{{ kolla_neutron_bridge_names | join(',') }}" + kolla_neutron_external_interfaces: "{{ kolla_neutron_external_interfaces | join(',') }}" + +- name: Set interfaces for the seed host + hosts: seed + tags: + - config + - config-validation + - kolla-ansible + gather_facts: False + tasks: + - name: Set bifrost network interface + set_fact: + kolla_bifrost_network_interface: "{{ provision_oc_net_name | net_interface | replace('-', '_') }}" + when: provision_oc_net_name in network_interfaces + + - name: Validate seed Kolla Ansible network configuration + fail: + msg: > + The Kolla Ansible variable {{ item.var_name }} + ({{ item.description }}) is invalid. Value: + "{{ hostvars[inventory_hostname][item.var_name] | default('') }}". + 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_bifrost_network_interface" + description: "Bifrost network interface name" + required: True + + # Strictly api_interface is not required but kolla-ansible currently + # references it in prechecks. + - name: Set API network interface + set_fact: + kolla_api_interface: "{{ kolla_bifrost_network_interface }}" - name: Ensure Kolla Ansible is configured hosts: localhost tags: - kolla-ansible vars: - # We need to reference configuration for the controller and seed nodes. - # We pick the first host from each group for this. It is possible that at + # 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. - # NOTE: Per-host configuration is not currently supported. - controller_host: "{{ groups['controllers'][0] }}" network_host: "{{ groups['network'][0] }}" - seed_host: "{{ groups['seed'][0] }}" pre_tasks: # Configuration of extra user-provided Kolla globals. - block: @@ -55,39 +199,6 @@ tags: - config - # Configuration and validation of controller networking. - - block: - - name: Set facts containing the controller network interfaces - set_fact: - kolla_network_interface: "{{ internal_net_name | net_interface(controller_host) | replace('-', '_') }}" - kolla_storage_interface: "{{ storage_net_name | net_interface(controller_host) | replace('-', '_') }}" - kolla_cluster_interface: "{{ storage_mgmt_net_name | net_interface(controller_host) | replace('-', '_') }}" - kolla_provision_interface: "{{ provision_wl_net_name | net_interface(controller_host) | replace('-', '_') }}" - kolla_inspector_dnsmasq_interface: "{{ inspection_net_name | net_interface(controller_host) | replace('-', '_') }}" - kolla_dns_interface: "{{ public_net_name | net_interface(controller_host) | replace('-', '_') }}" - kolla_tunnel_interface: "{{ tunnel_net_name | net_interface(controller_host) | replace('-', '_') }}" - - - name: Validate controller Kolla Ansible network configuration - fail: - msg: > - The Kolla Ansible variable {{ item.var_name }} - ({{ item.description }}) is invalid. Value: - "{{ hostvars[inventory_hostname][item.var_name] | default('') }}". - 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_provision_interface" - description: "Bare metal provisioning network interface name" - required: "{{ kolla_enable_ironic }}" - - var_name: "kolla_inspector_dnsmasq_interface" - description: "Bare metal introspection network interface name" - required: "{{ kolla_enable_ironic }}" - when: groups['controllers'] | length > 0 - tags: - - config - - config-validation - # Configuration and validation of network host networking. - block: - name: Set facts containing the VIP addresses and FQDNs @@ -106,41 +217,7 @@ kolla_external_fqdn: "{{ public_net_name | net_ip(network_host) }}" when: not kolla_enable_haproxy | bool - - name: Set facts containing the network host interfaces - set_fact: - kolla_external_vip_interface: "{{ public_net_name | net_interface(network_host) | replace('-', '_') }}" - - - name: Initialise facts containing the network host interfaces - set_fact: - # Initialise the following lists. - kolla_neutron_bridge_names: [] - kolla_neutron_external_interfaces: [] - kolla_neutron_bridge_interfaces: [] - - # When these networks are VLANs, we need to use the underlying tagged - # bridge interface rather than the untagged interface. We therefore - # strip the . suffix of the interface name. We use a union here - # as a single tagged interface may be shared between these networks. - - name: Set a fact containing the bridges to be patched to the Neutron OVS bridges - set_fact: - kolla_neutron_bridge_interfaces: > - {{ kolla_neutron_bridge_interfaces | - union([item | net_interface(network_host) | replace('.' ~ item | net_vlan(network_host) | default('!nomatch!'), '')]) | - list }} - with_items: "{{ [provision_wl_net_name, cleaning_net_name] + external_net_names | unique | list }}" - when: item in hostvars[network_host].network_interfaces - - - name: Set facts containing the Neutron bridge and interface names - set_fact: - kolla_neutron_bridge_names: > - {{ kolla_neutron_bridge_names + - [item ~ network_bridge_suffix_ovs] }} - kolla_neutron_external_interfaces: > - {{ kolla_neutron_external_interfaces + - [network_patch_prefix ~ item ~ network_patch_suffix_ovs] }} - with_items: "{{ kolla_neutron_bridge_interfaces }}" - - - name: Validate network host Kolla Ansible network configuration + - name: Validate Kolla Ansible API address configuration fail: msg: > The Kolla Ansible variable {{ item.var_name }} @@ -162,64 +239,11 @@ - var_name: "kolla_external_fqdn" description: "External API Fully Qualified Domain Name (FQDN)" required: True - - var_name: "kolla_external_vip_interface" - description: "External network interface name" - required: True - - var_name: "kolla_neutron_bridge_names" - description: "List of Neutron bridge names" - required: True - - var_name: "kolla_neutron_external_interfaces" - description: "List of Neutron interface names" - required: True - - - name: Validate network host Kolla Ansible Neutron bridge and interface configuration - fail: - msg: > - The Kolla Ansible variable {{ item.0.var_name }} - ({{ item.0.description }}) is invalid. Value: - "{{ item.1 | default('') }}". - when: - - item.0.required | bool - - item.1 is not defined or not item.1 - with_subelements: - - - var_name: "kolla_neutron_bridge_names" - value: "{{ kolla_neutron_bridge_names }}" - description: "List of Neutron bridge names" - required: True - - var_name: "kolla_neutron_external_interfaces" - value: "{{ kolla_neutron_external_interfaces }}" - description: "List of Neutron interface names" - required: True - - value when: groups['network'] | length > 0 tags: - config - config-validation - # Configuration and validation of seed networking. - - block: - - name: Set facts containing the seed network interfaces - set_fact: - kolla_bifrost_network_interface: "{{ provision_oc_net_name | net_interface(seed_host) | replace('-', '_') }}" - - - name: Validate seed Kolla Ansible network configuration - fail: - msg: > - The Kolla Ansible variable {{ item.var_name }} - ({{ item.description }}) is invalid. Value: - "{{ hostvars[inventory_hostname][item.var_name] | default('') }}". - 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_bifrost_network_interface" - description: "Bifrost network interface name" - required: True - when: groups['seed'] | length > 0 - tags: - - config - - config-validation - roles: - role: kolla-ansible kolla_ansible_install_epel: "{{ yum_install_epel }}" diff --git a/ansible/roles/kolla-ansible/defaults/main.yml b/ansible/roles/kolla-ansible/defaults/main.yml index 51b4600e9..5b4c521db 100644 --- a/ansible/roles/kolla-ansible/defaults/main.yml +++ b/ansible/roles/kolla-ansible/defaults/main.yml @@ -54,6 +54,24 @@ kolla_ansible_become: true # Full custom seed inventory contents. kolla_seed_inventory_custom: +# List of names of host variables to pass through from kayobe hosts to +# the kolla-ansible seed host, if set. See also +# kolla_seed_inventory_pass_through_host_vars_map. +kolla_seed_inventory_pass_through_host_vars: + - "ansible_host" + - "ansible_port" + - "ansible_ssh_private_key_file" + - "kolla_api_interface" + - "kolla_bifrost_network_interface" + +# Dict mapping names of variables in +# kolla_seed_inventory_pass_through_host_vars to the variable to use in +# kolla-ansible. If a variable name is not in this mapping the kayobe name is +# used. +kolla_seed_inventory_pass_through_host_vars_map: + kolla_api_interface: "api_interface" + kolla_bifrost_network_interface: "bifrost_network_interface" + # Custom overcloud inventory containing a mapping from top level groups to # hosts. kolla_overcloud_inventory_custom_top_level: @@ -81,12 +99,39 @@ kolla_overcloud_inventory_top_level_group_map: {} kolla_overcloud_inventory_kolla_top_level_groups: [] # List of names of host variables to pass through from kayobe hosts to -# kolla-ansible hosts, if set. +# kolla-ansible hosts, if set. See also +# kolla_overcloud_inventory_pass_through_host_vars_map. kolla_overcloud_inventory_pass_through_host_vars: - "ansible_host" - "ansible_port" - "ansible_ssh_private_key_file" + - "kolla_network_interface" - "kolla_api_interface" + - "kolla_storage_interface" + - "kolla_cluster_interface" + - "kolla_provision_interface" + - "kolla_inspector_dnsmasq_interface" + - "kolla_dns_interface" + - "kolla_tunnel_interface" + - "kolla_external_vip_interface" + - "kolla_neutron_external_interfaces" + - "kolla_neutron_bridge_names" + +# Dict mapping names of variables in +# kolla_seed_inventory_pass_through_host_vars to the variable to use in +# kolla-ansible. If a variable name is not in this mapping the kayobe name is +# used. +kolla_overcloud_inventory_pass_through_host_vars_map: + kolla_network_interface: "network_interface" + kolla_api_interface: "api_interface" + kolla_storage_interface: "storage_interface" + kolla_cluster_interface: "cluster_interface" + kolla_provision_interface: "provision_interface" + kolla_inspector_dnsmasq_interface: "inspector_dnsmasq_interface" + kolla_dns_interface: "dns_interface" + kolla_tunnel_interface: "tunnel_interface" + kolla_neutron_external_interfaces: "neutron_external_interface" + kolla_neutron_bridge_names: "neutron_bridge_name" ############################################################################### # Kolla-ansible global configuration options. @@ -138,47 +183,6 @@ kolla_external_fqdn: #################### # Networking options #################### -# This interface is what all your api services will be bound to by default. -# Additionally, all vxlan/tunnel and storage network traffic will go over this -# interface by default. This interface must contain an IPv4 address. -# It is possible for hosts to have non-matching names of interfaces - these can -# be set in an inventory file per host or per group or stored separately, see -# http://docs.ansible.com/ansible/intro_inventory.html -# Yet another way to workaround the naming problem is to create a bond for the -# interface on all hosts and give the bond name here. Similar strategy can be -# followed for other types of interfaces. -kolla_network_interface: - -# These can be adjusted for even more customization. The default is the same as -# the 'network_interface'. These interfaces must contain an IPv4 address. -kolla_external_vip_interface: -kolla_api_interface: -kolla_storage_interface: -kolla_cluster_interface: -kolla_dns_interface: -kolla_tunnel_interface: - -# This is the raw interface given to neutron as its external network port. Even -# though an IP address can exist on this interface, it will be unusable in most -# configurations. It is recommended this interface not be configured with any IP -# addresses for that reason. -# This should be a list of names of interfaces. -kolla_neutron_external_interfaces: [] - -# List of names of Neutron bridges. -kolla_neutron_bridge_names: [] - -# This is the interface to use for Bifrost bare metal provisioning of the -# control plane. -kolla_bifrost_network_interface: - -# This is the interface to use for bare metal provisioning. It is not a -# standard kolla variable. -kolla_provision_interface: - -# Interface on which the inspector dnsmasq service listens. -kolla_inspector_dnsmasq_interface: - # List of Neutron ML2 type drivers to use. kolla_neutron_ml2_type_drivers: [] diff --git a/ansible/roles/kolla-ansible/templates/globals.yml.j2 b/ansible/roles/kolla-ansible/templates/globals.yml.j2 index c9d54e77c..6835ba163 100644 --- a/ansible/roles/kolla-ansible/templates/globals.yml.j2 +++ b/ansible/roles/kolla-ansible/templates/globals.yml.j2 @@ -95,36 +95,8 @@ docker_registry_password: "{{ kolla_docker_registry_password }}" # interface on all hosts and give the bond name here. Similar strategy can be # followed for other types of interfaces. # -# NOTE: The following interfaces are configured via the inventory and are -# therefore not set here: -# -# - api_interface - -network_interface: "{{ kolla_network_interface }}" - -# These can be adjusted for even more customization. The default is the same as -# the 'network_interface'. These interfaces must contain an IPv4 address. -kolla_external_vip_interface: "{{ kolla_external_vip_interface }}" -storage_interface: "{{ kolla_storage_interface }}" -cluster_interface: "{{ kolla_cluster_interface }}" -dns_interface: "{{ kolla_dns_interface }}" -tunnel_interface: "{{ kolla_tunnel_interface }}" - -# This is the raw interface given to neutron as its external network port. Even -# though an IP address can exist on this interface, it will be unusable in most -# configurations. It is recommended this interface not be configured with any IP -# addresses for that reason. -neutron_external_interface: "{{ kolla_neutron_external_interfaces | join(',') }}" - -# Name of the Neutron external bridge. -neutron_bridge_name: "{{ kolla_neutron_bridge_names | join(',') }}" - -# This is the interface to use for Bifrost bare metal provisioning of the -# control plane. -bifrost_network_interface: "{{ kolla_bifrost_network_interface }}" - -# Interface on which the inspector dnsmasq service listens. -ironic_dnsmasq_interface: "{{ kolla_inspector_dnsmasq_interface }}" +# NOTE: Most network interfaces are configured via the inventory and are +# therefore not set here. # Valid options are [ openvswitch, linuxbridge ] neutron_plugin_agent: "openvswitch" diff --git a/ansible/roles/kolla-ansible/templates/overcloud-top-level.j2 b/ansible/roles/kolla-ansible/templates/overcloud-top-level.j2 index dadf1f154..6edf26dc5 100644 --- a/ansible/roles/kolla-ansible/templates/overcloud-top-level.j2 +++ b/ansible/roles/kolla-ansible/templates/overcloud-top-level.j2 @@ -17,7 +17,7 @@ # 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 %} {{ hv_name | regex_replace('^kolla_(.*)$', '\1') }}={{ host_hv[hv_name] }}{% endif %}{% endfor %} +{{ 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 %} diff --git a/ansible/roles/kolla-ansible/templates/seed.j2 b/ansible/roles/kolla-ansible/templates/seed.j2 index bc66951c8..0cc06ce45 100644 --- a/ansible/roles/kolla-ansible/templates/seed.j2 +++ b/ansible/roles/kolla-ansible/templates/seed.j2 @@ -2,7 +2,8 @@ [seed] {% for seed in groups.get('seed', []) %} {% set seed_hv=hostvars[seed] %} -{{ seed }}{% if "ansible_host" in seed_hv %} ansible_host={{ seed_hv["ansible_host"] }}{% endif %} +{{ 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 %} [seed:vars] diff --git a/ansible/roles/kolla-ansible/tests/test-defaults.yml b/ansible/roles/kolla-ansible/tests/test-defaults.yml index c20daf845..bf43091b9 100644 --- a/ansible/roles/kolla-ansible/tests/test-defaults.yml +++ b/ansible/roles/kolla-ansible/tests/test-defaults.yml @@ -29,22 +29,6 @@ kolla_internal_fqdn: "fake.internal.fqdn" kolla_external_vip_address: "10.0.0.2" kolla_external_fqdn: "fake.external.fqdn" - kolla_network_interface: "eth0" - kolla_external_vip_interface: "eth1" - kolla_api_interface: "eth2" - kolla_storage_interface: "eth3" - kolla_cluster_interface: "eth4" - kolla_dns_interface: "eth5" - kolla_neutron_external_interfaces: - - "eth6" - - "eth7" - kolla_neutron_bridge_names: - - "br0" - - "br1" - kolla_bifrost_network_interface: "eth8" - kolla_provision_interface: "eth9" - kolla_inspector_dnsmasq_interface: "eth10" - kolla_tunnel_interface: "eth11" kolla_enable_tls_external: False kolla_enable_grafana: False kolla_external_fqdn_cert: "fake-cert" @@ -83,16 +67,6 @@ kolla_external_fqdn: "fake.external.fqdn" node_custom_config: "{{ temp_path }}/etc/kolla/config" docker_namespace: "fake-namespace" - network_interface: "eth0" - kolla_external_vip_interface: "eth1" - storage_interface: "eth3" - cluster_interface: "eth4" - dns_interface: "eth5" - neutron_external_interface: "eth6,eth7" - neutron_bridge_name: "br0,br1" - bifrost_network_interface: "eth8" - ironic_dnsmasq_interface: "eth10" - tunnel_interface: "eth11" neutron_plugin_agent: "openvswitch" kolla_enable_tls_external: False kolla_external_fqdn_cert: "fake-cert" @@ -127,6 +101,18 @@ - enable_nova - enable_zookeeper - grafana_admin_username + - network_interface + - api_interface + - kolla_external_vip_interface + - storage_interface + - cluster_interface + - provision_interface + - inspector_dnsmasq_interface + - dns_interface + - tunnel_interface + - bifrost_network_interface + - neutron_external_interface + - neutron_bridge_name - name: Check whether inventory files exist stat: diff --git a/ansible/roles/kolla-ansible/tests/test-extras.yml b/ansible/roles/kolla-ansible/tests/test-extras.yml index 96219798a..ef54c05e0 100644 --- a/ansible/roles/kolla-ansible/tests/test-extras.yml +++ b/ansible/roles/kolla-ansible/tests/test-extras.yml @@ -2,6 +2,43 @@ - hosts: localhost connection: local tasks: + - name: Add a seed host to the inventory + add_host: + name: test-seed + groups: seed + ansible_host: "1.2.3.4" + kolla_api_interface: "eth0" + kolla_bifrost_network_interface: "eth1" + + - name: Add a controller host to the inventory + add_host: + name: test-controller + groups: controllers + ansible_host: "1.2.3.5" + kolla_network_interface: "eth0" + kolla_external_vip_interface: "eth1" + kolla_api_interface: "eth2" + kolla_storage_interface: "eth3" + kolla_cluster_interface: "eth4" + kolla_dns_interface: "eth5" + kolla_neutron_external_interfaces: "eth6,eth7" + kolla_neutron_bridge_names: "br0,br1" + kolla_provision_interface: "eth8" + kolla_inspector_dnsmasq_interface: "eth9" + kolla_tunnel_interface: "eth10" + + - name: Add a compute host to the inventory + add_host: + name: test-compute + groups: compute + ansible_host: "1.2.3.6" + kolla_network_interface: "eth0" + kolla_api_interface: "eth2" + kolla_storage_interface: "eth3" + kolla_neutron_external_interfaces: "eth4,eth5" + kolla_neutron_bridge_names: "br0,br1" + kolla_tunnel_interface: "eth6" + - name: Create a temporary directory tempfile: state: directory @@ -36,22 +73,17 @@ kolla_internal_fqdn: "fake.internal.fqdn" kolla_external_vip_address: "10.0.0.2" kolla_external_fqdn: "fake.external.fqdn" - kolla_network_interface: "eth0" - kolla_external_vip_interface: "eth1" - kolla_api_interface: "eth2" - kolla_storage_interface: "eth3" - kolla_cluster_interface: "eth4" - kolla_dns_interface: "eth5" - kolla_neutron_external_interfaces: - - "eth6" - - "eth7" - kolla_neutron_bridge_names: - - "br0" - - "br1" - kolla_bifrost_network_interface: "eth8" - kolla_provision_interface: "eth9" - kolla_inspector_dnsmasq_interface: "eth10" - kolla_tunnel_interface: "eth11" + # Inventory mapping. + kolla_overcloud_inventory_top_level_group_map: + control: + groups: + - controllers + compute: + groups: + - compute + kolla_overcloud_inventory_kolla_top_level_groups: + - "control" + - "compute" kolla_neutron_ml2_type_drivers: - "fake-ml2-type-1" - "fake-ml2-type-2" @@ -183,16 +215,6 @@ docker_registry: "fake-registry" docker_registry_username: "fake-username" docker_registry_password: "fake-password" - network_interface: "eth0" - kolla_external_vip_interface: "eth1" - storage_interface: "eth3" - cluster_interface: "eth4" - dns_interface: "eth5" - neutron_external_interface: "eth6,eth7" - neutron_bridge_name: "br0,br1" - bifrost_network_interface: "eth8" - ironic_dnsmasq_interface: "eth10" - tunnel_interface: "eth11" neutron_plugin_agent: "openvswitch" kolla_enable_tls_external: False kolla_external_fqdn_cert: "fake-cert" @@ -286,6 +308,18 @@ - enable_ironic - enable_neutron - enable_nova + - network_interface + - api_interface + - kolla_external_vip_interface + - storage_interface + - cluster_interface + - provision_interface + - inspector_dnsmasq_interface + - dns_interface + - tunnel_interface + - bifrost_network_interface + - neutron_external_interface + - neutron_bridge_name - name: Create a vault password file copy: @@ -326,11 +360,55 @@ expected_variables: custom-password-1: custom-password-1 custom-password-2: custom-password-2 + + - name: Check whether inventory files exist + stat: + path: "{{ temp_path ~ '/etc/kolla/inventory/' ~ item }}" + with_items: + - seed + - overcloud + register: inventory_stat + + - name: Validate inventory files + assert: + that: + - item.stat.exists + - item.stat.size > 0 + msg: > + Inventory file {{ item.item }} was not found. + with_items: "{{ inventory_stat.results }}" + + - name: Read inventory files + slurp: + src: "{{ item.stat.path }}" + with_items: "{{ inventory_stat.results }}" + register: inventory_slurp + + - name: Validate seed inventory file contents + vars: + inventory_lines: "{{ (inventory_slurp.results[0].content | b64decode).splitlines() }}" + assert: + that: item in inventory_lines + with_items: + - test-seed ansible_host='"1.2.3.4"' api_interface='"eth0"' bifrost_network_interface='"eth1"' + + - name: Validate overcloud inventory file contents + vars: + inventory_lines: "{{ (inventory_slurp.results[1].content | b64decode).splitlines() }}" + 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"' inspector_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"' + always: - name: Ensure the temporary directory is removed file: path: "{{ temp_path }}" state: absent + + - name: Refresh the inventory + meta: refresh_inventory rescue: - name: Flag that a failure occurred set_fact: diff --git a/releasenotes/notes/per-host-interfaces-6e548331fa3a4244.yaml b/releasenotes/notes/per-host-interfaces-6e548331fa3a4244.yaml new file mode 100644 index 000000000..edc46d7b2 --- /dev/null +++ b/releasenotes/notes/per-host-interfaces-6e548331fa3a4244.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + Adds support for configuration of per-host network interfaces in Kolla + Ansible. Previously, all interfaces were configured in ``globals.yml``, + meaning that all hosts used the same interface names. Now, interfaces are + configured for each host via inventory files.