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/db/sqlalchemy/session.py b/heat/db/sqlalchemy/session.py index caa9fecaa5..dcdd6efbb1 100644 --- a/heat/db/sqlalchemy/session.py +++ b/heat/db/sqlalchemy/session.py @@ -27,30 +27,6 @@ _ENGINE = None _MAKER = None -class Error(Exception): - pass - - -class DBError(Error): - """Wraps an implementation specific exception.""" - def __init__(self, inner_exception=None): - self.inner_exception = inner_exception - super(DBError, self).__init__(str(inner_exception)) - - -def _wrap_db_error(f): - def _wrap(*args, **kwargs): - try: - return f(*args, **kwargs) - except UnicodeEncodeError: - raise InvalidUnicodeParameter() - except Exception, e: - logger.exception(_('DB exception wrapped.')) - raise DBError(e) - _wrap.func_name = f.func_name - return _wrap - - def get_session(autocommit=True, expire_on_commit=False): """Return a SQLAlchemy session.""" global _ENGINE, _MAKER @@ -58,10 +34,7 @@ def get_session(autocommit=True, expire_on_commit=False): if _MAKER is None or _ENGINE is None: _ENGINE = get_engine() _MAKER = get_maker(_ENGINE, autocommit, expire_on_commit) - session = _MAKER() - session.query = _wrap_db_error(session.query) - session.flush = _wrap_db_error(session.flush) - return session + return _MAKER() class SynchronousSwitchListener(sqlalchemy.interfaces.PoolListener): diff --git a/heat/engine/instance.py b/heat/engine/instance.py index f49d4a094c..39bff989ea 100644 --- a/heat/engine/instance.py +++ b/heat/engine/instance.py @@ -241,17 +241,20 @@ class Instance(Resource): res = Resource.validate(self) if res: return res + #check validity of key - if self.stack.parms['KeyName']: + try: + key_name = self.properties['KeyName'] + except ValueError: + return + else: keypairs = self.nova().keypairs.list() valid_key = False for k in keypairs: - if k.name == self.stack.parms['KeyName']: - valid_key = True - if not valid_key: - return {'Error': - 'Provided KeyName is not registered with nova'} - return None + if k.name == key_name: + return + return {'Error': + 'Provided KeyName is not registered with nova'} def handle_delete(self): try: diff --git a/heat/engine/manager.py b/heat/engine/manager.py index 87fd1948fd..2c9c2de86f 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 diff --git a/heat/tests/test_validate.py b/heat/tests/test_validate.py index 9455701771..f5172cb2d9 100644 --- a/heat/tests/test_validate.py +++ b/heat/tests/test_validate.py @@ -71,7 +71,7 @@ test_template_ref = ''' "Properties": { "ImageId": "image_name", "InstanceType": "m1.large", - "KeyName": "test_KeyName" + "KeyName": { "Ref" : "KeyName" } } }, "DataVolume" : { @@ -112,7 +112,7 @@ test_template_findinmap_valid = ''' "Properties": { "ImageId": "image_name", "InstanceType": "m1.large", - "KeyName": "test_KeyName" + "KeyName": { "Ref" : "KeyName" } } }, "DataVolume" : { @@ -176,7 +176,7 @@ test_template_findinmap_invalid = ''' '"InstanceType" }, "Arch" ] } ] },' + \ ''' "InstanceType": "m1.large", - "KeyName": "test_KeyName" + "KeyName": { "Ref" : "KeyName"} } }, "DataVolume" : {