Add notification for floatingip update/delete

As neutron now allows L3 Flavors, but when other backends use L3
flavors, the floating delete only commits db transaction therefore
removing fip from neutron db but backend still have that fip as active
because there's no notification for the subscribed precommit_delete
event.

Co-Authored-By: Isaku Yamahata <isaku.yamahata@intel.com>
Change-Id: I87dd124cc5bf17365ca197e4b35ffaa7825ca17c
Closes-Bug: #1742802
This commit is contained in:
Manjeet Singh Bhatia 2018-01-16 13:04:07 -08:00
parent bc150cdbf8
commit 257de15310
3 changed files with 66 additions and 2 deletions

View File

@ -173,6 +173,8 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
"deleting.", port_id)
self._core_plugin.delete_port(
context, port_id, l3_port_check=False)
registry.notify(resources.FLOATING_IP, events.AFTER_DELETE,
self, **fips[0])
def _get_dead_floating_port_candidates(self, context):
filters = {'device_id': ['PENDING'],
@ -1392,6 +1394,13 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
floatingip_obj = l3_obj.FloatingIP.get_object(
context, id=floatingip_obj.id)
floatingip_db = floatingip_obj.db_obj
registry.notify(resources.FLOATING_IP,
events.PRECOMMIT_UPDATE,
self,
floatingip=floatingip,
floatingip_db=floatingip_db,
old_floatingip=old_floatingip,
**assoc_result)
registry.notify(resources.FLOATING_IP,
events.AFTER_UPDATE,
@ -1425,6 +1434,14 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
return l3_obj.FloatingIP.update_object(
context, {'status': status}, id=floatingip_id)
@registry.receives(resources.PORT, [events.PRECOMMIT_DELETE])
def _precommit_delete_port_callback(
self, resource, event, trigger, **kwargs):
if (kwargs['port']['device_owner'] ==
constants.DEVICE_OWNER_FLOATINGIP):
registry.notify(resources.FLOATING_IP, events.PRECOMMIT_DELETE,
self, **kwargs)
def _delete_floatingip(self, context, id):
floatingip = self._get_floatingip(context, id)
floatingip_dict = self._make_floatingip_dict(floatingip)
@ -1437,6 +1454,8 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
self._core_plugin.delete_port(context.elevated(),
floatingip.floating_port_id,
l3_port_check=False)
registry.notify(resources.FLOATING_IP, events.AFTER_DELETE,
self, **floatingip_dict)
return floatingip_dict
@db_api.retry_if_session_inactive()
@ -1547,12 +1566,34 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
floating_ip_objs = l3_obj.FloatingIP.get_objects(
context, fixed_port_id=port_id)
router_ids = {fip.router_id for fip in floating_ip_objs}
old_fips = {fip.id: fip.to_dict() for fip in floating_ip_objs}
values = {'fixed_port_id': None,
'fixed_ip_address': None,
'router_id': None}
l3_obj.FloatingIP.update_objects(
context, values, fixed_port_id=port_id)
return router_ids
for fip in floating_ip_objs:
registry.notify(resources.FLOATING_IP, events.PRECOMMIT_UPDATE,
self,
floatingip={l3_apidef.FLOATINGIP: values},
floatingip_db=fip,
old_floatingip=old_fips[fip.id],
router_ids=router_ids)
for fip in floating_ip_objs:
assoc_result = {
'fixed_ip_address': None,
'fixed_port_id': None,
'router_id': None,
'floating_ip_address': fip.floating_ip_address,
'floating_network_id': fip.floating_network_id,
'floating_ip_id': fip.id,
'context': context,
'router_ids': router_ids,
}
registry.notify(resources.FLOATING_IP, events.AFTER_UPDATE, self,
**assoc_result)
return router_ids
def _get_floatingips_by_port_id(self, context, port_id):
"""Helper function to retrieve the fips associated with a port_id."""

View File

@ -1524,6 +1524,14 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
network = self.get_network(context, port['network_id'])
bound_mech_contexts = []
kwargs = {
'context': context,
'id': id,
'network': network,
'port': port,
'port_db': port_db,
'bindings': binding,
}
device_owner = port['device_owner']
if device_owner == const.DEVICE_OWNER_DVR_INTERFACE:
bindings = db.get_distributed_port_bindings(context,
@ -1531,6 +1539,10 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
for bind in bindings:
levels = db.get_binding_levels(context, id,
bind.host)
kwargs['bind'] = bind
kwargs['levels'] = levels
registry.notify(resources.PORT, events.PRECOMMIT_DELETE,
self, **kwargs)
mech_context = driver_context.PortContext(
self, context, port, network, bind, levels)
self.mechanism_manager.delete_port_precommit(mech_context)
@ -1538,6 +1550,10 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
else:
levels = db.get_binding_levels(context, id,
binding.host)
kwargs['bind'] = None
kwargs['levels'] = levels
registry.notify(resources.PORT, events.PRECOMMIT_DELETE,
self, **kwargs)
mech_context = driver_context.PortContext(
self, context, port, network, binding, levels)
self.mechanism_manager.delete_port_precommit(mech_context)

View File

@ -1574,6 +1574,8 @@ class TestMl2DvrPortsV2(TestMl2PortsV2):
ns_to_delete = {'host': 'myhost', 'agent_id': 'vm_l3_agent',
'router_id': 'my_router'}
router_ids = set()
call_count_total = 3
if floating_ip:
router_ids.add(ns_to_delete['router_id'])
@ -1584,12 +1586,17 @@ class TestMl2DvrPortsV2(TestMl2PortsV2):
return_value=router_ids):
port_id = port['port']['id']
self.plugin.delete_port(self.context, port_id)
self.assertEqual(2, notify.call_count)
self.assertEqual(call_count_total, notify.call_count)
# needed for a full match in the assertion below
port['port']['extra_dhcp_opts'] = []
expected = [mock.call(resources.PORT, events.BEFORE_DELETE,
mock.ANY, context=self.context,
port_id=port['port']['id'], port_check=True),
mock.call(resources.PORT, events.PRECOMMIT_DELETE,
mock.ANY, network=mock.ANY, bind=mock.ANY,
port=port['port'], port_db=mock.ANY,
context=self.context, levels=mock.ANY,
id=mock.ANY, bindings=mock.ANY),
mock.call(resources.PORT, events.AFTER_DELETE,
mock.ANY, context=self.context,
port=port['port'],