Merge "Delete fipnamespace when external net removed on DVR" into stable/liberty
This commit is contained in:
commit
2b87fee13b
|
@ -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:
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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 = {
|
||||
|
|
Loading…
Reference in New Issue