Fix update router API

The semantics for the update router API call were affected by the
introduction of the SNAT subnet only extension patch series. This
patch modifies the API to support the upstream semantics, while
still supporting the new extension.

Change-Id: Ia1244876b19b364295cf4198a809d820810a16c5
This commit is contained in:
Thomas Bachman 2021-10-13 02:19:08 +00:00
parent 9c0d8b55c2
commit 3566dbaf1c
1 changed files with 19 additions and 45 deletions

View File

@ -173,59 +173,46 @@ class ApicL3Plugin(common_db_mixin.CommonDbMixin,
page_reverse=page_reverse)
return self._make_routers_dict(routers_db, fields)
def _check_snat_subnets(self, context, gw_info, router, method, *args):
result = None
def _check_snat_subnets(self, context, gw_info, router):
self._core_plugin._get_network(context, gw_info['network_id'])
if ('external_fixed_ips' in gw_info):
# Check to make sure they haven't picked a subnet
# that has an extension set to disallow it.
self.validate_snat_extension(context, gw_info)
else:
# No subnet set, so check to see if should be allocating one
# from non-SNAT subnets.
# No subnet set, so look for at most one subnet in
# each address family to include in the request,
# skipping any subnets with the SNAT only extension
# set to True.
subnets_in_nw = self._core_plugin.get_subnets_by_network(context,
gw_info['network_id'])
subs = {}
for ext_sn in subnets_in_nw:
if (ext_sn['apic:snat_subnet_only'] is False):
fixed_ips = [{'subnet_id': ext_sn['id']}]
gw_info.update({'external_fixed_ips': fixed_ips})
router['router'].update({EXTERNAL_GW_INFO: gw_info})
try:
result = method(*args)
break
except exceptions.IpAddressGenerationFailure:
LOG.info('No more IP addresses available '
'in subnet %s for gateway', ext_sn)
return result
if (ext_sn['apic:snat_subnet_only'] is False and
not subs.get(ext_sn['ip_version'])):
subs[ext_sn['ip_version']] = {'subnet_id': ext_sn['id']}
gw_info.update({'external_fixed_ips': list(subs.values())})
router['router'].update({EXTERNAL_GW_INFO: gw_info})
# REVISIT: Eliminate this wrapper?
@n_utils.transaction_guard
def create_router(self, context, router):
method = super(ApicL3Plugin, self).create_router
args = (context, router)
LOG.debug("APIC AIM L3 Plugin creating router: %s", router)
# REVISIT: Do this in MD by registering for
# ROUTER.BEFORE_CREATE event.
self._md.ensure_tenant(context, router['router']['tenant_id'])
result = None
current = router['router']
gw_info = (current[EXTERNAL_GW_INFO] if EXTERNAL_GW_INFO in current
else lib_constants.ATTR_NOT_SPECIFIED)
if (gw_info and gw_info != lib_constants.ATTR_NOT_SPECIFIED and
'network_id' in gw_info):
result = self._check_snat_subnets(context, gw_info, router,
method, *args)
if result:
return result
else:
return method(context, router)
self._check_snat_subnets(context, gw_info, router)
return super(ApicL3Plugin, self).create_router(context, router)
# REVISIT: Eliminate this wrapper?
@n_utils.transaction_guard
def update_router(self, context, id, router):
method = super(ApicL3Plugin, self).update_router
args = (context, id, router)
original = self.get_router(context, id)
current = router['router']
original_gw_info = (original[EXTERNAL_GW_INFO]
@ -238,28 +225,15 @@ class ApicL3Plugin(common_db_mixin.CommonDbMixin,
LOG.debug("APIC AIM L3 Plugin updating router %(id)s with: %(router)s",
{'id': id, 'router': router})
# User is deleting the gateway info
if (not current_gw_info and original_gw_info):
return method(context, id, router)
# User is updating info other than gateway info
if (current_gw_info == original_gw_info):
return method(context, id, router)
# No gw info yet / gw info is being updated
result = None
# If the gateway is being set, do additional validation for
# the SNAT only subnets extension.
if ((current_gw_info and
current_gw_info != lib_constants.ATTR_NOT_SPECIFIED) and
(not original_gw_info or
original_gw_info == lib_constants.ATTR_NOT_SPECIFIED or
original_gw_info != current_gw_info) and ('network_id' in
current_gw_info)):
result = self._check_snat_subnets(context, current_gw_info,
router, method, *args)
if result:
return result
else:
return method(context, id, router)
original_gw_info == lib_constants.ATTR_NOT_SPECIFIED) and (
'network_id' in current_gw_info)):
self._check_snat_subnets(context, current_gw_info, router)
return super(ApicL3Plugin, self).update_router(context, id, router)
# REVISIT: Eliminate this wrapper?
@n_utils.transaction_guard