]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Fix race condition in list_stacks
authorSteve Baker <sbaker@redhat.com>
Mon, 10 Dec 2012 03:18:26 +0000 (16:18 +1300)
committerSteve Baker <sbaker@redhat.com>
Tue, 11 Dec 2012 20:42:59 +0000 (09:42 +1300)
A stack may be deleted between querying the stacks to list and formatting
each stack.

This issue was found by concurrently creating and deleting 100 stacks
while running heat list.

Change-Id: I4a47bbdbde111454672c2579caf28b4675c3cf10

heat/engine/service.py

index cf317fca3388dfdf1d37dbb78c15296e19aff708..11efff66a497ba799a921556746d51bdb76bae64 100644 (file)
 
 import functools
 import webob
+import sqlalchemy.exc
 
 from heat.common import context
 from heat.db import api as db_api
 from heat.engine import api
 from heat.engine.event import Event
+from heat.common import exception
 from heat.common import identifier
 from heat.engine import parser
 from heat.engine import resources
@@ -161,13 +163,21 @@ class EngineService(service.Service):
         The list_stacks method returns attributes of all stacks.
         arg1 -> RPC context.
         """
-        stacks = db_api.stack_get_all_by_tenant(context) or []
 
-        def format_stack_detail(s):
-            stack = parser.Stack.load(context, stack=s, resolve_data=False)
-            return api.format_stack(stack)
+        def format_stack_details(stacks):
+            for s in stacks:
+                try:
+                    stack = parser.Stack.load(context, stack=s,
+                        resolve_data=False)
+                except exception.NotFound:
+                    # The stack may have been deleted between listing
+                    # and formatting
+                    pass
+                else:
+                    yield api.format_stack(stack)
 
-        return {'stacks': [format_stack_detail(s) for s in stacks]}
+        stacks = db_api.stack_get_all_by_tenant(context) or []
+        return {'stacks': list(format_stack_details(stacks))}
 
     @request_context
     def create_stack(self, context, stack_name, template, params, args):