diff --git a/bin/heat b/bin/heat index 1037686479..48e8c19b50 100755 --- a/bin/heat +++ b/bin/heat @@ -176,7 +176,7 @@ def stack_create(options, arguments): parameters['Parameters.member.%d.ParameterValue' % count] = v count = count + 1 - parameters['Timeout'] = options.timeout + parameters['TimeoutInMinutes'] = options.timeout if options.template_file: parameters['TemplateBody'] = open(options.template_file).read() diff --git a/heat/api/v1/stacks.py b/heat/api/v1/stacks.py index f0c4342f01..eed301b7cd 100644 --- a/heat/api/v1/stacks.py +++ b/heat/api/v1/stacks.py @@ -152,9 +152,6 @@ class StackController(object): except ValueError: msg = _("The Template must be a JSON document.") return webob.exc.HTTPBadRequest(explanation=msg) - stack['StackName'] = req.params['StackName'] - if 'Timeout' in req.params: - stack['Timeout'] = req.params['Timeout'] try: res = rpc.call(con, 'engine', diff --git a/heat/cloudformations.py b/heat/cloudformations.py index 5ad1fb3a99..648770d687 100644 --- a/heat/cloudformations.py +++ b/heat/cloudformations.py @@ -16,6 +16,6 @@ SUPPORTED_PARAMS = ('StackName', 'TemplateBody', 'TemplateUrl', 'NotificationARNs', 'Parameters', 'Version', 'SignatureVersion', 'Timestamp', 'AWSAccessKeyId', - 'Signature', 'KeyStoneCreds', 'Timeout', + 'Signature', 'KeyStoneCreds', 'TimeoutInMinutes', 'LogicalResourceId', 'PhysicalResourceId', 'NextToken', ) diff --git a/heat/engine/manager.py b/heat/engine/manager.py index 11b98973bc..94e82585ad 100644 --- a/heat/engine/manager.py +++ b/heat/engine/manager.py @@ -63,6 +63,18 @@ def _extract_user_params(params): return dict(get_param_pairs()) +def _extract_args(params): + kwargs = {} + try: + timeout_mins = int(params.get('TimeoutInMinutes', 0)) + except ValueError: + logger.exception('create timeout conversion') + else: + if timeout > 0: + kwargs['timeout_in_minutes'] = timeout_mins + return kwargs + + class EngineManager(manager.Manager): """ Manages the running instances from creation to destruction. @@ -129,9 +141,8 @@ class EngineManager(manager.Manager): mem['LastUpdatedTimestamp'] = heat_utils.strtime(s.updated_at) mem['NotificationARNs'] = 'TODO' mem['Parameters'] = ps.t['Parameters'] - mem['TimeoutInMinutes'] = ps.t.get('Timeout', '60') mem['Description'] = ps.t.get('Description', - 'No description') + 'No description') mem['StackStatus'] = s.status mem['StackStatusReason'] = s.status_reason @@ -201,7 +212,8 @@ class EngineManager(manager.Manager): new_pt = db_api.parsed_template_create(None, pt) stack.parsed_template_id = new_pt.id - greenpool.spawn_n(stack.create) + + greenpool.spawn_n(stack.create, **_extract_args(params)) return {'StackId': "/".join([new_s.name, str(new_s.id)])} diff --git a/heat/engine/parser.py b/heat/engine/parser.py index 5373266a71..8e77735e41 100644 --- a/heat/engine/parser.py +++ b/heat/engine/parser.py @@ -191,28 +191,20 @@ class Stack(object): stack.update_and_save({'status': new_status, 'status_reason': reason}) - def _timeout(self): - '''Return the stack creation timeout in seconds''' - if 'Timeout' in self.t: - try: - # Timeout is in minutes - return int(self.t['Timeout']) * 60 - except ValueError: - logger.exception('create timeout conversion') - - # Default to 1 hour - return 60 * 60 - - def create(self): + def create(self, timeout_in_minutes=60): ''' Create the stack and all of the resources. + + Creation will fail if it exceeds the specified timeout. The default is + 60 minutes. ''' self.state_set(self.IN_PROGRESS, 'Stack creation started') stack_status = self.CREATE_COMPLETE reason = 'Stack successfully created' + res = None - with eventlet.Timeout(self._timeout()) as tmo: + with eventlet.Timeout(timeout_in_minutes * 60) as tmo: try: for res in self: if stack_status != self.CREATE_FAILED: @@ -231,10 +223,10 @@ class Stack(object): res.state_set(res.CREATE_FAILED, 'Stack creation aborted') - except eventlet.Timeout, t: + except eventlet.Timeout as t: if t is tmo: stack_status = self.CREATE_FAILED - reason = 'Timed out waiting for %s' % (res.name) + reason = 'Timed out waiting for %s' % str(res) else: # not my timeout raise