Make l2/l3 operations retriable at plugin level

This adds decorators to ML2/db_base_plugin_v2 and the L3
DB modules to make L2 and L3 resource operations retriable
at the plugin level.

Retrying the L2 operations in particular at this level should
go a long way to improving the reliability of complex operations
that require L2 resources in the face of deadlocks under high
concurrency.

Partial-Bug: #1612798
Partial-Bug: #1596075
Change-Id: I3c9437f7ecdd5ebb188b622144b7bd7bed74231d
This commit is contained in:
Kevin Benton 2016-09-07 18:42:40 -07:00
parent 09c87425fa
commit acbabaa3db
7 changed files with 86 additions and 7 deletions

View File

@ -41,6 +41,7 @@ from neutron.common import exceptions as n_exc
from neutron.common import ipv6_utils
from neutron.common import utils
from neutron import context as ctx
from neutron.db import api as db_api
from neutron.db import db_base_plugin_common
from neutron.db import ipam_pluggable_backend
from neutron.db import models_v2
@ -142,6 +143,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
registry.subscribe(self.validate_network_rbac_policy_change,
rbac_mixin.RBAC_POLICY, e)
@db_api.retry_if_session_inactive()
def validate_network_rbac_policy_change(self, resource, event, trigger,
context, object_type, policy,
**kwargs):
@ -329,9 +331,11 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
{'resource': resource, 'item': item})
return objects
@db_api.retry_if_session_inactive()
def create_network_bulk(self, context, networks):
return self._create_bulk('network', context, networks)
@db_api.retry_if_session_inactive()
def create_network(self, context, network):
"""Handle creation of a single network."""
net_db = self.create_network_db(context, network)
@ -360,6 +364,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
context.session.add(network)
return network
@db_api.retry_if_session_inactive()
def update_network(self, context, id, network):
n = network['network']
with context.session.begin(subtransactions=True):
@ -390,6 +395,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
models_v2.Network))
return self._make_network_dict(network, context=context)
@db_api.retry_if_session_inactive()
def delete_network(self, context, id):
with context.session.begin(subtransactions=True):
network = self._get_network(context, id)
@ -412,10 +418,12 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
context.session.delete(network)
@db_api.retry_if_session_inactive()
def get_network(self, context, id, fields=None):
network = self._get_network(context, id)
return self._make_network_dict(network, fields, context=context)
@db_api.retry_if_session_inactive()
def get_networks(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False):
@ -430,10 +438,12 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
marker_obj=marker_obj,
page_reverse=page_reverse)
@db_api.retry_if_session_inactive()
def get_networks_count(self, context, filters=None):
return self._get_collection_count(context, models_v2.Network,
filters=filters)
@db_api.retry_if_session_inactive()
def create_subnet_bulk(self, context, subnets):
return self._create_bulk('subnet', context, subnets)
@ -666,6 +676,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
msg = _('No default subnetpool found for IPv%s') % ip_version
raise exc.BadRequest(resource='subnets', msg=msg)
@db_api.retry_if_session_inactive()
def create_subnet(self, context, subnet):
s = subnet['subnet']
@ -719,6 +730,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
'end': str(netaddr.IPAddress(p.last, subnet['ip_version']))}
for p in allocation_pools]
@db_api.retry_if_session_inactive()
def update_subnet(self, context, id, subnet):
"""Update the subnet with new info.
@ -846,6 +858,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
"cannot delete", subnet_id)
raise exc.SubnetInUse(subnet_id=subnet_id)
@db_api.retry_if_session_inactive()
def delete_subnet(self, context, id):
with context.session.begin(subtransactions=True):
subnet = self._get_subnet(context, id)
@ -895,20 +908,24 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
# since there is no FK relationship
self.ipam.delete_subnet(context, id)
@db_api.retry_if_session_inactive()
def get_subnet(self, context, id, fields=None):
subnet = self._get_subnet(context, id)
return self._make_subnet_dict(subnet, fields, context=context)
@db_api.retry_if_session_inactive()
def get_subnets(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False):
return self._get_subnets(context, filters, fields, sorts, limit,
marker, page_reverse)
@db_api.retry_if_session_inactive()
def get_subnets_count(self, context, filters=None):
return self._get_collection_count(context, models_v2.Subnet,
filters=filters)
@db_api.retry_if_session_inactive()
def get_subnets_by_network(self, context, network_id):
return [self._make_subnet_dict(subnet_db) for subnet_db in
self._get_subnets_by_network(context, network_id)]
@ -982,6 +999,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
"been set. Only one default may exist per IP family")
raise exc.InvalidInput(error_message=msg)
@db_api.retry_if_session_inactive()
def create_subnetpool(self, context, subnetpool):
sp = subnetpool['subnetpool']
sp_reader = subnet_alloc.SubnetPoolReader(sp)
@ -1012,6 +1030,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
return self._make_subnetpool_dict(subnetpool)
@db_api.retry_if_session_inactive()
def update_subnetpool(self, context, id, subnetpool):
new_sp = subnetpool['subnetpool']
@ -1049,10 +1068,12 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
updated, orig_sp)
return updated
@db_api.retry_if_session_inactive()
def get_subnetpool(self, context, id, fields=None):
subnetpool = self._get_subnetpool(context, id)
return self._make_subnetpool_dict(subnetpool, fields)
@db_api.retry_if_session_inactive()
def get_subnetpools(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False):
@ -1064,6 +1085,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
for pool in subnetpools
]
@db_api.retry_if_session_inactive()
def get_default_subnetpool(self, context, ip_version):
"""Retrieve the default subnetpool for the given IP version."""
filters = {'is_default': True,
@ -1072,6 +1094,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
if subnetpool:
return subnetpool[0]
@db_api.retry_if_session_inactive()
def delete_subnetpool(self, context, id):
with context.session.begin(subtransactions=True):
subnetpool = self._get_subnetpool(context, id=id)
@ -1088,6 +1111,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
op=_("mac address update"), port_id=id,
device_owner=device_owner)
@db_api.retry_if_session_inactive()
def create_port_bulk(self, context, ports):
return self._create_bulk('port', context, ports)
@ -1104,6 +1128,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
context.session.add(db_port)
return db_port
@db_api.retry_if_session_inactive()
def create_port(self, context, port):
db_port = self.create_port_db(context, port)
return self._make_port_dict(db_port, process_extensions=False)
@ -1157,6 +1182,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
self._check_mac_addr_update(context, db_port,
new_mac, current_owner)
@db_api.retry_if_session_inactive()
def update_port(self, context, id, port):
new_port = port['port']
@ -1184,6 +1210,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
result = self._make_port_dict(db_port)
return result
@db_api.retry_if_session_inactive()
def delete_port(self, context, id):
with context.session.begin(subtransactions=True):
self.ipam.delete_port(context, id)
@ -1204,6 +1231,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
"The port has already been deleted.",
port_id)
@db_api.retry_if_session_inactive()
def get_port(self, context, id, fields=None):
port = self._get_port(context, id)
return self._make_port_dict(port, fields)
@ -1238,6 +1266,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
sort_dirs=sort_dirs)
return query
@db_api.retry_if_session_inactive()
def get_ports(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False):
@ -1251,6 +1280,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
items.reverse()
return items
@db_api.retry_if_session_inactive()
def get_ports_count(self, context, filters=None):
return self._get_ports_query(context, filters).count()

View File

@ -266,6 +266,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
self._update_router_gw_info(context, router_id,
gw_info, router=router_db)
@db_api.retry_if_session_inactive()
def create_router(self, context, router):
r = router['router']
gw_info = r.pop(EXTERNAL_GW_INFO, None)
@ -293,6 +294,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
old_router=old_router)
return router_db
@db_api.retry_if_session_inactive()
def update_router(self, context, id, router):
r = router['router']
gw_info = r.pop(EXTERNAL_GW_INFO, lib_constants.ATTR_NOT_SPECIFIED)
@ -562,6 +564,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
raise l3.RouterInUse(router_id=router_id)
return router
@db_api.retry_if_session_inactive()
def delete_router(self, context, id):
#TODO(nati) Refactor here when we have router insertion model
@ -578,10 +581,12 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
self, context=context, router_id=id)
context.session.delete(router)
@db_api.retry_if_session_inactive()
def get_router(self, context, id, fields=None):
router = self._get_router(context, id)
return self._make_router_dict(router, fields)
@db_api.retry_if_session_inactive()
def get_routers(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False):
@ -594,6 +599,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
marker_obj=marker_obj,
page_reverse=page_reverse)
@db_api.retry_if_session_inactive()
def get_routers_count(self, context, filters=None):
return self._get_collection_count(context, Router,
filters=filters)
@ -750,7 +756,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
port = self._find_ipv6_router_port_by_network(router,
subnet['network_id'])
if port:
fixed_ips = list(port['port']['fixed_ips'])
fixed_ips = list(map(dict, port['port']['fixed_ips']))
fixed_ips.append(fixed_ip)
return self._core_plugin.update_port(context,
port['port_id'], {'port':
@ -778,6 +784,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
'subnet_ids': subnet_ids
}
@db_api.retry_if_session_inactive()
def add_router_interface(self, context, router_id, interface_info):
router = self._get_router(context, router_id)
add_by_port, add_by_sub = self._validate_interface_info(interface_info)
@ -918,8 +925,8 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
port_subnets = [fip['subnet_id'] for fip in p['fixed_ips']]
if subnet_id in port_subnets and len(port_subnets) > 1:
# multiple prefix port - delete prefix from port
fixed_ips = [fip for fip in p['fixed_ips'] if
fip['subnet_id'] != subnet_id]
fixed_ips = [dict(fip) for fip in p['fixed_ips']
if fip['subnet_id'] != subnet_id]
self._core_plugin.update_port(context, p['id'],
{'port':
{'fixed_ips': fixed_ips}})
@ -934,6 +941,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
raise l3.RouterInterfaceNotFoundForSubnet(router_id=router_id,
subnet_id=subnet_id)
@db_api.retry_if_session_inactive()
def remove_router_interface(self, context, router_id, interface_info):
remove_by_port, remove_by_subnet = (
self._validate_interface_info(interface_info, for_removal=True)
@ -1282,6 +1290,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
floatingip_db)
return floatingip_dict
@db_api.retry_if_session_inactive()
def create_floatingip(self, context, floatingip,
initial_status=lib_constants.FLOATINGIP_STATUS_ACTIVE):
return self._create_floatingip(context, floatingip, initial_status)
@ -1312,11 +1321,13 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
for floatingip in floatingips
if floatingip['router_id']]))
@db_api.retry_if_session_inactive()
def update_floatingip(self, context, id, floatingip):
_old_floatingip, floatingip = self._update_floatingip(
context, id, floatingip)
return floatingip
@db_api.retry_if_session_inactive()
def update_floatingip_status(self, context, floatingip_id, status):
"""Update operational status for floating IP in neutron DB."""
fip_query = self._model_query(context, FloatingIP).filter(
@ -1337,13 +1348,16 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
l3_port_check=False)
return floatingip_dict
@db_api.retry_if_session_inactive()
def delete_floatingip(self, context, id):
self._delete_floatingip(context, id)
@db_api.retry_if_session_inactive()
def get_floatingip(self, context, id, fields=None):
floatingip = self._get_floatingip(context, id)
return self._make_floatingip_dict(floatingip, fields)
@db_api.retry_if_session_inactive()
def get_floatingips(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False):
@ -1362,6 +1376,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
marker_obj=marker_obj,
page_reverse=page_reverse)
@db_api.retry_if_session_inactive()
def delete_disassociated_floatingips(self, context, network_id):
query = self._model_query(context, FloatingIP)
query = query.filter_by(floating_network_id=network_id,
@ -1370,6 +1385,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
for fip in query:
self.delete_floatingip(context, fip.id)
@db_api.retry_if_session_inactive()
def get_floatingips_count(self, context, filters=None):
return self._get_collection_count(context, FloatingIP,
filters=filters)
@ -1435,6 +1451,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
raise n_exc.ServicePortInUse(port_id=port['id'],
reason=reason)
@db_api.retry_if_session_inactive()
def disassociate_floatingips(self, context, port_id, do_notify=True):
"""Disassociate all floating IPs linked to specific port.

