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:
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()
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,
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})
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
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):
router.ns_name)
utils.wait_until_true(device_exists)
+ ext_gateway_port = router_info['gw_port']
self.assertTrue(self._namespace_exists(router.ns_name))
utils.wait_until_true(
lambda: self._metadata_proxy_exists(self.agent.conf, router))
router, ip_versions, 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)
self._assert_snat_namespace_does_not_exist(router)
self._assert_ip_addresses_in_dvr_ha_snat_namespace(router2)
self._assert_no_ip_addresses_in_dvr_ha_snat_namespace(router1)
+
+ 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()
'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'),\
'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 = [{
'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 = {