From 5b0a90baa4739aae106d5f6661c1b27885dfec81 Mon Sep 17 00:00:00 2001
From: Mark Goddard <mark@stackhpc.com>
Date: Thu, 30 Nov 2017 18:26:52 +0000
Subject: [PATCH] Support multiple external networks

---
 ansible/external-net.yml             | 17 +++++++++--------
 ansible/group_vars/all/controllers   |  4 ++--
 ansible/group_vars/all/network       | 17 +++++++++++++----
 ansible/kolla-ansible.yml            |  5 +----
 ansible/network.yml                  |  4 +---
 doc/source/configuration/network.rst |  6 ++++--
 doc/source/release-notes.rst         |  2 ++
 etc/kayobe/networks.yml              |  9 ++++++---
 8 files changed, 38 insertions(+), 26 deletions(-)

diff --git a/ansible/external-net.yml b/ansible/external-net.yml
index 1cf16b274..ca0b4cf3c 100644
--- a/ansible/external-net.yml
+++ b/ansible/external-net.yml
@@ -8,15 +8,16 @@
       os_networks_openstack_auth_type: "{{ openstack_auth_type }}"
       os_networks_openstack_auth: "{{ openstack_auth }}"
       # Network configuration.
-      os_networks_name: "{{ external_net_name }}"
-      os_networks_type: "{% if external_net_name | net_vlan %}vlan{% else %}flat{% endif %}"
+      os_networks_name: "{{ item }}"
+      os_networks_type: "{% if item | net_vlan %}vlan{% else %}flat{% endif %}"
       os_networks_physical_network: "physnet1"
-      os_networks_segmentation_id: "{{ external_net_name | net_vlan }}"
+      os_networks_segmentation_id: "{{ item | net_vlan }}"
       os_networks_shared: True
       os_networks_external: True
       # Subnet configuration.
-      os_networks_subnet_name: "{{ external_net_name }}"
-      os_networks_cidr: "{{ external_net_name | net_cidr }}"
-      os_networks_gateway_ip: "{{ external_net_name | net_gateway }}"
-      os_networks_allocation_pool_start: "{{ external_net_name | net_neutron_allocation_pool_start }}"
-      os_networks_allocation_pool_end: "{{ external_net_name | net_neutron_allocation_pool_end }}"
+      os_networks_subnet_name: "{{ item }}"
+      os_networks_cidr: "{{ item | net_cidr }}"
+      os_networks_gateway_ip: "{{ item | net_gateway }}"
+      os_networks_allocation_pool_start: "{{ item | net_neutron_allocation_pool_start }}"
+      os_networks_allocation_pool_end: "{{ item | net_neutron_allocation_pool_end }}"
+      with_items: "{{ external_net_names }}"
diff --git a/ansible/group_vars/all/controllers b/ansible/group_vars/all/controllers
index 18339326b..44550de6f 100644
--- a/ansible/group_vars/all/controllers
+++ b/ansible/group_vars/all/controllers
@@ -30,8 +30,8 @@ controller_extra_network_interfaces: []
 
 # List of network interfaces to which network nodes are attached.
 controller_network_host_network_interfaces: >
-  {{ [public_net_name,
-      external_net_name] | unique | list }}
+  {{ ([public_net_name] +
+      external_net_names) | unique | list }}
 
 ###############################################################################
 # Controller node BIOS configuration.
diff --git a/ansible/group_vars/all/network b/ansible/group_vars/all/network
index 1d9caa53a..12511a498 100644
--- a/ansible/group_vars/all/network
+++ b/ansible/group_vars/all/network
@@ -21,12 +21,21 @@ provision_wl_net_name: 'provision_wl_net'
 # Name of the network used to expose the internal OpenStack API endpoints.
 internal_net_name: 'internal_net'
 
-# Name of the network used to expose the external OpenStack API endpoints and
-# to provide external network access via Neutron.
-external_net_name: 'external_net'
+# List of names of networks used to provide external network access via
+# Neutron.
+# Deprecated name: external_net_name
+# If external_net_name is defined, external_net_names will default to a list
+# containing one item, external_net_name.
+external_net_names: >
+  {{ [external_net_name]
+     if external_net_name is defined else
+     ['external_net'] }}
 
 # Name of the network used to expose the public OpenStack API endpoints.
