From 5dee017f12ad37838d5a3dfa784e60644edf4565 Mon Sep 17 00:00:00 2001 From: Trent Lloyd Date: Wed, 23 Mar 2016 00:33:06 +0800 Subject: [PATCH] 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 --- README.md | 78 ++++++++++++++++++----------- config.yaml | 4 ++ hooks/neutron_contexts.py | 4 ++ templates/icehouse/l3_agent.ini | 5 +- templates/juno/l3_agent.ini | 5 +- unit_tests/test_neutron_contexts.py | 15 +++++- 6 files changed, 79 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 294e48be..17bfe063 100644 --- a/README.md +++ b/README.md @@ -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: + 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=" - juju set neutron-gateway-extnet2 "external-network-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 ============ diff --git a/config.yaml b/config.yaml index d17ca25e..f83c1545 100644 --- a/config.yaml +++ b/config.yaml @@ -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 diff --git a/hooks/neutron_contexts.py b/hooks/neutron_contexts.py index 9222c67f..ee567316 100644 --- a/hooks/neutron_contexts.py +++ b/hooks/neutron_contexts.py @@ -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']: diff --git a/templates/icehouse/l3_agent.ini b/templates/icehouse/l3_agent.ini index e64591a4..8a34af01 100644 --- a/templates/icehouse/l3_agent.ini +++ b/templates/icehouse/l3_agent.ini @@ -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 -%} diff --git a/templates/juno/l3_agent.ini b/templates/juno/l3_agent.ini index 6fd6cd4b..b0f5d696 100644 --- a/templates/juno/l3_agent.ini +++ b/templates/juno/l3_agent.ini @@ -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 }} diff --git a/unit_tests/test_neutron_contexts.py b/unit_tests/test_neutron_contexts.py index 625b2f25..d95be7c1 100644 --- a/unit_tests/test_neutron_contexts.py +++ b/unit_tests/test_neutron_contexts.py @@ -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,