Implement Floating IP association logic only once

Implement the Floating IP association logic only in one single place,
L3_NAT_dbonly_mixin._update_fip_assoc(). The dictionary returned will
include a new key, "association_event", with values:
- None: there is no association event. The internal port does not
  change.
- True: a new internal port is added to the FIP register. An
  association event can imply a disassociation event if the FIP register
  had an existing internal port.
- False: the previous internal port is removed and no one is added.

Change-Id: I775aee178cf56f842b3c0a375eda01577840e227
Related-Bug: #1842327
This commit is contained in:
Rodolfo Alonso Hernandez 2019-09-09 10:58:46 +00:00
parent 0809f4e224
commit 1947fd65d2
4 changed files with 20 additions and 18 deletions

@ -1239,10 +1239,13 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
# {'port_id': null}, then the floating IP cloud also be dissociated. # {'port_id': null}, then the floating IP cloud also be dissociated.
return port_id, internal_ip_address, router_id return port_id, internal_ip_address, router_id
def _update_fip_assoc(self, context, fip, floatingip_obj, external_port): def _update_fip_assoc(self, context, fip, floatingip_obj):
previous_router_id = floatingip_obj.router_id previous_router_id = floatingip_obj.router_id
port_id, internal_ip_address, router_id = ( port_id, internal_ip_address, router_id = (
self._check_and_get_fip_assoc(context, fip, floatingip_obj)) self._check_and_get_fip_assoc(context, fip, floatingip_obj))
association_event = None
if floatingip_obj.fixed_port_id != port_id:
association_event = bool(port_id)
floatingip_obj.fixed_ip_address = ( floatingip_obj.fixed_ip_address = (
netaddr.IPAddress(internal_ip_address) netaddr.IPAddress(internal_ip_address)
if internal_ip_address else None) if internal_ip_address else None)
@ -1260,7 +1263,8 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
'floating_ip_address': floating_ip_address, 'floating_ip_address': floating_ip_address,
'floating_network_id': floatingip_obj.floating_network_id, 'floating_network_id': floatingip_obj.floating_network_id,
'floating_ip_id': floatingip_obj.id, 'floating_ip_id': floatingip_obj.id,
'context': context} 'context': context,
'association_event': association_event}
def _is_ipv4_network(self, context, net_id): def _is_ipv4_network(self, context, net_id):
net = self._core_plugin._get_network(context, net_id) net = self._core_plugin._get_network(context, net_id)
@ -1339,8 +1343,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
description=fip.get('description')) description=fip.get('description'))
# Update association with internal port # Update association with internal port
# and define external IP address # and define external IP address
assoc_result = self._update_fip_assoc( assoc_result = self._update_fip_assoc(context, fip, floatingip_obj)
context, fip, floatingip_obj, external_port)
floatingip_obj.create() floatingip_obj.create()
floatingip_dict = self._make_floatingip_dict( floatingip_dict = self._make_floatingip_dict(
floatingip_obj, process_extensions=False) floatingip_obj, process_extensions=False)
@ -1366,7 +1369,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
events.AFTER_UPDATE, events.AFTER_UPDATE,
self._update_fip_assoc, self._update_fip_assoc,
**assoc_result) **assoc_result)
if assoc_result['fixed_ip_address'] and assoc_result['fixed_port_id']: if assoc_result['association_event']:
LOG.info(FIP_ASSOC_MSG, LOG.info(FIP_ASSOC_MSG,
{'fip_id': assoc_result['floating_ip_id'], {'fip_id': assoc_result['floating_ip_id'],
'ext_ip': assoc_result['floating_ip_address'], 'ext_ip': assoc_result['floating_ip_address'],
@ -1402,11 +1405,8 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
with context.session.begin(subtransactions=True): with context.session.begin(subtransactions=True):
floatingip_obj = self._get_floatingip(context, id) floatingip_obj = self._get_floatingip(context, id)
old_floatingip = self._make_floatingip_dict(floatingip_obj) old_floatingip = self._make_floatingip_dict(floatingip_obj)
fip_port_id = floatingip_obj.floating_port_id
old_fixed_port_id = floatingip_obj.fixed_port_id old_fixed_port_id = floatingip_obj.fixed_port_id
assoc_result = self._update_fip_assoc( assoc_result = self._update_fip_assoc(context, fip, floatingip_obj)
context, fip, floatingip_obj,
self._core_plugin.get_port(context.elevated(), fip_port_id))
floatingip_obj.update() floatingip_obj.update()
floatingip_dict = self._make_floatingip_dict(floatingip_obj) floatingip_dict = self._make_floatingip_dict(floatingip_obj)
@ -1433,10 +1433,10 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
events.AFTER_UPDATE, events.AFTER_UPDATE,
self._update_fip_assoc, self._update_fip_assoc,
**assoc_result) **assoc_result)
if old_fixed_port_id != assoc_result['fixed_port_id']: if assoc_result['association_event'] is not None:
assoc = ('associated' if assoc_result['fixed_port_id']
else 'disassociated')
port_id = old_fixed_port_id or assoc_result['fixed_port_id'] port_id = old_fixed_port_id or assoc_result['fixed_port_id']
assoc = ('associated' if assoc_result['association_event']
else 'disassociated')
LOG.info(FIP_ASSOC_MSG, LOG.info(FIP_ASSOC_MSG,
{'fip_id': assoc_result['floating_ip_id'], {'fip_id': assoc_result['floating_ip_id'],
'ext_ip': assoc_result['floating_ip_address'], 'ext_ip': assoc_result['floating_ip_address'],
@ -1625,6 +1625,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
'floating_ip_id': fip.id, 'floating_ip_id': fip.id,
'context': context, 'context': context,
'router_ids': router_ids, 'router_ids': router_ids,
'association_event': False,
} }
registry.notify(resources.FLOATING_IP, events.AFTER_UPDATE, self, registry.notify(resources.FLOATING_IP, events.AFTER_UPDATE, self,
**assoc_result) **assoc_result)

@ -391,14 +391,13 @@ class DVRResourceOperationHandler(object):
def _create_dvr_floating_gw_port(self, resource, event, trigger, context, def _create_dvr_floating_gw_port(self, resource, event, trigger, context,
router_id, fixed_port_id, floating_ip_id, router_id, fixed_port_id, floating_ip_id,
floating_network_id, fixed_ip_address, floating_network_id, fixed_ip_address,
**kwargs): association_event, **kwargs):
"""Create floating agent gw port for DVR. """Create floating agent gw port for DVR.
Floating IP Agent gateway port will be created when a Floating IP Agent gateway port will be created when a
floatingIP association happens. floatingIP association happens.
""" """
associate_fip = fixed_port_id and floating_ip_id if association_event and router_id:
if associate_fip and router_id:
admin_ctx = context.elevated() admin_ctx = context.elevated()
router_dict = self.get_router(admin_ctx, router_id) router_dict = self.get_router(admin_ctx, router_id)
# Check if distributed router and then create the # Check if distributed router and then create the

@ -605,7 +605,7 @@ class L3DvrTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
context=mock.Mock(), router_id=router_db['id'], context=mock.Mock(), router_id=router_db['id'],
fixed_port_id=port['id'], floating_ip_id=fip['id'], fixed_port_id=port['id'], floating_ip_id=fip['id'],
floating_network_id=fip['floating_network_id'], floating_network_id=fip['floating_network_id'],
fixed_ip_address='1.2.3.4') fixed_ip_address='1.2.3.4', association_event=True)
return c_fip return c_fip
def test_create_floatingip_agent_gw_port_with_dvr_router(self): def test_create_floatingip_agent_gw_port_with_dvr_router(self):

@ -2668,7 +2668,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin):
floating_network_id=fip_network_id, floating_network_id=fip_network_id,
last_known_router_id=None, last_known_router_id=None,
floating_ip_id=fip_id, floating_ip_id=fip_id,
router_id=router_id) router_id=router_id,
association_event=True)
def test_floatingip_disassociate_notification(self): def test_floatingip_disassociate_notification(self):
with self.port() as p: with self.port() as p:
@ -2697,7 +2698,8 @@ class L3NatTestCaseBase(L3NatTestCaseMixin):
floating_network_id=fip_network_id, floating_network_id=fip_network_id,
last_known_router_id=router_id, last_known_router_id=router_id,
floating_ip_id=fip_id, floating_ip_id=fip_id,
router_id=None) router_id=None,
association_event=False)
def test_floatingip_association_on_unowned_router(self): def test_floatingip_association_on_unowned_router(self):
# create a router owned by one tenant and associate the FIP with a # create a router owned by one tenant and associate the FIP with a