Support new style (and multiple) external networks

Switch the generated configuration to use "new" style external
networks when ext-port is not set.  In this case we configure
external_network_bridge = (intentionally blank),
gateway_external_network_id = (blank) and update the README with
information on using this new style of configuration.

The current template configures external networks by using the default
external_network_bridge=br-ex (implied when not set).  This activates
legacy code which assumes that a single external network exists on
that bridge and the L3 Agent directly plugs itself in.
provider:network_type, provider:physical_network and
provider:segmentation_id are ignored.  You cannot create multiple
networks and you cannot use segmented networks (e.g. VLAN)

By setting external_network_bridge = (intentionally blank) the L2
Agent handles the configuration instead, this allows us to create
multiple networks and also to use more complex network configurations
such as VLAN.  It is also possible to use the same physical connection
with different segmentation IDs for both internal and external
networks, as well as multiple external networks.

Legacy/existing configurations where ext-port is set generate the same
configuration as previous and should continue to work as before.  I do
not believe it to be easy to migrate existing setups to the "new"
style configuration automatically as changes to the neutron network
configuration may be required (specifically: provider:physical_network
will now be used when it was not before, and may not be correct) and
the physical port needs to be moved from br-ex to br-data which the
charm does not currently handle and is likely to error as it does not
attempt removal first.  Further work may be possible in this area.

For information about this new style of configuration being preferred,
see discussions in LP#1491668, LP#1525059 and
http://docs.openstack.org/liberty/networking-guide/scenario-classic-ovs.html

Change-Id: I8d2bb8098e080969e0445293b1ed79714b2c964f
Related-Bug: #1491668
Related-Bug: #1525059
Closes-Bug: #1536768
This commit is contained in:
Trent Lloyd 2016-03-23 00:33:06 +08:00 committed by James Page
parent 5e1d6e88ff
commit 5dee017f12
6 changed files with 79 additions and 32 deletions

View File

