DVR: delete stale devices after router update

After the external network change of router gateway, the l3 agent
deletes stale external devices in the qrouter namespace only. This
doesn't apply to distributed router.

This patch extract a method named _delete_stale_external_devices from
RouterInfo and override it in DvrEdgeRouter.

Change-Id: I2602efd5be92ec57410e54cf9c26641330a52ee6
Partial-Bug: #1651813
This commit is contained in:
Quan Tian 2016-12-21 20:40:08 +08:00
parent eb5871535c
commit dcd4c8b8de
3 changed files with 58 additions and 11 deletions

View File

@ -242,3 +242,18 @@ class DvrEdgeRouter(dvr_local_router.DvrLocalRouter):
with self.snat_iptables_manager.defer_apply():
self._add_address_scope_mark(
self.snat_iptables_manager, ports_scopemark)
def _delete_stale_external_devices(self, interface_name):
if not self.snat_namespace.exists():
return
ns_ip = ip_lib.IPWrapper(namespace=self.snat_namespace.name)
for d in ns_ip.get_devices(exclude_loopback=True):
if (d.name.startswith(router.EXTERNAL_DEV_PREFIX) and
d.name != interface_name):
LOG.debug('Deleting stale external router device: %s', d.name)
self.driver.unplug(
d.name,
bridge=self.agent_conf.external_network_bridge,
namespace=self.snat_namespace.name,
prefix=router.EXTERNAL_DEV_PREFIX)

View File

@ -713,6 +713,19 @@ class RouterInfo(object):
def _gateway_ports_equal(port1, port2):
return port1 == port2
def _delete_stale_external_devices(self, interface_name):
existing_devices = self._get_existing_devices()
stale_devs = [dev for dev in existing_devices
if dev.startswith(EXTERNAL_DEV_PREFIX)
and dev != interface_name]
for stale_dev in stale_devs:
LOG.debug('Deleting stale external router device: %s', stale_dev)
self.agent.pd.remove_gw_interface(self.router['id'])
self.driver.unplug(stale_dev,
bridge=self.agent_conf.external_network_bridge,
namespace=self.ns_name,
prefix=EXTERNAL_DEV_PREFIX)
def _process_external_gateway(self, ex_gw_port):
# TODO(Carl) Refactor to clarify roles of ex_gw_port vs self.ex_gw_port
ex_gw_port_id = (ex_gw_port and ex_gw_port['id'] or
@ -736,17 +749,7 @@ class RouterInfo(object):
interface_name = self.get_internal_device_name(p['id'])
self.gateway_redirect_cleanup(interface_name)
existing_devices = self._get_existing_devices()
stale_devs = [dev for dev in existing_devices
if dev.startswith(EXTERNAL_DEV_PREFIX)
and dev != interface_name]
for stale_dev in stale_devs:
LOG.debug('Deleting stale external router device: %s', stale_dev)
self.agent.pd.remove_gw_interface(self.router['id'])
self.driver.unplug(stale_dev,
bridge=self.agent_conf.external_network_bridge,
namespace=self.ns_name,
prefix=EXTERNAL_DEV_PREFIX)
self._delete_stale_external_devices(interface_name)
# Process SNAT rules for external gateway
gw_port = self._router.get('gw_port')

View File

@ -1871,6 +1871,35 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
namespace=ri.ns_name,
prefix=namespaces.EXTERNAL_DEV_PREFIX)
def test_process_dvr_router_delete_stale_external_devices(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
stale_devlist = [l3_test_common.FakeDev('qg-a1b2c3d4-e5')]
stale_devnames = [dev.name for dev in stale_devlist]
router = l3_test_common.prepare_router_data(enable_snat=True,
num_internal_ports=1)
self._set_ri_kwargs(agent, router['id'], router)
ri = dvr_router.DvrEdgeRouter(HOSTNAME, **self.ri_kwargs)
self.mock_ip.get_devices.return_value = stale_devlist
ri.process()
self.mock_driver.unplug.assert_called_with(
stale_devnames[0],
bridge=agent.conf.external_network_bridge,
namespace=ri.snat_namespace.name,
prefix=namespaces.EXTERNAL_DEV_PREFIX)
def test_process_dvr_router_delete_stale_external_devices_no_snat_ns(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
router = l3_test_common.prepare_router_data(enable_gw=False,
num_internal_ports=1)
self._set_ri_kwargs(agent, router['id'], router)
ri = dvr_router.DvrEdgeRouter(HOSTNAME, **self.ri_kwargs)
self.mock_ip.netns.exists.return_value = False
ri._delete_stale_external_devices('qg-a1b2c3d4-e5')
self.assertFalse(self.mock_ip.get_devices.called)
def test_router_deleted(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
agent._queue = mock.Mock()