else:
raise
+ def expire(self, session=None):
+ """Expire this object ()."""
+ if not session:
+ session = Session.object_session(self)
+ if not session:
+ session = get_session()
+ session.expire(self)
+
+ def refresh(self, session=None):
+ """Refresh this object."""
+ if not session:
+ session = Session.object_session(self)
+ if not session:
+ session = get_session()
+ session.refresh(self)
+
def delete(self, session=None):
"""Delete this object."""
self.deleted = True
status = 'WAITING'
reason = ''
res = None
+ sleep_time = 1
try:
while status == 'WAITING':
try:
res_name,
self.stack.id)
except Exception as ex:
+ logger.exception('resource %s not found' % res_name)
if 'not found' in ex:
# it has been deleted
status = 'DELETED'
else:
pass
- if res and res.rsrc_metadata:
- metadata = res.rsrc_metadata
- if metadata:
- status = metadata.get('Status', 'WAITING')
- reason = metadata.get('Reason', 'Reason not provided')
- logger.debug('got %s' % json.dumps(metadata))
+ if res:
+ if res.rsrc_metadata:
+ meta = res.rsrc_metadata
+ status = meta.get('Status',
+ 'WAITING')
+ reason = meta.get('Reason',
+ 'Reason not provided')
+ logger.debug('got %s' % json.dumps(res.rsrc_metadata))
if status == 'WAITING':
logger.debug('Waiting some more for the Metadata[Status]')
- eventlet.sleep(30)
+ eventlet.sleep(sleep_time)
+ sleep_time = min(sleep_time * 2, self.timeout / 4)
+ if res:
+ res.expire()
+
except eventlet.Timeout, t:
if t is not tmo:
# not my timeout
--- /dev/null
+from datetime import datetime
+import eventlet
+import json
+import logging
+import os
+import sys
+
+import nose
+import unittest
+import mox
+from nose.plugins.attrib import attr
+from nose import with_setup
+
+import heat.db as db_api
+from heat.engine import parser
+
+logger = logging.getLogger('test_waitcondition')
+
+test_template_waitcondition = '''
+{
+ "AWSTemplateFormatVersion" : "2010-09-09",
+ "Description" : "Just a WaitCondition.",
+ "Parameters" : {},
+ "Resources" : {
+ "WaitHandle" : {
+ "Type" : "AWS::CloudFormation::WaitConditionHandle"
+ },
+ "WaitForTheHandle" : {
+ "Type" : "AWS::CloudFormation::WaitCondition",
+ "Properties" : {
+ "Handle" : {"Ref" : "WaitHandle"},
+ "Timeout" : "5"
+ }
+ }
+ }
+}
+'''
+
+
+@attr(tag=['unit', 'resource'])
+@attr(speed='slow')
+class stacksTest(unittest.TestCase):
+ def setUp(self):
+ self.m = mox.Mox()
+ self.greenpool = eventlet.GreenPool()
+
+ def tearDown(self):
+ self.m.UnsetStubs()
+
+ def create_stack(self, stack_name, temp, params):
+ stack = parser.Stack(None, stack_name, temp, 0, params)
+
+ rt = {}
+ rt['template'] = temp
+ rt['StackName'] = stack_name
+ new_rt = db_api.raw_template_create(None, rt)
+
+ ct = {'username': 'fred',
+ 'password': 'mentions_fruit'}
+ new_creds = db_api.user_creds_create(ct)
+
+ s = {}
+ s['name'] = stack_name
+ s['raw_template_id'] = new_rt.id
+ s['user_creds_id'] = new_creds.id
+ s['username'] = ct['username']
+ new_s = db_api.stack_create(None, s)
+ stack.id = new_s.id
+ pt = {}
+ pt['template'] = stack.t
+ pt['raw_template_id'] = new_rt.id
+ new_pt = db_api.parsed_template_create(None, pt)
+
+ stack.parsed_template_id = new_pt.id
+ return stack
+
+ def test_post_success_to_handle(self):
+ params = {}
+ t = json.loads(test_template_waitcondition)
+ stack = self.create_stack('test_stack', t, params)
+
+ self.m.ReplayAll()
+ self.greenpool.spawn_n(stack.create)
+ eventlet.sleep(1)
+ assert(stack.resources['WaitForTheHandle'].state == 'IN_PROGRESS')
+
+ r = db_api.resource_get_by_name_and_stack(None, 'WaitHandle',
+ stack.id)
+ assert(r.name == 'WaitHandle')
+
+ metadata = {"Status": "SUCCESS",
+ "Reason": "woot toot",
+ "Data": "Application has completed configuration.",
+ "UniqueId": "00000"}
+
+ r.update_and_save({'rsrc_metadata': metadata})
+
+ eventlet.sleep(2)
+
+ logger.debug('state %s' % stack.resources['WaitForTheHandle'].state)
+ assert(stack.resources['WaitForTheHandle'].state == 'CREATE_COMPLETE')
+
+ self.greenpool.waitall()
+
+ # allows testing of the test directly
+ if __name__ == '__main__':
+ sys.argv.append(__file__)
+ nose.main()