Change external_network_bridge default to ''
This changes the default for external_network_bridge to '' to encourage operators to deploy L3 agents in the correct manner. This patch also adds a functional test to ensure that namespaces with an existing external gateway interface are not torn down and rewired on change. Closes-Bug: #1563070 Change-Id: If533cf7c4c379be78f5a15073accaff7f65973ab
This commit is contained in:
parent
414f2ffc8d
commit
3f71a49e0f
@ -83,14 +83,14 @@ AVAILABILITY_ZONE_OPTS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
EXT_NET_BRIDGE_OPTS = [
|
EXT_NET_BRIDGE_OPTS = [
|
||||||
cfg.StrOpt('external_network_bridge', default='br-ex',
|
cfg.StrOpt('external_network_bridge', default='',
|
||||||
deprecated_for_removal=True,
|
deprecated_for_removal=True,
|
||||||
help=_("Name of bridge used for external network "
|
help=_("Name of bridge used for external network "
|
||||||
"traffic. This should be set to an empty value for the "
|
"traffic. When this parameter is set, the L3 agent will "
|
||||||
"Linux Bridge. When this parameter is set, each L3 "
|
"plug an interface directly into an external bridge "
|
||||||
"agent can be associated with no more than one external "
|
"which will not allow any wiring by the L2 agent. Using "
|
||||||
"network. This option is deprecated and will be removed "
|
"this will result in incorrect port statuses. This "
|
||||||
"in the M release.")),
|
"option is deprecated and will be removed in Ocata."))
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -332,7 +332,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
|
|||||||
ext_net_id = agent['configurations'].get(
|
ext_net_id = agent['configurations'].get(
|
||||||
'gateway_external_network_id')
|
'gateway_external_network_id')
|
||||||
ext_bridge = agent['configurations'].get(
|
ext_bridge = agent['configurations'].get(
|
||||||
'external_network_bridge', 'br-ex')
|
'external_network_bridge', '')
|
||||||
if (ext_net_id == network_id or
|
if (ext_net_id == network_id or
|
||||||
(not ext_net_id and not ext_bridge)):
|
(not ext_net_id and not ext_bridge)):
|
||||||
return
|
return
|
||||||
|
@ -24,6 +24,7 @@ from neutron.agent.linux import ip_lib
|
|||||||
from neutron.callbacks import events
|
from neutron.callbacks import events
|
||||||
from neutron.callbacks import registry
|
from neutron.callbacks import registry
|
||||||
from neutron.callbacks import resources
|
from neutron.callbacks import resources
|
||||||
|
from neutron.tests import base as tests_base
|
||||||
from neutron.tests.common import machine_fixtures
|
from neutron.tests.common import machine_fixtures
|
||||||
from neutron.tests.common import net_helpers
|
from neutron.tests.common import net_helpers
|
||||||
from neutron.tests.functional.agent.l3 import framework
|
from neutron.tests.functional.agent.l3 import framework
|
||||||
@ -96,6 +97,39 @@ class L3AgentTestCase(framework.L3AgentTestFramework):
|
|||||||
|
|
||||||
self.assertIsNone(device.route.get_gateway())
|
self.assertIsNone(device.route.get_gateway())
|
||||||
|
|
||||||
|
def _make_bridge(self):
|
||||||
|
bridge = framework.get_ovs_bridge(tests_base.get_rand_name())
|
||||||
|
bridge.create()
|
||||||
|
self.addCleanup(bridge.destroy)
|
||||||
|
return bridge
|
||||||
|
|
||||||
|
def test_external_network_bridge_change(self):
|
||||||
|
bridge1, bridge2 = self._make_bridge(), self._make_bridge()
|
||||||
|
self.agent.conf.set_override('external_network_bridge',
|
||||||
|
bridge1.br_name)
|
||||||
|
router_info = self.generate_router_info(False)
|
||||||
|
router = self.manage_router(self.agent, router_info)
|
||||||
|
gw_port = router.router['gw_port']
|
||||||
|
gw_inf_name = router.get_external_device_name(gw_port['id'])
|
||||||
|
|
||||||
|
self.assertIn(gw_inf_name,
|
||||||
|
[v.port_name for v in bridge1.get_vif_ports()])
|
||||||
|
# changeing the external_network_bridge should have no impact since
|
||||||
|
# the interface exists.
|
||||||
|
self.agent.conf.set_override('external_network_bridge',
|
||||||
|
bridge2.br_name)
|
||||||
|
self.manage_router(self.agent, router_info)
|
||||||
|
self.assertIn(gw_inf_name,
|
||||||
|
[v.port_name for v in bridge1.get_vif_ports()])
|
||||||
|
self.assertNotIn(gw_inf_name,
|
||||||
|
[v.port_name for v in bridge2.get_vif_ports()])
|
||||||
|
namespaces.Namespace.delete(router.router_namespace)
|
||||||
|
self.manage_router(self.agent, router_info)
|
||||||
|
self.assertIn(gw_inf_name,
|
||||||
|
[v.port_name for v in bridge2.get_vif_ports()])
|
||||||
|
self.assertNotIn(gw_inf_name,
|
||||||
|
[v.port_name for v in bridge1.get_vif_ports()])
|
||||||
|
|
||||||
def test_legacy_router_ns_rebuild(self):
|
def test_legacy_router_ns_rebuild(self):
|
||||||
router_info = self.generate_router_info(False)
|
router_info = self.generate_router_info(False)
|
||||||
router = self.manage_router(self.agent, router_info)
|
router = self.manage_router(self.agent, router_info)
|
||||||
|
@ -1813,7 +1813,7 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
|||||||
|
|
||||||
self.mock_driver.unplug.assert_called_with(
|
self.mock_driver.unplug.assert_called_with(
|
||||||
stale_devnames[0],
|
stale_devnames[0],
|
||||||
bridge="br-ex",
|
bridge="",
|
||||||
namespace=ri.ns_name,
|
namespace=ri.ns_name,
|
||||||
prefix=l3_agent.EXTERNAL_DEV_PREFIX)
|
prefix=l3_agent.EXTERNAL_DEV_PREFIX)
|
||||||
|
|
||||||
@ -1994,6 +1994,7 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
|||||||
self._test_process_routers_update_router_deleted(True)
|
self._test_process_routers_update_router_deleted(True)
|
||||||
|
|
||||||
def test_process_router_if_compatible_with_no_ext_net_in_conf(self):
|
def test_process_router_if_compatible_with_no_ext_net_in_conf(self):
|
||||||
|
self.conf.set_override('external_network_bridge', 'br-ex')
|
||||||
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
|
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
|
||||||
self.plugin_api.get_external_network_id.return_value = 'aaa'
|
self.plugin_api.get_external_network_id.return_value = 'aaa'
|
||||||
|
|
||||||
@ -2022,6 +2023,7 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
|||||||
self.assertFalse(self.plugin_api.get_external_network_id.called)
|
self.assertFalse(self.plugin_api.get_external_network_id.called)
|
||||||
|
|
||||||
def test_process_router_if_compatible_with_stale_cached_ext_net(self):
|
def test_process_router_if_compatible_with_stale_cached_ext_net(self):
|
||||||
|
self.conf.set_override('external_network_bridge', 'br-ex')
|
||||||
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
|
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
|
||||||
self.plugin_api.get_external_network_id.return_value = 'aaa'
|
self.plugin_api.get_external_network_id.return_value = 'aaa'
|
||||||
agent.target_ex_net_id = 'bbb'
|
agent.target_ex_net_id = 'bbb'
|
||||||
@ -2037,6 +2039,7 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
|||||||
agent.context)
|
agent.context)
|
||||||
|
|
||||||
def test_process_router_if_compatible_w_no_ext_net_and_2_net_plugin(self):
|
def test_process_router_if_compatible_w_no_ext_net_and_2_net_plugin(self):
|
||||||
|
self.conf.set_override('external_network_bridge', 'br-ex')
|
||||||
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
|
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
|
||||||
|
|
||||||
router = {'id': _uuid(),
|
router = {'id': _uuid(),
|
||||||
@ -2078,7 +2081,6 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
|||||||
'external_gateway_info': {'network_id': 'aaa'}}
|
'external_gateway_info': {'network_id': 'aaa'}}
|
||||||
|
|
||||||
agent.router_info = {}
|
agent.router_info = {}
|
||||||
self.conf.set_override('external_network_bridge', '')
|
|
||||||
agent._process_router_if_compatible(router)
|
agent._process_router_if_compatible(router)
|
||||||
self.assertIn(router['id'], agent.router_info)
|
self.assertIn(router['id'], agent.router_info)
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ class TestDebugCommands(base.BaseTestCase):
|
|||||||
'fake_port',
|
'fake_port',
|
||||||
'tap12345678-12',
|
'tap12345678-12',
|
||||||
'aa:bb:cc:dd:ee:ffa',
|
'aa:bb:cc:dd:ee:ffa',
|
||||||
bridge='br-ex',
|
bridge='',
|
||||||
namespace=namespace),
|
namespace=namespace),
|
||||||
mock.call.init_l3('tap12345678-12',
|
mock.call.init_l3('tap12345678-12',
|
||||||
['10.0.0.3/24'],
|
['10.0.0.3/24'],
|
||||||
@ -223,7 +223,7 @@ class TestDebugCommands(base.BaseTestCase):
|
|||||||
self.driver.assert_has_calls([mock.call.get_device_name(mock.ANY),
|
self.driver.assert_has_calls([mock.call.get_device_name(mock.ANY),
|
||||||
mock.call.unplug('tap12345678-12',
|
mock.call.unplug('tap12345678-12',
|
||||||
namespace=namespace,
|
namespace=namespace,
|
||||||
bridge='br-ex')])
|
bridge='')])
|
||||||
|
|
||||||
def test_list_probe(self):
|
def test_list_probe(self):
|
||||||
cmd = commands.ListProbe(self.app, None)
|
cmd = commands.ListProbe(self.app, None)
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
prelude: >
|
||||||
|
The default value for 'external_network_bridge' in the L3 agent is now ''.
|
||||||
|
upgrade:
|
||||||
|
- The default value for 'external_network_bridge' has been changed to ''
|
||||||
|
since that is the preferred way to configure the L3 agent and will be the
|
||||||
|
only way in future releases. If you have not explicitly set this value
|
||||||
|
and you use the L3 agent, you will need to set this value to 'br-ex' to
|
||||||
|
match the old default.
|
||||||
|
If you are using 'br-ex', you should switch to '', ensure your external
|
||||||
|
network has a flat segment and ensure your L2 agent has a bridge_mapping
|
||||||
|
entry between the external network's flat segment physnet and 'br-ex' to
|
||||||
|
get the same connectivity. If the external network did not already have
|
||||||
|
the flat segment, you will need to detach all routers from the external
|
||||||
|
networks, delete the incorrect segment type, add the flat segment, and
|
||||||
|
re-attach the routers.
|
Loading…
Reference in New Issue
Block a user