Use callbacks to create DVR floating GW port
This stops the DVR mixin from overriding the '_update_fip_assoc' function in order to create its agent floating IP gateway ports. It instead now subscribes to the floating IP AFTER_UPDATE event to create these ports. Additionally, it fixes the semantics of the floating IP AFTER_UPDATE event so it's emitted after the update is committed to the DB so it's safe to call core plugin mutation methods and external systems. In addition to fixing the callback semantics, this is part of the effort to eliminate GUARD_TRANSACTION in-tree, which should pave the way for ML2 to adopt the new engine facade and for push notifications to safely transmit the latest DB state. Related-Bug: #1540844 Partially-Implements: blueprint push-notifications Partially-Implements: blueprint enginefacade-switch Change-Id: I93e4d847f96707b17c4a7dfdb3bbf81d062fe3fb
This commit is contained in:
parent
8eac5e2db7
commit
03f7ec38b6
|
@ -1166,18 +1166,15 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
|
|||
if addr.version == lib_constants.IP_VERSION_4:
|
||||
next_hop = fixed_ip.ip_address
|
||||
break
|
||||
args = {'fixed_ip_address': internal_ip_address,
|
||||
return {'fixed_ip_address': internal_ip_address,
|
||||
'fixed_port_id': port_id,
|
||||
'router_id': router_id,
|
||||
'last_known_router_id': previous_router_id,
|
||||
'floating_ip_address': floatingip_db.floating_ip_address,
|
||||
'floating_network_id': floatingip_db.floating_network_id,
|
||||
'floating_ip_id': floatingip_db.id,
|
||||
'next_hop': next_hop,
|
||||
'context': context}
|
||||
registry.notify(resources.FLOATING_IP,
|
||||
events.AFTER_UPDATE,
|
||||
self._update_fip_assoc,
|
||||
**args)
|
||||
|
||||
def _is_ipv4_network(self, context, net_id):
|
||||
net = self._core_plugin._get_network(context, net_id)
|
||||
|
@ -1242,14 +1239,18 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
|
|||
description=fip.get('description'))
|
||||
# Update association with internal port
|
||||
# and define external IP address
|
||||
self._update_fip_assoc(context, fip,
|
||||
floatingip_db, external_port)
|
||||
assoc_result = self._update_fip_assoc(context, fip,
|
||||
floatingip_db, external_port)
|
||||
context.session.add(floatingip_db)
|
||||
floatingip_dict = self._make_floatingip_dict(
|
||||
floatingip_db, process_extensions=False)
|
||||
if self._is_dns_integration_supported:
|
||||
dns_data = self._process_dns_floatingip_create_precommit(
|
||||
context, floatingip_dict, fip)
|
||||
registry.notify(resources.FLOATING_IP,
|
||||
events.AFTER_UPDATE,
|
||||
self._update_fip_assoc,
|
||||
**assoc_result)
|
||||
|
||||
if self._is_dns_integration_supported:
|
||||
self._process_dns_floatingip_create_postcommit(context,
|
||||
|
@ -1270,13 +1271,17 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
|
|||
floatingip_db = self._get_floatingip(context, id)
|
||||
old_floatingip = self._make_floatingip_dict(floatingip_db)
|
||||
fip_port_id = floatingip_db['floating_port_id']
|
||||
self._update_fip_assoc(context, fip, floatingip_db,
|
||||
self._core_plugin.get_port(
|
||||
context.elevated(), fip_port_id))
|
||||
assoc_result = self._update_fip_assoc(
|
||||
context, fip, floatingip_db,
|
||||
self._core_plugin.get_port(context.elevated(), fip_port_id))
|
||||
floatingip_dict = self._make_floatingip_dict(floatingip_db)
|
||||
if self._is_dns_integration_supported:
|
||||
dns_data = self._process_dns_floatingip_update_precommit(
|
||||
context, floatingip_dict)
|
||||
registry.notify(resources.FLOATING_IP,
|
||||
events.AFTER_UPDATE,
|
||||
self._update_fip_assoc,
|
||||
**assoc_result)
|
||||
|
||||
if self._is_dns_integration_supported:
|
||||
self._process_dns_floatingip_update_postcommit(context,
|
||||
|
|
|
@ -70,6 +70,12 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
|
|||
'default': cfg.CONF.router_distributed
|
||||
}])
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
n = super(L3_NAT_with_dvr_db_mixin, cls).__new__(cls, *args, **kwargs)
|
||||
registry.subscribe(n._create_dvr_floating_gw_port,
|
||||
resources.FLOATING_IP, events.AFTER_UPDATE)
|
||||
return n
|
||||
|
||||
def _create_router_db(self, context, router, tenant_id):
|
||||
"""Create a router db object with dvr additions."""
|
||||
with context.session.begin(subtransactions=True):
|
||||
|
@ -221,39 +227,33 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
|
|||
models_v2.Port.admin_state_up == True) # noqa
|
||||
return query.all()
|
||||
|
||||
def _update_fip_assoc(self, context, fip, floatingip_db, external_port):
|
||||
"""Override to create floating agent gw port for DVR.
|
||||
def _create_dvr_floating_gw_port(self, resource, event, trigger, context,
|
||||
router_id, fixed_port_id, floating_ip_id,
|
||||
floating_network_id, fixed_ip_address,
|
||||
**kwargs):
|
||||
"""Create floating agent gw port for DVR.
|
||||
|
||||
Floating IP Agent gateway port will be created when a
|
||||
floatingIP association happens.
|
||||
"""
|
||||
fip_port = fip.get('port_id')
|
||||
super(L3_NAT_with_dvr_db_mixin, self)._update_fip_assoc(
|
||||
context, fip, floatingip_db, external_port)
|
||||
associate_fip = fip_port and floatingip_db['id']
|
||||
if associate_fip and floatingip_db.get('router_id'):
|
||||
associate_fip = fixed_port_id and floating_ip_id
|
||||
if associate_fip and router_id:
|
||||
admin_ctx = context.elevated()
|
||||
router_dict = self.get_router(
|
||||
admin_ctx, floatingip_db['router_id'])
|
||||
router_dict = self.get_router(admin_ctx, router_id)
|
||||
# Check if distributed router and then create the
|
||||
# FloatingIP agent gateway port
|
||||
if router_dict.get('distributed'):
|
||||
hostid = self._get_dvr_service_port_hostid(
|
||||
context, fip_port)
|
||||
hostid = self._get_dvr_service_port_hostid(context,
|
||||
fixed_port_id)
|
||||
if hostid:
|
||||
# FIXME (Swami): This FIP Agent Gateway port should be
|
||||
# created only once and there should not be a duplicate
|
||||
# for the same host. Until we find a good solution for
|
||||
# augmenting multiple server requests we should use the
|
||||
# existing flow.
|
||||
# FIXME(kevinbenton): refactor so this happens outside
|
||||
# of floating IP transaction since it creates a port
|
||||
# via ML2.
|
||||
setattr(admin_ctx, 'GUARD_TRANSACTION', False)
|
||||
fip_agent_port = (
|
||||
self.create_fip_agent_gw_port_if_not_exists(
|
||||
admin_ctx, external_port['network_id'],
|
||||
hostid))
|
||||
admin_ctx, floating_network_id, hostid))
|
||||
LOG.debug("FIP Agent gateway port: %s", fip_agent_port)
|
||||
else:
|
||||
# If not hostid check if the fixed ip provided has to
|
||||
|
@ -261,7 +261,7 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
|
|||
# port. Get the port_dict, inherit the service port host
|
||||
# and device owner(if it does not exist).
|
||||
port = self._core_plugin.get_port(
|
||||
admin_ctx, fip_port)
|
||||
admin_ctx, fixed_port_id)
|
||||
allowed_device_owners = (
|
||||
n_utils.get_dvr_allowed_address_pair_device_owners())
|
||||
# NOTE: We just need to deal with ports that do not
|
||||
|
@ -273,7 +273,7 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
|
|||
addr_pair_active_service_port_list = (
|
||||
self._get_ports_for_allowed_address_pair_ip(
|
||||
admin_ctx, port['network_id'],
|
||||
floatingip_db['fixed_ip_address']))
|
||||
fixed_ip_address))
|
||||
if not addr_pair_active_service_port_list:
|
||||
return
|
||||
if len(addr_pair_active_service_port_list) > 1:
|
||||
|
|
|
@ -19,6 +19,9 @@ from neutron_lib import exceptions
|
|||
from oslo_utils import uuidutils
|
||||
import testtools
|
||||
|
||||
from neutron.callbacks import events
|
||||
from neutron.callbacks import registry
|
||||
from neutron.callbacks import resources
|
||||
from neutron.common import constants as n_const
|
||||
from neutron import context
|
||||
from neutron.db import agents_db
|
||||
|
@ -445,8 +448,11 @@ class L3DvrTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
|
|||
grtr.return_value = router_db
|
||||
vmp.return_value = 'my-host'
|
||||
mvmp.return_value = 'my-future-host'
|
||||
self.mixin._update_fip_assoc(
|
||||
self.ctx, fip, floatingip_db, port)
|
||||
registry.notify(resources.FLOATING_IP, events.AFTER_UPDATE, self,
|
||||
context=mock.Mock(), router_id=router_db['id'],
|
||||
fixed_port_id=port['id'], floating_ip_id=fip['id'],
|
||||
floating_network_id=fip['floating_network_id'],
|
||||
fixed_ip_address='1.2.3.4')
|
||||
return c_fip
|
||||
|
||||
def test_create_floatingip_agent_gw_port_with_dvr_router(self):
|
||||
|
@ -457,6 +463,7 @@ class L3DvrTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
|
|||
router = {'id': 'foo_router_id', 'distributed': True}
|
||||
fip = {
|
||||
'id': _uuid(),
|
||||
'floating_network_id': _uuid(),
|
||||
'port_id': _uuid()
|
||||
}
|
||||
create_fip = (
|
||||
|
@ -472,6 +479,7 @@ class L3DvrTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
|
|||
router = {'id': 'foo_router_id', 'distributed': False}
|
||||
fip = {
|
||||
'id': _uuid(),
|
||||
'floating_network_id': _uuid(),
|
||||
'port_id': _uuid()
|
||||
}
|
||||
create_fip = (
|
||||
|
|
|
@ -2347,6 +2347,7 @@ class L3NatTestCaseBase(L3NatTestCaseMixin):
|
|||
{'floatingip': {'port_id': port_id}})
|
||||
fip_addr = fip['floatingip']['floating_ip_address']
|
||||
fip_network_id = fip['floatingip']['floating_network_id']
|
||||
fip_id = fip['floatingip']['id']
|
||||
router_id = body['floatingip']['router_id']
|
||||
body = self._show('routers', router_id)
|
||||
ext_gw_info = body['router']['external_gateway_info']
|
||||
|
@ -2360,6 +2361,7 @@ class L3NatTestCaseBase(L3NatTestCaseMixin):
|
|||
floating_ip_address=fip_addr,
|
||||
floating_network_id=fip_network_id,
|
||||
last_known_router_id=None,
|
||||
floating_ip_id=fip_id,
|
||||
router_id=router_id,
|
||||
next_hop=ext_fixed_ip['ip_address'])
|
||||
|
||||
|
@ -2375,6 +2377,7 @@ class L3NatTestCaseBase(L3NatTestCaseMixin):
|
|||
with mock.patch.object(registry, 'notify') as notify:
|
||||
fip_addr = fip['floatingip']['floating_ip_address']
|
||||
fip_network_id = fip['floatingip']['floating_network_id']
|
||||
fip_id = fip['floatingip']['id']
|
||||
router_id = body['floatingip']['router_id']
|
||||
self._update('floatingips',
|
||||
fip['floatingip']['id'],
|
||||
|
@ -2388,6 +2391,7 @@ class L3NatTestCaseBase(L3NatTestCaseMixin):
|
|||
floating_ip_address=fip_addr,
|
||||
floating_network_id=fip_network_id,
|
||||
last_known_router_id=router_id,
|
||||
floating_ip_id=fip_id,
|
||||
router_id=None,
|
||||
next_hop=None)
|
||||
|
||||
|
|
Loading…
Reference in New Issue