Support Neutron VLAN networks
For VLAN networks we need to use a tagged Linux bridge on the controller with a veth pair to link it to the corresponding Neutron OVS bridge. This must be done for the physical network(s) carrying the provisioning, tenant, and external network traffic. We also need untagged VLAN subinterfaces on the tagged bridge for the controller to communicate on these networks with. The network interface role in use requires that we use two passes through interface configuration to ensure that VLAN subinterfaces can be added to bridge interfaces. Finally, we must configure Ironic with the name of the Neutron network used for provisioning.
This commit is contained in:
parent
7b2be06725
commit
26be2c5af3
@ -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,
|
||||
}
|
||||
|
16
ansible/group_vars/all/ironic
Normal file
16
ansible/group_vars/all/ironic
Normal file
@ -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'
|
@ -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"
|
||||
|
@ -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 .<vlan> 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:
|
||||
|
@ -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 .<vlan> 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
|
||||
|
@ -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 }}"
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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'] }}
|
||||
|
16
etc/kayobe/ironic.yml
Normal file
16
etc/kayobe/ironic.yml
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user