From 03a5707849de32141f89aebb34b464a19e9db246 Mon Sep 17 00:00:00 2001 From: Zane Bitter Date: Fri, 31 May 2013 12:39:08 +0200 Subject: [PATCH] Create stacks with a co-routine This will allow nested stacks to be created in parallel with other stack resources in the future. Change-Id: If1817bddcea50fdd7b640dee5b5d12257aada651 --- heat/engine/parser.py | 29 +++++++++++++++-------------- heat/tests/test_parser.py | 26 ++++++++++++++++++++++++++ heat/tests/test_waitcondition.py | 4 ++++ 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/heat/engine/parser.py b/heat/engine/parser.py index ef5c00b7..d0dabaff 100644 --- a/heat/engine/parser.py +++ b/heat/engine/parser.py @@ -277,9 +277,14 @@ class Stack(object): def create(self): ''' Create the stack and all of the resources. + ''' + creator = scheduler.TaskRunner(self.create_task) + creator(timeout=self.timeout_secs()) - Creation will fail if it exceeds the specified timeout. The default is - 60 minutes, set in the constructor + @scheduler.wrappertask + def create_task(self): + ''' + A task to create the stack and all of the resources. ''' self.state_set(self.CREATE_IN_PROGRESS, 'Stack creation started') @@ -292,19 +297,15 @@ class Stack(object): create_task = scheduler.DependencyTaskGroup(self.dependencies, resource_create) - create = scheduler.TaskRunner(create_task) - with eventlet.Timeout(self.timeout_secs()) as tmo: - try: - create() - except exception.ResourceFailure as ex: - stack_status = self.CREATE_FAILED - reason = 'Resource failed: %s' % str(ex) - except eventlet.Timeout as t: - if t is not tmo: # not my timeout - raise - stack_status = self.CREATE_FAILED - reason = 'Timed out' + try: + yield create_task() + except exception.ResourceFailure as ex: + stack_status = self.CREATE_FAILED + reason = 'Resource failed: %s' % str(ex) + except scheduler.Timeout: + stack_status = self.CREATE_FAILED + reason = 'Timed out' self.state_set(stack_status, reason) diff --git a/heat/tests/test_parser.py b/heat/tests/test_parser.py index 7aebc302..5baa4c0f 100644 --- a/heat/tests/test_parser.py +++ b/heat/tests/test_parser.py @@ -14,6 +14,7 @@ import mox +import time import uuid from heat.common import context @@ -1077,6 +1078,31 @@ class StackTest(HeatTestCase): self.m.VerifyAll() + def test_stack_create_timeout(self): + self.m.StubOutWithMock(scheduler.DependencyTaskGroup, '__call__') + self.m.StubOutWithMock(scheduler, 'wallclock') + + stack = parser.Stack(None, 's', parser.Template({})) + + def dummy_task(): + while True: + yield + + start_time = time.time() + scheduler.wallclock().AndReturn(start_time) + scheduler.wallclock().AndReturn(start_time + 1) + scheduler.DependencyTaskGroup.__call__().AndReturn(dummy_task()) + scheduler.wallclock().AndReturn(start_time + stack.timeout_secs() + 1) + + self.m.ReplayAll() + + stack.create() + + self.assertEqual(stack.state, stack.CREATE_FAILED) + self.assertEqual(stack.state_description, 'Timed out') + + self.m.VerifyAll() + def test_stack_name_valid(self): stack = parser.Stack(None, 's', parser.Template({})) stack = parser.Stack(None, 'stack123', parser.Template({})) diff --git a/heat/tests/test_waitcondition.py b/heat/tests/test_waitcondition.py index 13a4533b..e8ea8356 100644 --- a/heat/tests/test_waitcondition.py +++ b/heat/tests/test_waitcondition.py @@ -221,6 +221,10 @@ class WaitConditionTest(HeatTestCase): self.stack = self.create_stack() + # Avoid the stack create exercising the timeout code at the same time + self.m.StubOutWithMock(self.stack, 'timeout_secs') + self.stack.timeout_secs().AndReturn(None) + self.m.StubOutWithMock(scheduler, 'wallclock') scheduler.wallclock().AndReturn(st) -- 2.45.2