-public_net_name: "{{ external_net_name }}"
+public_net_name: >
+  {{ external_net_names[0]
+     if external_net_names | length > 0 else
+     None }}
 
 # Name of the network used to carry storage data traffic.
 storage_net_name: 'storage_net'
diff --git a/ansible/kolla-ansible.yml b/ansible/kolla-ansible.yml
index c86342209..3a14dc8f1 100644
--- a/ansible/kolla-ansible.yml
+++ b/ansible/kolla-ansible.yml
@@ -103,10 +103,7 @@
               {{ kolla_neutron_bridge_interfaces |
                  union([item | net_interface(network_host) | replace('.' ~ item | net_vlan(network_host) | default('!nomatch!'), '')]) |
                  list }}
-          with_items:
-            # FIXME: Network host does not have an IP on this network.
-            - "{{ provision_wl_net_name }}"
-            - "{{ external_net_name }}"
+          with_items: "{{ [provision_wl_net_name] + external_net_names }}"
           when: item in hostvars[network_host].network_interfaces
 
         - name: Set facts containing the Neutron bridge and interface names
diff --git a/ansible/network.yml b/ansible/network.yml
index 06f5aba1b..1636fed3f 100644
--- a/ansible/network.yml
+++ b/ansible/network.yml
@@ -85,9 +85,7 @@
       set_fact:
         veth_bridges: >
           {{ veth_bridges | union([bridge_obj]) | list }}
-      with_items:
-        - "{{ provision_wl_net_name }}"
-        - "{{ external_net_name }}"
+      with_items: "{{ [provision_wl_net_name] + external_net_names }}"
       when: item in network_interfaces
       vars:
         interface: "{{ item | net_interface | replace('.' ~ item | net_vlan | default('!nomatch!'), '') }}"
diff --git a/doc/source/configuration/network.rst b/doc/source/configuration/network.rst
index 4cd8557d8..0607c3c0d 100644
--- a/doc/source/configuration/network.rst
+++ b/doc/source/configuration/network.rst
@@ -391,8 +391,10 @@ Internal network (``internal_net_name``)
     Name of the network used to expose the internal OpenStack API endpoints.
 Public network (``public_net_name``)
     Name of the network used to expose the public OpenStack API endpoints.
-External network (``external_net_name``)
-    Name of the network used to provide external network access via Neutron.
+External networks (``external_net_names``, deprecated: ``external_net_name``)
+    List of names of networks used to provide external network access via
+    Neutron. If ``external_net_name`` is defined, ``external_net_names``
+    defaults to a list containing only that network.
 Storage network (``storage_net_name``)
     Name of the network used to carry storage data traffic.
 Storage management network (``storage_mgmt_net_name``)
diff --git a/doc/source/release-notes.rst b/doc/source/release-notes.rst
index 04a69e68f..2068213af 100644
--- a/doc/source/release-notes.rst
+++ b/doc/source/release-notes.rst
@@ -26,6 +26,8 @@ Features
   single host.
 * Adds support for deployment of virtualised compute hosts.  These hosts should
   be added to the ``[compute]`` group.
+* Adds support for multiple external networks.  ``external_net_names`` should
+  be a list of names of networks.
 
 Upgrade Notes
 -------------
diff --git a/etc/kayobe/networks.yml b/etc/kayobe/networks.yml
index cc5ec3bb9..5f61b2ffc 100644
--- a/etc/kayobe/networks.yml
+++ b/etc/kayobe/networks.yml
@@ -23,9 +23,12 @@
 # Name of the network used to expose the internal OpenStack API endpoints.
 #internal_net_name:
 
-# Name of the network used to expose the external OpenStack API endpoints and
-# to provide external network access via Neutron.
-#external_net_name:
+# List of names of networks used to provide external network access via
+# Neutron.
+# Deprecated name: external_net_name
+# If external_net_name is defined, external_net_names will default to a list
+# containing one item, external_net_name.
+#external_net_names:
 
 # Name of the network used to expose the public OpenStack API endpoints.
 #public_net_name: