Add support for customising Neutron physical network names

Previously Kolla Ansible hard-coded Neutron physical networks starting
at physnet1 up to physnetN, matching the number of interfaces in
neutron_external_interface and bridges in neutron_bridge_name.

Sometimes we may want to customise the physical network names used. This
may be to allow for not all hosts having access to all physical
networks, or to use more descriptive names.

For example, in an environment with a separate physical network for
Ironic provisioning, controllers might have access to two physical
networks, while compute nodes have access to one.

This change adds a neutron_physical_networks variable, making it
possible to customise the Neutron physical network names used for the
OVS, OVN, Linux bridge and OVS DPDK plugins. The default behaviour is
unchanged.

Change-Id: Ib5b8ea727014964919c6b3bd2352bac4a4ac1787
This commit is contained in:
Mark Goddard 2024-06-19 14:05:32 +01:00
parent bd286db198
commit 64dcfb7291
8 changed files with 57 additions and 13 deletions

View File

@ -1080,6 +1080,7 @@ designate_notifications_topic_name: "notifications_designate"
####################### #######################
neutron_bgp_router_id: "1.1.1.1" neutron_bgp_router_id: "1.1.1.1"
neutron_bridge_name: "{{ 'br-dvs' if neutron_plugin_agent == 'vmware_dvs' else 'br_dpdk' if enable_ovs_dpdk | bool else 'br-ex' }}" neutron_bridge_name: "{{ 'br-dvs' if neutron_plugin_agent == 'vmware_dvs' else 'br_dpdk' if enable_ovs_dpdk | bool else 'br-ex' }}"
neutron_physical_networks: "{% for bridge in neutron_bridge_name.split(',') %}physnet{{ loop.index }}{% if not loop.last %},{% endif %}{% endfor %}"
# Comma-separated type of enabled ml2 type drivers # Comma-separated type of enabled ml2 type drivers
neutron_type_drivers: "flat,vlan,vxlan{% if neutron_plugin_agent == 'ovn' %},geneve{% endif %}" neutron_type_drivers: "flat,vlan,vxlan{% if neutron_plugin_agent == 'ovn' %},geneve{% endif %}"
# Comma-separated types of tenant networks (should be listed in 'neutron_type_drivers') # Comma-separated types of tenant networks (should be listed in 'neutron_type_drivers')

View File

@ -5,7 +5,8 @@ extensions = {{ neutron_agent_extensions|map(attribute='name')|join(',') }}
[linux_bridge] [linux_bridge]
{% if inventory_hostname in groups["network"] or (inventory_hostname in groups["compute"] and computes_need_external_bridge | bool ) %} {% if inventory_hostname in groups["network"] or (inventory_hostname in groups["compute"] and computes_need_external_bridge | bool ) %}
physical_interface_mappings = {% for interface in neutron_external_interface.split(',') %}physnet{{ loop.index0 + 1 }}:{{ interface }}{% if not loop.last %},{% endif %}{% endfor %} {# Format: physnet1:br1,physnet2:br2 #}
physical_interface_mappings = {{ neutron_physical_networks.split(',') | zip(neutron_external_interface.split(',')) | map('join', ':') | join(',') }}
{% endif %} {% endif %}
[securitygroup] [securitygroup]

View File

@ -15,7 +15,7 @@ extension_drivers = {{ neutron_extension_drivers | map(attribute='name') | join(
[ml2_type_vlan] [ml2_type_vlan]
{% if enable_ironic | bool %} {% if enable_ironic | bool %}
network_vlan_ranges = physnet1 network_vlan_ranges = {{ neutron_physical_networks }}
{% else %} {% else %}
network_vlan_ranges = network_vlan_ranges =
{% endif %} {% endif %}
@ -24,7 +24,7 @@ network_vlan_ranges =
{% if enable_ironic | bool %} {% if enable_ironic | bool %}
flat_networks = * flat_networks = *
{% else %} {% else %}
flat_networks = {% for interface in neutron_external_interface.split(',') %}physnet{{ loop.index0 + 1 }}{% if not loop.last %},{% endif %}{% endfor %} flat_networks = {{ neutron_physical_networks }}
{% endif %} {% endif %}
[ml2_type_vxlan] [ml2_type_vxlan]

View File

@ -15,7 +15,8 @@ firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewal
[ovs] [ovs]
{% if inventory_hostname in groups["network"] or (inventory_hostname in groups["compute"] and computes_need_external_bridge | bool ) %} {% if inventory_hostname in groups["network"] or (inventory_hostname in groups["compute"] and computes_need_external_bridge | bool ) %}
bridge_mappings = {% for bridge in neutron_bridge_name.split(',') %}physnet{{ loop.index0 + 1 }}:{{ bridge }}{% if not loop.last %},{% endif %}{% endfor %} {# Format: physnet1:br1,physnet2:br2 #}
bridge_mappings = {{ neutron_physical_networks.split(',') | zip(neutron_bridge_name.split(',')) | map('join', ':') | join(',') }}
{% endif %} {% endif %}
datapath_type = {{ ovs_datapath }} datapath_type = {{ ovs_datapath }}
ovsdb_connection = tcp:127.0.0.1:{{ ovsdb_port }} ovsdb_connection = tcp:127.0.0.1:{{ ovsdb_port }}

View File

@ -12,8 +12,10 @@
- name: Configure OVN in OVSDB - name: Configure OVN in OVSDB
vars: vars:
ovn_mappings: "{% for bridge in neutron_bridge_name.split(',') %}physnet{{ loop.index0 + 1 }}:{{ bridge }}{% if not loop.last %},{% endif %}{% endfor %}" # Format: physnet1:br1,physnet2:br2
ovn_macs: "{% for bridge in neutron_bridge_name.split(',') %}physnet{{ loop.index0 + 1 }}:{{ ovn_base_mac | random_mac(seed=inventory_hostname + bridge) }}{% if not loop.last %},{% endif %}{% endfor %}" ovn_mappings: "{{ neutron_physical_networks.split(',') | zip(neutron_bridge_name.split(',')) | map('join', ':') | join(',') }}"
# Format: physnet1:00:11:22:33:44:55,physnet2:00:11:22:33:44:56
ovn_macs: "{% for physnet, bridge in neutron_physical_networks.split(',') | zip(neutron_bridge_name.split(',')) %}{{ physnet }}:{{ ovn_base_mac | random_mac(seed=inventory_hostname + bridge) }}{% if not loop.last %},{% endif %}{% endfor %}"
ovn_cms_opts: "{{ 'enable-chassis-as-gw' if inventory_hostname in groups['ovn-controller-network'] else '' }}{{ ',availability-zones=' + neutron_ovn_availability_zones | join(',') if inventory_hostname in groups['ovn-controller-network'] and neutron_ovn_availability_zones }}" ovn_cms_opts: "{{ 'enable-chassis-as-gw' if inventory_hostname in groups['ovn-controller-network'] else '' }}{{ ',availability-zones=' + neutron_ovn_availability_zones | join(',') if inventory_hostname in groups['ovn-controller-network'] and neutron_ovn_availability_zones }}"
become: true become: true
kolla_toolbox: kolla_toolbox:

View File

@ -37,8 +37,10 @@ ovsdpdk_services:
#################### ####################
# OVS # OVS
#################### ####################
ovs_bridge_mappings: "{% for bridge in neutron_bridge_name.split(',') %}physnet{{ loop.index0 + 1 }}:{{ bridge }}{% if not loop.last %},{% endif %}{% endfor %}" # Format: physnet1:br1,physnet2:br2
ovs_port_mappings: "{% for bridge in neutron_bridge_name.split(',') %} {{ neutron_external_interface.split(',')[loop.index0] }}:{{ bridge }}{% if not loop.last %},{% endif %}{% endfor %}" ovs_bridge_mappings: "{{ neutron_physical_networks.split(',') | zip(neutron_bridge_name.split(',')) | map('join', ':') | join(',') }}"
# Format: eth1:br1,eth2:br2
ovs_port_mappings: "{{ neutron_external_interface.split(',') | zip(neutron_bridge_name.split(',')) | map('join', ':') | join(',') }}"
tunnel_interface_network: "{{ hostvars[inventory_hostname].ansible_facts[dpdk_tunnel_interface]['ipv4']['network'] }}/{{ hostvars[inventory_hostname].ansible_facts[dpdk_tunnel_interface]['ipv4']['netmask'] }}" tunnel_interface_network: "{{ hostvars[inventory_hostname].ansible_facts[dpdk_tunnel_interface]['ipv4']['network'] }}/{{ hostvars[inventory_hostname].ansible_facts[dpdk_tunnel_interface]['ipv4']['netmask'] }}"
tunnel_interface_cidr: "{{ dpdk_tunnel_interface_address }}/{{ tunnel_interface_network | ipaddr('prefix') }}" tunnel_interface_cidr: "{{ dpdk_tunnel_interface_address }}/{{ tunnel_interface_network | ipaddr('prefix') }}"
ovs_cidr_mappings: "{% if neutron_bridge_name.split(',') | length != 1 %} {neutron_bridge_name.split(',')[0]}:{{ tunnel_interface_cidr }} {% else %} {{ neutron_bridge_name }}:{{ tunnel_interface_cidr }} {% endif %}" ovs_cidr_mappings: "{% if neutron_bridge_name.split(',') | length != 1 %} {neutron_bridge_name.split(',')[0]}:{{ tunnel_interface_cidr }} {% else %} {{ neutron_bridge_name }}:{{ tunnel_interface_cidr }} {% endif %}"

View File

@ -20,13 +20,20 @@ Neutron external interface is used for communication with the external world,
for example provider networks, routers and floating IPs. for example provider networks, routers and floating IPs.
For setting up the neutron external interface modify For setting up the neutron external interface modify
``/etc/kolla/globals.yml`` setting ``neutron_external_interface`` to the ``/etc/kolla/globals.yml`` setting ``neutron_external_interface`` to the
desired interface name. This interface is used by hosts in the ``network`` desired interface name or comma-separated list of interface names. Its default
group. It is also used by hosts in the ``compute`` group if value is ``eth1``. These external interfaces are used by hosts in the
``network`` group. They are also used by hosts in the ``compute`` group if
``enable_neutron_provider_networks`` is set or DVR is enabled. ``enable_neutron_provider_networks`` is set or DVR is enabled.
The interface is plugged into a bridge (Open vSwitch or Linux Bridge, depending The external interfaces are each plugged into a bridge (Open vSwitch or Linux
on the driver) defined by ``neutron_bridge_name``, which defaults to ``br-ex``. Bridge, depending on the driver) defined by ``neutron_bridge_name``, which
The default Neutron physical network is ``physnet1``. defaults to ``br-ex``. When there are multiple external interfaces,
``neutron_bridge_name`` should be a comma-separated list of the same length.
The default Neutron physical network is ``physnet1``, or ``physnet1`` to
``physnetN`` when there are multiple external network interfaces. This may be
changed by setting ``neutron_physical_networks`` to a comma-separated list of
networks of the same length.
Example: single interface Example: single interface
------------------------- -------------------------
@ -54,6 +61,30 @@ These two lists are "zipped" together, such that ``eth1`` is plugged into the
Ansible maps these interfaces to Neutron physical networks ``physnet1`` and Ansible maps these interfaces to Neutron physical networks ``physnet1`` and
``physnet2`` respectively. ``physnet2`` respectively.
Example: custom physical networks
---------------------------------
Sometimes we may want to customise the physical network names used. This may be
to allow for not all hosts having access to all physical networks, or to use
more descriptive names.
For example, in an environment with a separate physical network for Ironic
provisioning, controllers might have access to two physical networks:
.. code-block:: yaml
neutron_external_interface: "eth1,eth2"
neutron_bridge_name: "br-ex1,br-ex2"
neutron_physical_network: "physnet1,physnet2"
While compute nodes have access only to ``physnet2``.
.. code-block:: yaml
neutron_external_interface: "eth1"
neutron_bridge_name: "br-ex1"
neutron_physical_network: "physnet2"
Example: shared interface Example: shared interface
------------------------- -------------------------

View File

@ -0,0 +1,6 @@
---
features:
- |
Adds a ``neutron_physical_networks`` variable for customising Neutron
physical network names. The default behaviour of using ``physnet1`` to
``physnetN`` is unchanged.