View File

@ -305,6 +305,7 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
floating_ip = fip_qry.filter_by(fixed_port_id=port_id)
return floating_ip.first()
@db_api.retry_if_session_inactive()
def add_router_interface(self, context, router_id, interface_info):
add_by_port, add_by_sub = self._validate_interface_info(interface_info)
router = self._get_router(context, router_id)
@ -486,6 +487,7 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
return True
return False
@db_api.retry_if_session_inactive()
def remove_router_interface(self, context, router_id, interface_info):
router = self._get_router(context, router_id)
if not router.extra_attributes.distributed:
@ -968,6 +970,7 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
p['id'],
l3_port_check=False)
@db_api.retry_if_session_inactive()
def create_floatingip(self, context, floatingip,
initial_status=const.FLOATINGIP_STATUS_ACTIVE):
floating_ip = self._create_floatingip(
@ -1003,6 +1006,7 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
else:
self.notify_router_updated(context, router_id)
@db_api.retry_if_session_inactive()
def update_floatingip(self, context, id, floatingip):
old_floatingip, floatingip = self._update_floatingip(
context, id, floatingip)
@ -1012,6 +1016,7 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
self._notify_floating_ip_change(context, floatingip)
return floatingip
@db_api.retry_if_session_inactive()
def delete_floatingip(self, context, id):
floating_ip = self._delete_floatingip(context, id)
self._notify_floating_ip_change(context, floating_ip)

View File

@ -35,6 +35,7 @@ from neutron.api.v2 import attributes
from neutron.common import constants as n_const
from neutron.common import utils as n_utils
from neutron.db import agents_db
from neutron.db import api as db_api
from neutron.db.availability_zone import router as router_az_db
from neutron.db import common_db_mixin
from neutron.db import l3_db
@ -204,7 +205,10 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin,
return allocated_vr_ids
@db_api.retry_if_session_inactive()
def _allocate_vr_id(self, context, network_id, router_id):
# TODO(kevinbenton): let decorator handle duplicate retry
# like in review.openstack.org/#/c/367179/1/neutron/db/l3_hamode_db.py
for count in range(MAX_ALLOCATION_TRIES):
try:
# NOTE(kevinbenton): we disallow subtransactions because the
@ -235,6 +239,7 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin,
network_id=network_id, router_id=router_id,
max_tries=MAX_ALLOCATION_TRIES)
@db_api.retry_if_session_inactive()
def _delete_vr_id_allocation(self, context, ha_network, vr_id):
with context.session.begin(subtransactions=True):
context.session.query(L3HARouterVRIdAllocation).filter_by(
@ -460,6 +465,7 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin,
return n_utils.create_object_with_dependency(
creator, dep_getter, dep_creator, dep_id_attr, dep_deleter)
@db_api.retry_if_session_inactive()
def create_router(self, context, router):
is_ha = self._is_ha(router['router'])
router['router']['ha'] = is_ha
@ -492,6 +498,7 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin,
self.delete_router(context, router_dict['id'])
return router_dict
@db_api.retry_if_session_inactive()
def _update_router_db(self, context, router_id, data):
router_db = self._get_router(context, router_id)
@ -602,6 +609,7 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin,
"%(tenant)s."),
{'network': ha_network.network_id, 'tenant': tenant_id})
@db_api.retry_if_session_inactive()
def delete_router(self, context, id):
router_db = self._get_router(context, id)
super(L3_HA_NAT_db_mixin, self).delete_router(context, id)
@ -748,6 +756,7 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin,
# Take concurrently deleted routers in to account
pass
@db_api.retry_if_session_inactive()
def update_routers_states(self, context, states, host):
"""Receive dict of router ID to state and update them all."""
@ -758,7 +767,7 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin,
def _update_router_port_bindings(self, context, states, host):
admin_ctx = context.elevated()
device_filter = {'device_id': states.keys(),
device_filter = {'device_id': list(states.keys()),
'device_owner':
[constants.DEVICE_OWNER_HA_REPLICATED_INT,
constants.DEVICE_OWNER_ROUTER_SNAT]}

View File

@ -28,7 +28,7 @@ class MechanismDriverError(exceptions.MultipleExceptions):
# MultipleExceptions and return inner exceptions. Keep it
# for backward-compatibility, in case other code use it.
self.message = _("%s failed.") % method
super(MechanismDriverError, self).__init__(errors)
super(MechanismDriverError, self).__init__(errors or [])
class ExtensionDriverError(exceptions.InvalidInput):

View File

@ -772,6 +772,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
return result, mech_context
@utils.transaction_guard
@db_api.retry_if_session_inactive()
def create_network(self, context, network):
result, mech_context = self._create_network_db(context, network)
kwargs = {'context': context, 'network': result}
@ -787,11 +788,13 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
return result
@utils.transaction_guard
@db_api.retry_if_session_inactive()
def create_network_bulk(self, context, networks):
objects = self._create_bulk_ml2(attributes.NETWORK, context, networks)
return [obj['result'] for obj in objects]
@utils.transaction_guard
@db_api.retry_if_session_inactive()
def update_network(self, context, id, network):
net_data = network[attributes.NETWORK]
provider._raise_if_updates_provider_attributes(net_data)
@ -833,6 +836,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
self.notifier.network_update(context, updated_network)
return updated_network
@db_api.retry_if_session_inactive()
def get_network(self, context, id, fields=None):
session = context.session
with session.begin(subtransactions=True):
@ -842,6 +846,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
return self._fields(result, fields)
@db_api.retry_if_session_inactive()
def get_networks(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None, page_reverse=False):
session = context.session
@ -886,6 +891,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
_LE("Exception auto-deleting subnet %s"), subnet_id)
@utils.transaction_guard
@db_api.retry_if_session_inactive()
def delete_network(self, context, id):
# REVISIT(rkukura) The super(Ml2Plugin, self).delete_network()
# function is not used because it auto-deletes ports and
@ -993,6 +999,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
return result, mech_context
@utils.transaction_guard
@db_api.retry_if_session_inactive()
def create_subnet(self, context, subnet):
result, mech_context = self._create_subnet_db(context, subnet)
kwargs = {'context': context, 'subnet': result}
@ -1007,11 +1014,13 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
return result
@utils.transaction_guard
@db_api.retry_if_session_inactive()
def create_subnet_bulk(self, context, subnets):
objects = self._create_bulk_ml2(attributes.SUBNET, context, subnets)
return [obj['result'] for obj in objects]
@utils.transaction_guard
@db_api.retry_if_session_inactive()
def update_subnet(self, context, id, subnet):
session = context.session
with session.begin(subtransactions=True):
@ -1037,6 +1046,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
return updated_subnet
@utils.transaction_guard
@db_api.retry_if_session_inactive()
def delete_subnet(self, context, id):
# REVISIT(rkukura) The super(Ml2Plugin, self).delete_subnet()
# function is not used because it deallocates the subnet's addresses
@ -1246,6 +1256,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
return result, mech_context
@utils.transaction_guard
@db_api.retry_if_session_inactive()
def create_port(self, context, port):
result, mech_context = self._create_port_db(context, port)
# notify any plugin that is interested in port create events
@ -1282,6 +1293,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
return bound_context.current
@utils.transaction_guard
@db_api.retry_if_session_inactive()
def create_port_bulk(self, context, ports):
objects = self._create_bulk_ml2(attributes.PORT, context, ports)
@ -1352,6 +1364,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
raise psec.PortSecurityPortHasSecurityGroup()
@utils.transaction_guard
@db_api.retry_if_session_inactive()
def update_port(self, context, id, port):
attrs = port[attributes.PORT]
need_port_update_notify = False
@ -1489,6 +1502,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
binding.router_id = attrs and attrs.get('device_id')
@utils.transaction_guard
@db_api.retry_if_session_inactive()
def update_distributed_port_binding(self, context, id, port):
attrs = port[attributes.PORT]
@ -1546,6 +1560,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
raise exc.ServicePortInUse(port_id=port_id, reason=e)
@utils.transaction_guard
@db_api.retry_if_session_inactive()
def delete_port(self, context, id, l3_port_check=True):
self._pre_delete_port(context, id, l3_port_check)
# TODO(armax): get rid of the l3 dependency in the with block
@ -1616,6 +1631,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
self.notify_security_groups_member_updated(context, port)
@utils.transaction_guard
@db_api.retry_if_session_inactive(context_var_name='plugin_context')
def get_bound_port_context(self, plugin_context, port_id, host=None,
cached_networks=None):
session = plugin_context.session
@ -1668,7 +1684,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
return self._bind_port_if_needed(port_context)
@utils.transaction_guard
@db_api.retry_db_errors
@db_api.retry_if_session_inactive()
def update_port_status(self, context, port_id, status, host=None,
network=None):
"""
@ -1746,6 +1762,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
return port['id']
@db_api.retry_if_session_inactive()
def port_bound_to_host(self, context, port_id, host):
if not host:
return
@ -1765,6 +1782,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
port_host = db.get_port_binding_host(context.session, port_id)
return port if (port_host == host) else None
@db_api.retry_if_session_inactive()
def get_ports_from_devices(self, context, devices):
port_ids_to_devices = dict(
(self._device_to_port_id(context, device), device)

View File

@ -234,7 +234,7 @@ class L3_NAT_db_mixin(base.BaseTestCase):
mock.patch.object(l3_db.L3_NAT_db_mixin, 'notify_router_updated')\
as nru:
self.db.create_router(mock.ANY, router_input)
self.db.create_router(mock.Mock(), router_input)
self.assertTrue(crd.called)
if external_gateway_info:
self.assertTrue(urgi.called)