summaryrefslogtreecommitdiff
path: root/neutron/db/provisioning_blocks.py
diff options
context:
space:
mode:
authorKevin Benton <kevin@benton.pub>2016-09-07 17:11:06 -0700
committerKevin Benton <kevin@benton.pub>2016-09-08 13:00:07 +0000
commit7b4350a4cb6da34b92deb578a0af837bcf14e023 (patch)
tree779b7a0ef7cfbe1268e2ef8a7b403797b8c183c5 /neutron/db/provisioning_blocks.py
parentdc6508aae2819f2b718785b4da2c11f30bdc3ffd (diff)
downloadneutron-7b4350a4cb6da34b92deb578a0af837bcf14e023.tar.gz
Don't use nested transaction in provisioning blocks
Relying on duplicate entries for existing provisioning block detection led to lots of log noise whenever we would encounter a deadlock because the savepoint would go missing. Additionally, since this would happen inside of another transaction, we couldn't be guaranteed until the final commit that this was unique anyway so the whole transaction could throw a duplicate exception. Since the outer transaction has to handle duplicate exceptions anyway, this patch just adjusts the logic to check for the existing of a record first with a regular query. If there is a race the outer transaction will still fail with a duplicate as before, but we at least won't have a bunch of missing savepoint exception noise. Closes-Bug: #1613759 Change-Id: I02d30427505591e24d7bdc1ba654d3757ab9a33d
Diffstat (limited to 'neutron/db/provisioning_blocks.py')
-rw-r--r--neutron/db/provisioning_blocks.py17
1 files changed, 8 insertions, 9 deletions
diff --git a/neutron/db/provisioning_blocks.py b/neutron/db/provisioning_blocks.py
index 4c57bc7b17..1cc02f30b2 100644
--- a/neutron/db/provisioning_blocks.py
+++ b/neutron/db/provisioning_blocks.py
@@ -14,14 +14,12 @@
#
from neutron_lib.db import model_base
-from oslo_db import exception as db_exc
from oslo_log import log as logging
import sqlalchemy as sa
from neutron._i18n import _LE
from neutron.callbacks import registry
from neutron.callbacks import resources
-from neutron.db import api as db_api
from neutron.db import models_v2
from neutron.db import standard_attr
@@ -56,7 +54,7 @@ def add_provisioning_component(context, object_id, object_type, entity):
of the entity that is doing the provisioning. While an object has these
provisioning blocks present, this module will not emit any callback events
indicating that provisioning has completed. Any logic that depends on
- multiple disjoint components use these blocks and subscribe to the
+ multiple disjoint components may use these blocks and subscribe to the
PROVISIONING_COMPLETE event to know when all components have completed.
:param context: neutron api request context
@@ -69,17 +67,18 @@ def add_provisioning_component(context, object_id, object_type, entity):
standard_attr_id = _get_standard_attr_id(context, object_id, object_type)
if not standard_attr_id:
return
- try:
- with db_api.autonested_transaction(context.session):
- record = ProvisioningBlock(standard_attr_id=standard_attr_id,
- entity=entity)
- context.session.add(record)
- except db_exc.DBDuplicateEntry:
+ record = context.session.query(ProvisioningBlock).filter_by(
+ standard_attr_id=standard_attr_id, entity=entity).first()
+ if record:
# an entry could be leftover from a previous transition that hasn't
# yet been provisioned. (e.g. multiple updates in a short period)
LOG.debug("Ignored duplicate provisioning block setup for %(otype)s "
"%(oid)s by entity %(entity)s.", log_dict)
return
+ with context.session.begin(subtransactions=True):
+ record = ProvisioningBlock(standard_attr_id=standard_attr_id,
+ entity=entity)
+ context.session.add(record)
LOG.debug("Transition to ACTIVE for %(otype)s object %(oid)s "
"will not be triggered until provisioned by entity %(entity)s.",
log_dict)