@ -50,45 +50,65 @@ See upstream [Neutron multi extnet](http://docs.openstack.org/trunk/config-refer
Configuration Options
---------------------
External Port Configuration
===========================
Port Configuration
==================
If the port to be used for external traffic is consistent across all physical
servers then is can be specified by simply setting ext-port to the nic id:
All network types (internal, external) are configured with bridge-mappings and
data-port and the flat-network-providers configuration option of the
neutron-api charm. Once deployed, you can configure the network specifics
using neutron net-create.
If the device name is not consistent between hosts, you can specify the same
bridge multiple times with MAC addresses instead of interface names. The charm
will loop through the list and configure the first matching interface.
Basic configuration of a single external network, typically used as floating IP
addresses combined with a GRE private network:
neutron-gateway:
ext-port: eth2
bridge-mappings: physnet1:br-ex
data-port: br-ex:eth1
neutron-api:
flat-network-providers: physnet1
However, if it varies between hosts then the mac addresses of the external
nics for each host can be passed as a space separated list:
neutron net-create --provider:network_type flat \
--provider:physical_network physnet1 --router:external=true \
external
neutron router-gateway-set provider external
Alternative configuration with two networks, where the internal private
network is directly connected to the gateway with public IP addresses but a
floating IP address range is also offered.
neutron-gateway:
ext-port: <MAC ext port host 1> <MAC ext port host 2> <MAC ext port host 3>
bridge-mappings: physnet1:br-data external:br-ex
data-port: br-data:eth1 br-ex:eth2
neutron-api:
flat-network-providers: physnet1 external
Alternative configuration with two external networks, one for public instance
addresses and one for floating IP addresses. Both networks are on the same
physical network connection (but they might be on different VLANs, that is
configured later using neutron net-create).
Multiple Floating Pools
=======================
neutron-gateway:
bridge-mappings: physnet1:br-data
data-port: br-data:eth1
neutron-api:
flat-network-providers: physnet1
If multiple floating pools are needed then an L3 agent (which corresponds to
a neutron-gateway for the sake of this charm) is needed for each one. Each
gateway needs to be deployed as a separate service so that the external
network id can be set differently for each gateway e.g.
neutron net-create --provider:network_type vlan \
--provider:segmentation_id 400 \
--provider:physical_network physnet1 --shared external
neutron net-create --provider:network_type vlan \
--provider:segmentation_id 401 \
--provider:physical_network physnet1 --shared --router:external=true \
floating
neutron router-gateway-set provider floating
juju deploy neutron-gateway neutron-gateway-extnet1
juju add-relation neutron-gateway-extnet1 mysql
juju add-relation neutron-gateway-extnet1 rabbitmq-server
juju add-relation neutron-gateway-extnet1 nova-cloud-controller
juju deploy neutron-gateway neutron-gateway-extnet2
juju add-relation neutron-gateway-extnet2 mysql
juju add-relation neutron-gateway-extnet2 rabbitmq-server
juju add-relation neutron-gateway-extnet2 nova-cloud-controller
Create extnet1 and extnet2 via neutron client and take a note of their ids
juju set neutron-gateway-extnet1 "run-internal-router=leader"
juju set neutron-gateway-extnet2 "run-internal-router=none"
juju set neutron-gateway-extnet1 "external-network-id=<extnet1 id>"
juju set neutron-gateway-extnet2 "external-network-id=<extnet2 id>"
This replaces the previous system of using ext-port, which always created a bridge
called br-ex for external networks which was used implicitly by external router
interfaces.
Instance MTU
============

View File

@ -69,6 +69,10 @@ options:
type: string
default:
description: |
Deprecated: Use bridge-mappings and data-port to create a network
which can be used for external connectivity. You can call the network
external and the bridge br-ex by convention, but neither is required.
Space-delimited list of external ports to use for routing of instance
traffic to the external public network. Valid values are either MAC
addresses (in which case only MAC addresses for interfaces without an IP

View File

@ -64,6 +64,10 @@ class L3AgentContext(OSContextGenerator):
if config('external-network-id'):
ctxt['ext_net_id'] = config('external-network-id')
if not config('ext-port') and not config('external-network-id'):
ctxt['external_configuration_new'] = True
if config('plugin'):
ctxt['plugin'] = config('plugin')
if api_settings['enable_dvr']:

View File

@ -19,6 +19,9 @@ use_namespaces = True
{% else %}
ovs_use_veth = True
{% endif %}
{% if ext_net_id -%}
{% if external_configuration_new -%}
gateway_external_network_id =
external_network_bridge =
{% elif ext_net_id %}
gateway_external_network_id = {{ ext_net_id }}
{% endif -%}

View File

@ -19,7 +19,10 @@ use_namespaces = True
{% else %}
ovs_use_veth = True
{% endif %}
{% if ext_net_id -%}
{% if external_configuration_new -%}
gateway_external_network_id =
external_network_bridge =
{% elif ext_net_id %}
gateway_external_network_id = {{ ext_net_id }}
{% endif -%}
agent_mode = {{ agent_mode }}

View File

@ -56,12 +56,25 @@ class TestL3AgentContext(CharmTestCase):
self.config.side_effect = self.test_config.get
@patch('neutron_contexts.NeutronAPIContext')
def test_no_ext_netid(self, _NeutronAPIContext):
def test_new_ext_network(self, _NeutronAPIContext):
_NeutronAPIContext.return_value = \
DummyNeutronAPIContext(return_value={'enable_dvr': False})
self.test_config.set('run-internal-router', 'none')
self.test_config.set('external-network-id', '')
self.eligible_leader.return_value = False
self.assertEquals(neutron_contexts.L3AgentContext()(),
{'agent_mode': 'legacy',
'external_configuration_new': True,
'handle_internal_only_router': False,
'plugin': 'ovs'})
@patch('neutron_contexts.NeutronAPIContext')
def test_old_ext_network(self, _NeutronAPIContext):
_NeutronAPIContext.return_value = \
DummyNeutronAPIContext(return_value={'enable_dvr': False})
self.test_config.set('run-internal-router', 'none')
self.test_config.set('ext-port', 'eth1')
self.eligible_leader.return_value = False
self.assertEquals(neutron_contexts.L3AgentContext()(),
{'agent_mode': 'legacy',
'handle_internal_only_router': False,