Merge changes I05dcfd9a,If938b51a,Iebd2693b

* changes:
  Don't go fishing in the stack for the KeyName
  Tidy up create timeout code
  Get rid of _wrap_db_error()
This commit is contained in:
Jenkins 2012-06-28 22:00:45 +00:00 committed by Gerrit Code Review
commit 73492540dd
8 changed files with 39 additions and 62 deletions

View File

@ -176,7 +176,7 @@ def stack_create(options, arguments):
parameters['Parameters.member.%d.ParameterValue' % count] = v parameters['Parameters.member.%d.ParameterValue' % count] = v
count = count + 1 count = count + 1
parameters['Timeout'] = options.timeout parameters['TimeoutInMinutes'] = options.timeout
if options.template_file: if options.template_file:
parameters['TemplateBody'] = open(options.template_file).read() parameters['TemplateBody'] = open(options.template_file).read()

View File

@ -152,9 +152,6 @@ class StackController(object):
except ValueError: except ValueError:
msg = _("The Template must be a JSON document.") msg = _("The Template must be a JSON document.")
return webob.exc.HTTPBadRequest(explanation=msg) return webob.exc.HTTPBadRequest(explanation=msg)
stack['StackName'] = req.params['StackName']
if 'Timeout' in req.params:
stack['Timeout'] = req.params['Timeout']
try: try:
res = rpc.call(con, 'engine', res = rpc.call(con, 'engine',

View File

@ -16,6 +16,6 @@
SUPPORTED_PARAMS = ('StackName', 'TemplateBody', 'TemplateUrl', SUPPORTED_PARAMS = ('StackName', 'TemplateBody', 'TemplateUrl',
'NotificationARNs', 'Parameters', 'Version', 'NotificationARNs', 'Parameters', 'Version',
'SignatureVersion', 'Timestamp', 'AWSAccessKeyId', 'SignatureVersion', 'Timestamp', 'AWSAccessKeyId',
'Signature', 'KeyStoneCreds', 'Timeout', 'Signature', 'KeyStoneCreds', 'TimeoutInMinutes',
'LogicalResourceId', 'PhysicalResourceId', 'NextToken', 'LogicalResourceId', 'PhysicalResourceId', 'NextToken',
) )

View File

@ -27,30 +27,6 @@ _ENGINE = None
_MAKER = 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): def get_session(autocommit=True, expire_on_commit=False):
"""Return a SQLAlchemy session.""" """Return a SQLAlchemy session."""
global _ENGINE, _MAKER global _ENGINE, _MAKER
@ -58,10 +34,7 @@ def get_session(autocommit=True, expire_on_commit=False):
if _MAKER is None or _ENGINE is None: if _MAKER is None or _ENGINE is None:
_ENGINE = get_engine() _ENGINE = get_engine()
_MAKER = get_maker(_ENGINE, autocommit, expire_on_commit) _MAKER = get_maker(_ENGINE, autocommit, expire_on_commit)
session = _MAKER() return _MAKER()
session.query = _wrap_db_error(session.query)
session.flush = _wrap_db_error(session.flush)
return session
class SynchronousSwitchListener(sqlalchemy.interfaces.PoolListener): class SynchronousSwitchListener(sqlalchemy.interfaces.PoolListener):

View File

@ -241,17 +241,20 @@ class Instance(Resource):
res = Resource.validate(self) res = Resource.validate(self)
if res: if res:
return res return res
#check validity of key #check validity of key
if self.stack.parms['KeyName']: try:
key_name = self.properties['KeyName']
except ValueError:
return
else:
keypairs = self.nova().keypairs.list() keypairs = self.nova().keypairs.list()
valid_key = False valid_key = False
for k in keypairs: for k in keypairs:
if k.name == self.stack.parms['KeyName']: if k.name == key_name:
valid_key = True return
if not valid_key: return {'Error':
return {'Error': 'Provided KeyName is not registered with nova'}
'Provided KeyName is not registered with nova'}
return None
def handle_delete(self): def handle_delete(self):
try: try:

View File

@ -63,6 +63,18 @@ def _extract_user_params(params):
return dict(get_param_pairs()) 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): class EngineManager(manager.Manager):
""" """
Manages the running instances from creation to destruction. 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['LastUpdatedTimestamp'] = heat_utils.strtime(s.updated_at)
mem['NotificationARNs'] = 'TODO' mem['NotificationARNs'] = 'TODO'
mem['Parameters'] = ps.t['Parameters'] mem['Parameters'] = ps.t['Parameters']
mem['TimeoutInMinutes'] = ps.t.get('Timeout', '60')
mem['Description'] = ps.t.get('Description', mem['Description'] = ps.t.get('Description',
'No description') 'No description')
mem['StackStatus'] = s.status mem['StackStatus'] = s.status
mem['StackStatusReason'] = s.status_reason mem['StackStatusReason'] = s.status_reason
@ -201,7 +212,8 @@ class EngineManager(manager.Manager):
new_pt = db_api.parsed_template_create(None, pt) new_pt = db_api.parsed_template_create(None, pt)
stack.parsed_template_id = new_pt.id 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)])} return {'StackId': "/".join([new_s.name, str(new_s.id)])}

