]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Fix the wait condition's reading of the metadata.
authorAngus Salkeld <asalkeld@redhat.com>
Thu, 21 Jun 2012 10:10:53 +0000 (20:10 +1000)
committerAngus Salkeld <asalkeld@redhat.com>
Thu, 21 Jun 2012 10:10:53 +0000 (20:10 +1000)
the db was caching the object, so we need to 'expire'
it to make sure we are getting live data.

Change-Id: I1108daccc96f3dcfa33fda968ea30d83e03aad2d
Signed-off-by: Angus Salkeld <asalkeld@redhat.com>
heat/db/sqlalchemy/models.py
heat/engine/manager.py
heat/engine/wait_condition.py
heat/tests/test_waitcondition.py [new file with mode: 0644]

index 9d477815a4a1f55eb688d9d9cb99a823d879be07..24285526c44a77df3b3fc61439994eb39e21f486 100644 (file)
@@ -61,6 +61,22 @@ class HeatBase(object):
             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
index be8b64654de0c3bbdf066fd6dc40adaca26c4fe9..0fee2e77ef8e6a8f4234655f4772601e7944d1f5 100644 (file)
@@ -492,6 +492,7 @@ class EngineManager(manager.Manager):
         """
         s = db_api.stack_get_by_name(None, stack_name)
         if not s:
+            logger.warn("Stack not found %s." % (stack_name))
             return ['stack', None]
 
         r = db_api.resource_get_by_name_and_stack(None, resource_id, s.id)
index f43f5674d70830b9d2d335bffdfe37619d1bab5d..894cb0d8d9ac6304a6d2bf1317f950f7eea30f2e 100644 (file)
@@ -78,6 +78,7 @@ class WaitCondition(Resource):
         status = 'WAITING'
         reason = ''
         res = None
+        sleep_time = 1
         try:
             while status == 'WAITING':
                 try:
@@ -85,21 +86,28 @@ class WaitCondition(Resource):
                                                                 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
diff --git a/heat/tests/test_waitcondition.py b/heat/tests/test_waitcondition.py
new file mode 100644 (file)
index 0000000..34ab525
--- /dev/null
@@ -0,0 +1,108 @@
+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()