Merge "Delete fipnamespace when external net removed on DVR" into stable/liberty

This commit is contained in:
Jenkins 2016-04-22 01:09:29 +00:00 committed by Gerrit Code Review
commit 2b87fee13b
6 changed files with 79 additions and 25 deletions

View File

@ -163,9 +163,11 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
1.2 - DVR support: new L3 agent methods added.
- add_arp_entry
- del_arp_entry
1.3 - fipnamespace_delete_on_ext_net - to delete fipnamespace
after the external network is removed
Needed by the L3 service when dealing with DVR
"""
target = oslo_messaging.Target(version='1.2')
target = oslo_messaging.Target(version='1.3')
def __init__(self, host, conf=None):
if conf:

View File

@ -77,3 +77,9 @@ class AgentMixin(object):
mac = arp_table['mac_address']
subnet_id = arp_table['subnet_id']
ri._update_arp_entry(ip, mac, subnet_id, 'delete')
def fipnamespace_delete_on_ext_net(self, context, ext_net_id):
"""Delete fip namespace after external network removed."""
fip_ns = self.get_fip_ns(ext_net_id)
if fip_ns.agent_gateway_port and not fip_ns.destroyed:
fip_ns.delete()

View File

@ -122,15 +122,28 @@ class L3AgentNotifyAPI(object):
cctxt = self.client.prepare(fanout=True)
cctxt.cast(context, method, routers=router_ids)
def _notification_fanout(self, context, method, router_id):
"""Fanout the deleted router to all L3 agents."""
LOG.debug('Fanout notify agent at %(topic)s the message '
'%(method)s on router %(router_id)s',
{'topic': topics.L3_AGENT,
'method': method,
'router_id': router_id})
def _notification_fanout(self, context, method, router_id=None, **kwargs):
"""Fanout the information to all L3 agents.
This function will fanout the router_id or ext_net_id
to the L3 Agents.
"""
ext_net_id = kwargs.get('ext_net_id')
if router_id:
kwargs['router_id'] = router_id
LOG.debug('Fanout notify agent at %(topic)s the message '
'%(method)s on router %(router_id)s',
{'topic': topics.L3_AGENT,
'method': method,
'router_id': router_id})
if ext_net_id:
LOG.debug('Fanout notify agent at %(topic)s the message '
'%(method)s for external_network %(ext_net_id)s',
{'topic': topics.L3_AGENT,
'method': method,
'ext_net_id': ext_net_id})
cctxt = self.client.prepare(fanout=True)
cctxt.cast(context, method, router_id=router_id)
cctxt.cast(context, method, **kwargs)
def agent_updated(self, context, admin_state_up, host):
self._notification_host(context, 'agent_updated', host,
@ -153,6 +166,11 @@ class L3AgentNotifyAPI(object):
self._agent_notification_arp(context, 'del_arp_entry', router_id,
operation, arp_table)
def delete_fipnamespace_for_ext_net(self, context, ext_net_id):
self._notification_fanout(
context, 'fipnamespace_delete_on_ext_net',
ext_net_id=ext_net_id)
def router_removed_from_agent(self, context, router_id, host):
self._notification_host(context, 'router_removed_from_agent', host,
payload={'router_id': router_id})

View File

@ -161,7 +161,7 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
self)._delete_current_gw_port(context, router_id,
router, new_network)
if (is_distributed_router(router) and
gw_ext_net_id != new_network):
gw_ext_net_id != new_network and gw_ext_net_id is not None):
self.delete_csnat_router_interface_ports(
context.elevated(), router)
# NOTE(Swami): Delete the Floatingip agent gateway port
@ -174,6 +174,10 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
if not ext_net_gw_ports:
self.delete_floatingip_agent_gateway_port(
context.elevated(), None, gw_ext_net_id)
# Send the information to all the L3 Agent hosts
# to clean up the fip namespace as it is no longer required.
self.l3_rpc_notifier.delete_fipnamespace_for_ext_net(
context, gw_ext_net_id)
def _create_gw_port(self, context, router_id, router, new_network,
ext_ips):

View File

@ -1145,6 +1145,7 @@ class TestDvrRouter(L3AgentTestFramework):
# attach interfaces, etc...)
router = self.manage_router(self.agent, router_info)
ext_gateway_port = router_info['gw_port']
self.assertTrue(self._namespace_exists(router.ns_name))
self.assertTrue(self._metadata_proxy_exists(self.agent.conf, router))
self._assert_internal_devices(router)
@ -1161,6 +1162,7 @@ class TestDvrRouter(L3AgentTestFramework):
self._assert_extra_routes(router, namespace=snat_ns_name)
self._delete_router(self.agent, router.router_id)
self._assert_fip_namespace_deleted(ext_gateway_port)
self._assert_router_does_not_exist(router)
def generate_dvr_router_info(self,
@ -1523,6 +1525,12 @@ class TestDvrRouter(L3AgentTestFramework):
self.assertFalse(sg_device)
self.assertTrue(qg_device)
def _assert_fip_namespace_deleted(self, ext_gateway_port):
ext_net_id = ext_gateway_port['network_id']
self.agent.fipnamespace_delete_on_ext_net(
self.agent.context, ext_net_id)
self._assert_interfaces_deleted_from_ovs()
def test_dvr_router_static_routes(self):
"""Test to validate the extra routes on dvr routers."""
self.agent.conf.agent_mode = 'dvr_snat'

View File

@ -301,16 +301,19 @@ class L3DvrTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
'foo_host')
def _setup_delete_current_gw_port_deletes_fip_agent_gw_port(
self, port=None):
gw_port_db = {
'id': 'my_gw_id',
'network_id': 'ext_net_id',
'device_owner': l3_const.DEVICE_OWNER_ROUTER_GW
}
self, port=None, gw_port=True):
router = mock.MagicMock()
router.extra_attributes.distributed = True
router['gw_port_id'] = gw_port_db['id']
router.gw_port = gw_port_db
if gw_port:
gw_port_db = {
'id': 'my_gw_id',
'network_id': 'ext_net_id',
'device_owner': l3_const.DEVICE_OWNER_ROUTER_GW
}
router.gw_port = gw_port_db
else:
router.gw_port = None
with mock.patch.object(manager.NeutronManager, 'get_plugin') as gp,\
mock.patch.object(l3_dvr_db.l3_db.L3_NAT_db_mixin,
'_delete_current_gw_port'),\
@ -322,24 +325,28 @@ class L3DvrTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
'delete_csnat_router_interface_ports') as del_csnat_port,\
mock.patch.object(
self.mixin,
'delete_floatingip_agent_gateway_port') as del_agent_gw_port:
'delete_floatingip_agent_gateway_port') as del_agent_gw_port,\
mock.patch.object(
self.mixin.l3_rpc_notifier,
'delete_fipnamespace_for_ext_net') as del_fip:
plugin = mock.Mock()
gp.return_value = plugin
plugin.get_ports.return_value = port
grtr.return_value = router
self.mixin._delete_current_gw_port(
self.ctx, router['id'], router, 'ext_network_id')
return router, plugin, del_csnat_port, del_agent_gw_port
return router, plugin, del_csnat_port, del_agent_gw_port, del_fip
def test_delete_current_gw_port_deletes_fip_agent_gw_port(self):
rtr, plugin, d_csnat_port, d_agent_gw_port = (
def test_delete_current_gw_port_deletes_fip_agent_gw_port_and_fipnamespace(
self):
rtr, plugin, d_csnat_port, d_agent_gw_port, del_fip = (
self._setup_delete_current_gw_port_deletes_fip_agent_gw_port())
self.assertTrue(d_csnat_port.called)
self.assertTrue(d_agent_gw_port.called)
d_csnat_port.assert_called_once_with(
mock.ANY, rtr)
d_agent_gw_port.assert_called_once_with(
mock.ANY, None, 'ext_net_id')
d_agent_gw_port.assert_called_once_with(mock.ANY, None, 'ext_net_id')
del_fip.assert_called_once_with(mock.ANY, 'ext_net_id')
def test_delete_current_gw_port_never_calls_delete_fip_agent_gw_port(self):
port = [{
@ -352,14 +359,23 @@ class L3DvrTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
'network_id': 'ext_net_id',
'device_owner': l3_const.DEVICE_OWNER_ROUTER_GW
}]
rtr, plugin, d_csnat_port, d_agent_gw_port = (
rtr, plugin, d_csnat_port, d_agent_gw_port, del_fip = (
self._setup_delete_current_gw_port_deletes_fip_agent_gw_port(
port=port))
self.assertTrue(d_csnat_port.called)
self.assertFalse(d_agent_gw_port.called)
self.assertFalse(del_fip.called)
d_csnat_port.assert_called_once_with(
mock.ANY, rtr)
def test_delete_current_gw_port_never_calls_delete_fipnamespace(self):
rtr, plugin, d_csnat_port, d_agent_gw_port, del_fip = (
self._setup_delete_current_gw_port_deletes_fip_agent_gw_port(
gw_port=False))
self.assertFalse(d_csnat_port.called)
self.assertFalse(d_agent_gw_port.called)
self.assertFalse(del_fip.called)
def _floatingip_on_port_test_setup(self, hostid):
router = {'id': 'foo_router_id', 'distributed': True}
floatingip = {