View File

@ -191,28 +191,20 @@ class Stack(object):
stack.update_and_save({'status': new_status, stack.update_and_save({'status': new_status,
'status_reason': reason}) 'status_reason': reason})
def _timeout(self): def create(self, timeout_in_minutes=60):
'''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):
''' '''
Create the stack and all of the resources. 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') self.state_set(self.IN_PROGRESS, 'Stack creation started')
stack_status = self.CREATE_COMPLETE stack_status = self.CREATE_COMPLETE
reason = 'Stack successfully created' reason = 'Stack successfully created'
res = None
with eventlet.Timeout(self._timeout()) as tmo: with eventlet.Timeout(timeout_in_minutes * 60) as tmo:
try: try:
for res in self: for res in self:
if stack_status != self.CREATE_FAILED: if stack_status != self.CREATE_FAILED:
@ -231,10 +223,10 @@ class Stack(object):
res.state_set(res.CREATE_FAILED, res.state_set(res.CREATE_FAILED,
'Stack creation aborted') 'Stack creation aborted')
except eventlet.Timeout, t: except eventlet.Timeout as t:
if t is tmo: if t is tmo:
stack_status = self.CREATE_FAILED stack_status = self.CREATE_FAILED
reason = 'Timed out waiting for %s' % (res.name) reason = 'Timed out waiting for %s' % str(res)
else: else:
# not my timeout # not my timeout
raise raise

View File

@ -71,7 +71,7 @@ test_template_ref = '''
"Properties": { "Properties": {
"ImageId": "image_name", "ImageId": "image_name",
"InstanceType": "m1.large", "InstanceType": "m1.large",
"KeyName": "test_KeyName" "KeyName": { "Ref" : "KeyName" }
} }
}, },
"DataVolume" : { "DataVolume" : {
@ -112,7 +112,7 @@ test_template_findinmap_valid = '''
"Properties": { "Properties": {
"ImageId": "image_name", "ImageId": "image_name",
"InstanceType": "m1.large", "InstanceType": "m1.large",
"KeyName": "test_KeyName" "KeyName": { "Ref" : "KeyName" }
} }
}, },
"DataVolume" : { "DataVolume" : {
@ -176,7 +176,7 @@ test_template_findinmap_invalid = '''
'"InstanceType" }, "Arch" ] } ] },' + \ '"InstanceType" }, "Arch" ] } ] },' + \
''' '''
"InstanceType": "m1.large", "InstanceType": "m1.large",
"KeyName": "test_KeyName" "KeyName": { "Ref" : "KeyName"}
} }
}, },
"DataVolume" : { "DataVolume" : {