diff --git a/ansible/filter_plugins/networks.py b/ansible/filter_plugins/networks.py index a6c19045f..b0e91f8ae 100644 --- a/ansible/filter_plugins/networks.py +++ b/ansible/filter_plugins/networks.py @@ -157,6 +157,11 @@ def net_is_bridge(context, name, inventory_hostname=None): return net_bridge_ports(context, name) is not None +@jinja2.contextfilter +def net_is_vlan(context, name, inventory_hostname=None): + return net_vlan(context, name) is not None + + @jinja2.contextfilter def net_select_ethers(context, names): return [name for name in names if net_is_ether(context, name)] @@ -167,6 +172,16 @@ def net_select_bridges(context, names): return [name for name in names if net_is_bridge(context, name)] +@jinja2.contextfilter +def net_select_vlans(context, names): + return [name for name in names if net_is_vlan(context, name)] + + +@jinja2.contextfilter +def net_reject_vlans(context, names): + return [name for name in names if not net_is_vlan(context, name)] + + @jinja2.contextfilter def net_configdrive_network_device(context, name, inventory_hostname=None): device = net_interface(context, name, inventory_hostname) @@ -212,7 +227,10 @@ class FilterModule(object): 'net_bridge_obj': net_bridge_obj, 'net_is_ether': net_is_ether, 'net_is_bridge': net_is_bridge, + 'net_is_vlan': net_is_vlan, 'net_select_ethers': net_select_ethers, 'net_select_bridges': net_select_bridges, + 'net_select_vlans': net_select_vlans, + 'net_reject_vlans': net_reject_vlans, 'net_configdrive_network_device': net_configdrive_network_device, } diff --git a/ansible/group_vars/all/ironic b/ansible/group_vars/all/ironic new file mode 100644 index 000000000..ac7f8b788 --- /dev/null +++ b/ansible/group_vars/all/ironic @@ -0,0 +1,16 @@ +--- +############################################################################### +# Ironic configuration. + +# List of enabled Ironic drivers. +kolla_ironic_drivers: + - agent_ssh + - agent_ipmitool + - pxe_ssh + - pxe_ipmitool + +# Name of the Neutron network to use for cleaning. +kolla_ironic_cleaning_network: 'provision-net' + +# Name of the Neutron network to use for provisioning. +kolla_ironic_provisioning_network: 'provision-net' diff --git a/ansible/ip-allocation.yml b/ansible/ip-allocation.yml index 167c59b34..c3f582385 100644 --- a/ansible/ip-allocation.yml +++ b/ansible/ip-allocation.yml @@ -20,6 +20,7 @@ }] }} with_items: "{{ network_interfaces }}" + when: "{{ item|net_cidr != None }}" roles: - role: ip-allocation ip_allocation_filename: "{{ kayobe_config_path }}/network-allocation.yml" diff --git a/ansible/kolla-ansible.yml b/ansible/kolla-ansible.yml index b8457efcd..d77de0ddb 100644 --- a/ansible/kolla-ansible.yml +++ b/ansible/kolla-ansible.yml @@ -52,24 +52,35 @@ 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: "{{ provision_wl_net_name | net_interface(controller_host) | replace('-', '_') }}" + # Initialise the following lists. + kolla_neutron_bridge_names: [] + kolla_neutron_external_interfaces: [] + kolla_neutron_bridge_interfaces: [] - - name: Set facts containing the Neutron bridge and interface names for the provisioning network + # 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_names: - - "{{ provision_wl_net_name | net_interface(controller_host) ~ network_bridge_suffix_ovs }}" - kolla_neutron_external_interfaces: - - "{{ network_patch_prefix ~ provision_wl_net_name | net_interface(controller_host) ~ network_patch_suffix_ovs }}" + kolla_neutron_bridge_interfaces: > + {{ kolla_neutron_bridge_interfaces | + union([item | net_interface(controller_host) | replace('.' ~ item | net_vlan(controller_host) | default('!nomatch!'), '')]) | + list }} + with_items: + - "{{ provision_wl_net_name }}" + - "{{ external_net_name }}" + when: "{{ item in hostvars[controller_host].network_interfaces }}" - - name: Update facts containing the Neutron bridge and interface names for the external network + - name: Set facts containing the Neutron bridge and interface names set_fact: kolla_neutron_bridge_names: > {{ kolla_neutron_bridge_names + - [external_net_name | net_interface(controller_host) ~ network_bridge_suffix_ovs] }} + [item ~ network_bridge_suffix_ovs] }} kolla_neutron_external_interfaces: > - {{ kolla_neutron_external_interfaces + - [network_patch_prefix ~ external_net_name | net_interface(controller_host) ~ network_patch_suffix_ovs] }} - when: - - "{{ provision_wl_net_name != external_net_name }}" + {{ kolla_neutron_bridge_names + + [network_patch_prefix ~ item ~ network_patch_suffix_ovs] }} + with_items: "{{ kolla_neutron_bridge_interfaces }}" - name: Validate controller Kolla Ansible network configuration fail: diff --git a/ansible/network.yml b/ansible/network.yml index 26e124ed2..41a01566d 100644 --- a/ansible/network.yml +++ b/ansible/network.yml @@ -1,6 +1,11 @@ --- - name: Ensure networking is configured hosts: seed:controllers + tags: + - config + vars: + ether_interfaces: "{{ network_interfaces | net_select_ethers | list }}" + bridge_interfaces: "{{ network_interfaces | net_select_bridges | list }}" pre_tasks: - block: - name: Validate network interface configuration @@ -8,7 +13,7 @@ msg: > Network interface validation failed - no interface configured for {{ item }}. This should be configured via '{{ item }}_interface'. - with_items: "{{ network_interfaces | net_select_ethers | list }}" + with_items: "{{ ether_interfaces }}" when: "{{ not item | net_interface }}" - name: Validate bridge interface configuration @@ -16,10 +21,9 @@ msg: > Bridge interface validation failed - no interface configured for {{ item }}. This should be configured via '{{ item }}_interface'. - with_items: "{{ network_interfaces | net_select_bridges | list }}" + with_items: "{{ bridge_interfaces }}" when: "{{ not item | net_interface }}" tags: - - config - config-validation - name: Ensure NetworkManager is disabled @@ -37,53 +41,67 @@ roles: - role: ahuffman.resolv become: True - tags: - - config + + # On the first pass we configure all ethernet interfaces that are not on + # VLANs and all bridges. On the second pass we configure all ethernet + # interfaces that are on VLANs. This allows us to specify VLAN interfaces + # on bridges. - role: MichaelRigart.interfaces interfaces_ether_interfaces: > - {{ network_interfaces | - net_select_ethers | + {{ ether_interfaces | + net_reject_vlans | map('net_interface_obj') | list }} interfaces_bridge_interfaces: > - {{ network_interfaces | - net_select_bridges | + {{ bridge_interfaces | map('net_bridge_obj') | list }} become: True - tags: - - config + - role: MichaelRigart.interfaces + interfaces_ether_interfaces: > + {{ ether_interfaces | + net_select_vlans | + map('net_interface_obj') | + list }} + become: True + +# Configure a virtual ethernet patch links to connect the workload provision +# and external network bridges to the Neutron OVS bridge. - name: Ensure controller workload OVS patch links exist hosts: controllers - roles: - # Configure a virtual ethernet patch link to connect the workload provision - # network bridge to the Neutron OVS bridge. - - role: veth - veth_interfaces: - - device: "{{ network_patch_prefix ~ provision_wl_net_name | net_interface ~ network_patch_suffix_phy }}" - bootproto: "static" - bridge: "{{ provision_wl_net_name | net_interface }}" - peer_device: "{{ network_patch_prefix ~ provision_wl_net_name | net_interface ~ network_patch_suffix_ovs }}" - peer_bootproto: "static" - onboot: yes - when: "{{ provision_wl_net_name in network_interfaces }}" - tags: - - config + tags: + - config + vars: + veth_bridges: [] + veth_interfaces: [] + pre_tasks: + # 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: Update a fact containing bridges to be patched to the Neutron OVS bridge + set_fact: + veth_bridges: > + {{ veth_bridges | + union([item | net_interface | replace('.' ~ item | net_vlan | default('!nomatch!'), '')]) | + list }} + with_items: + - "{{ provision_wl_net_name }}" + - "{{ external_net_name }}" + when: "{{ item in network_interfaces }}" - # Configure a virtual ethernet patch link to connect the external network - # bridge to the Neutron OVS bridge. + - name: Update a fact containing veth interfaces + set_fact: + veth_interfaces: > + {{ veth_interfaces + + [{'device': network_patch_prefix ~ item ~ network_patch_suffix_phy, + 'bootproto': 'static', + 'bridge': item, + 'peer_device': network_patch_prefix ~ item ~ network_patch_suffix_ovs, + 'peer_bootproto': 'static', + 'onboot': 'yes'}] }} + with_items: "{{ veth_bridges }}" + roles: - role: veth - veth_interfaces: - - device: "{{ network_patch_prefix ~ external_net_name | net_interface ~ network_patch_suffix_phy }}" - bootproto: "static" - bridge: "{{ external_net_name | net_interface }}" - peer_device: "{{ network_patch_prefix ~ external_net_name | net_interface ~ network_patch_suffix_ovs }}" - peer_bootproto: "static" - onboot: yes - when: - - "{{ external_net_name in network_interfaces }}" - - "{{ external_net_name != provision_wl_net_name }}" - tags: - - config diff --git a/ansible/provision-net.yml b/ansible/provision-net.yml index a9f1cd4f5..567f49d92 100644 --- a/ansible/provision-net.yml +++ b/ansible/provision-net.yml @@ -10,13 +10,13 @@ neutron_net_openstack_auth_type: "{{ openstack_auth_type }}" neutron_net_openstack_auth: "{{ openstack_auth }}" # Network configuration. - neutron_net_name: "provision-net" - neutron_net_type: "flat" + neutron_net_name: "{{ kolla_ironic_provisioning_network }}" + neutron_net_type: "{% if provision_wl_net_name | net_vlan %}vlan{% else %}flat{% endif %}" neutron_net_physical_network: "physnet1" - neutron_net_segmentation_id: + neutron_net_segmentation_id: "{{ provision_wl_net_name | net_vlan }}" neutron_net_shared: True # Subnet configuration. - neutron_net_subnet_name: "provision-subnet" + neutron_net_subnet_name: "{{ kolla_ironic_provisioning_network }}" neutron_net_cidr: "{{ provision_wl_net_name | net_cidr }}" neutron_net_gateway_ip: "{{ provision_wl_net_name | net_gateway }}" neutron_net_allocation_pool_start: "{{ provision_wl_net_name | net_allocation_pool_start }}" diff --git a/ansible/roles/kolla-openstack/defaults/main.yml b/ansible/roles/kolla-openstack/defaults/main.yml index 971c42a79..746aef5a5 100644 --- a/ansible/roles/kolla-openstack/defaults/main.yml +++ b/ansible/roles/kolla-openstack/defaults/main.yml @@ -6,12 +6,18 @@ kolla_node_custom_config_path: # Ironic configuration. # List of enabled Ironic drivers. -ironic_drivers: +kolla_ironic_drivers: - agent_ssh - agent_ipmitool - pxe_ssh - pxe_ipmitool +# Name or UUID of the Neutron network to use for cleaning. +kolla_ironic_cleaning_network: + +# Name or UUID of the Neutron network to use for provisioning. +kolla_ironic_provisioning_network: + # Free form extra configuration to append to ironic.conf. kolla_extra_ironic: diff --git a/ansible/roles/kolla-openstack/templates/ironic.conf.j2 b/ansible/roles/kolla-openstack/templates/ironic.conf.j2 index 9d01a7b3e..2b6d84a15 100644 --- a/ansible/roles/kolla-openstack/templates/ironic.conf.j2 +++ b/ansible/roles/kolla-openstack/templates/ironic.conf.j2 @@ -1,7 +1,7 @@ # {{ ansible_managed }} [DEFAULT] -enabled_drivers = {{ ironic_drivers | join(',') }} +enabled_drivers = {{ kolla_ironic_drivers | join(',') }} [conductor] {% raw %} @@ -11,6 +11,10 @@ api_url = {{ internal_protocol }}://{{ hostvars[inventory_hostname]['ansible_' + [agent] deploy_logs_local_path = /var/log/kolla/ironic/deploy +[neutron] +cleaning_network = {{ kolla_ironic_cleaning_network }} +provisioning_network = {{ kolla_ironic_provisioning_network }} + [pxe] {% raw %} tftp_server = {{ hostvars[inventory_hostname]['ansible_' + provision_interface | replace('-', '_')]['ipv4']['address'] }} diff --git a/etc/kayobe/ironic.yml b/etc/kayobe/ironic.yml new file mode 100644 index 000000000..6d9a3c526 --- /dev/null +++ b/etc/kayobe/ironic.yml @@ -0,0 +1,16 @@ +--- +############################################################################### +# Ironic configuration. + +# List of enabled Ironic drivers. +#kolla_ironic_drivers: + +# Name of the Neutron network to use for cleaning. +#kolla_ironic_cleaning_network: + +# Name of the Neutron network to use for provisioning. +#kolla_ironic_provisioning_network: + +############################################################################### +# Dummy variable to allow Ansible to accept this file. +workaround_ansible_issue_8743: yes