summaryrefslogtreecommitdiff
path: root/nova/context.py
diff options
context:
space:
mode:
authormelanie witt <melwittt@gmail.com>2017-10-09 20:36:59 +0000
committermelanie witt <melwittt@gmail.com>2017-10-11 15:41:03 +0000
commit3cc3cc453dc16e22365bea597c1be5bb0be57aeb (patch)
tree704c7adbf192a0d722c3094ea9440e4695a198fe /nova/context.py
parentc3ca8a6256f9b5f3235b65d483099047d50adc6f (diff)
downloadnova-3cc3cc453dc16e22365bea597c1be5bb0be57aeb.tar.gz
Fix target_cell usage for scatter_gather_cells
In the set_target_cell method, we synchronize access to the cached cell database transaction context manager objects to prevent more than one thread from using a cell's transaction context manager at the same time. In scatter_gather_cells, we're calling target_cell in such a way that the lock is acquired and released BEFORE the green thread actually accesses the database in the spawned function. So multiple threads can access a cell's database transaction context manager and it's possible for a database transaction to fail with the error: TypeError: Can't upgrade a READER transaction to a WRITER mid-transaction because the in-scope transaction context might be in the middle of a read when a concurrent green thread tries to do a write. Closes-Bug: #1722404 Change-Id: I07dd4d5aebdc82e343ec2035dc94c744e4754c96
Diffstat (limited to 'nova/context.py')
-rw-r--r--nova/context.py13
1 files changed, 7 insertions, 6 deletions
diff --git a/nova/context.py b/nova/context.py
index 03cb953790..28e838d9ce 100644
--- a/nova/context.py
+++ b/nova/context.py
@@ -419,9 +419,11 @@ def scatter_gather_cells(context, cell_mappings, timeout, fn, *args, **kwargs):
queue = eventlet.queue.LightQueue()
results = {}
- def gather_result(cell_uuid, fn, *args, **kwargs):
+ def gather_result(cell_mapping, fn, context, *args, **kwargs):
+ cell_uuid = cell_mapping.uuid
try:
- result = fn(*args, **kwargs)
+ with target_cell(context, cell_mapping) as cctxt:
+ result = fn(cctxt, *args, **kwargs)
except Exception:
LOG.exception('Error gathering result from cell %s', cell_uuid)
result = raised_exception_sentinel
@@ -429,10 +431,9 @@ def scatter_gather_cells(context, cell_mappings, timeout, fn, *args, **kwargs):
queue.put((cell_uuid, result))
for cell_mapping in cell_mappings:
- with target_cell(context, cell_mapping) as cctxt:
- greenthreads.append((cell_mapping.uuid,
- utils.spawn(gather_result, cell_mapping.uuid,
- fn, cctxt, *args, **kwargs)))
+ greenthreads.append((cell_mapping.uuid,
+ utils.spawn(gather_result, cell_mapping,
+ fn, context, *args, **kwargs)))
with eventlet.timeout.Timeout(timeout, exception.CellTimeout):
try: