]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Make timestamps available in Stack/Resource objects
authorZane Bitter <zbitter@redhat.com>
Fri, 13 Jul 2012 20:46:19 +0000 (16:46 -0400)
committerZane Bitter <zbitter@redhat.com>
Fri, 13 Jul 2012 20:46:19 +0000 (16:46 -0400)
Provide the creation time and last-updated time as attributes of Stack and
Resource objects so that external code does not need to access the database
in order to retrieve them. Use a Descriptor class so that the latest values
are always fetched from the database.

Change-Id: Ic3fa173b1dc8f2e5dc676a9152e8928ed2290913
Signed-off-by: Zane Bitter <zbitter@redhat.com>
heat/engine/parser.py
heat/engine/resources.py
heat/tests/test_parser.py
heat/tests/test_resource.py

index fb46a242145ef9b89de0fddb103a5eb51fb5d1ae..c91792773e525374b4f8f60d0247732366464c66 100644 (file)
@@ -22,7 +22,7 @@ import logging
 from heat.common import exception
 from heat.engine import checkeddict
 from heat.engine import dependencies
-from heat.engine.resources import Resource
+from heat.engine import resources
 from heat.db import api as db_api
 
 
@@ -234,6 +234,9 @@ class Stack(object):
     DELETE_FAILED = 'DELETE_FAILED'
     DELETE_COMPLETE = 'DELETE_COMPLETE'
 
+    created_time = resources.Timestamp(db_api.stack_get, 'created_at')
+    updated_time = resources.Timestamp(db_api.stack_get, 'updated_at')
+
     def __init__(self, context, stack_name, template, parameters=None,
                  stack_id=None, state=None, state_description='',
                  timeout_mins=60):
@@ -257,7 +260,7 @@ class Stack(object):
         self.outputs = self.resolve_static_data(self.t[OUTPUTS])
 
         self.resources = dict((name,
-                               Resource(name, data, self))
+                               resources.Resource(name, data, self))
                               for (name, data) in self.t[RESOURCES].items())
 
         self.dependencies = self._get_dependencies(self.resources.itervalues())
index 40b8822291193b188f53062a9db916d47b5d3749..2d246939145c01eddb20227c1eba35063238b986 100644 (file)
@@ -64,6 +64,32 @@ class Metadata(object):
             return None
 
 
+class Timestamp(object):
+    '''
+    A descriptor for fetching an up-to-date timestamp from the database.
+    '''
+
+    def __init__(self, db_fetch, attribute):
+        '''
+        Initialise with a function to fetch the database representation of an
+        object (given a context and ID) and the name of the attribute to
+        retrieve.
+        '''
+        self.db_fetch = db_fetch
+        self.attribute = attribute
+
+    def __get__(self, obj, obj_class):
+        '''
+        Get the latest data from the database for the given object and class.
+        '''
+        if obj is None or obj.id is None:
+            return None
+
+        o = self.db_fetch(obj.context, obj.id)
+        o.refresh(attrs=[self.attribute])
+        return getattr(o, self.attribute)
+
+
 class Resource(object):
     CREATE_IN_PROGRESS = 'IN_PROGRESS'
     CREATE_FAILED = 'CREATE_FAILED'
@@ -78,6 +104,9 @@ class Resource(object):
     # If True, this resource must be created before it can be referenced.
     strict_dependency = True
 
+    created_time = Timestamp(db_api.resource_get, 'created_at')
+    updated_time = Timestamp(db_api.resource_get, 'updated_at')
+
     metadata = Metadata()
 
     def __new__(cls, name, json, stack):
index 8ad8ac3fe751ce7f19c46eb360ab72ab48e69fe2..d58ed45591e69e8d41bc31b59c45346379c2637b 100644 (file)
@@ -17,8 +17,9 @@ import nose
 import unittest
 from nose.plugins.attrib import attr
 import mox
-
 import json
+
+from heat.common import context
 from heat.common import exception
 from heat.engine import parser
 from heat.engine import checkeddict
@@ -318,6 +319,20 @@ class ParametersTest(unittest.TestCase):
 @attr(tag=['unit', 'parser', 'stack'])
 @attr(speed='fast')
 class StackTest(unittest.TestCase):
+    def setUp(self):
+        self.username = 'parser_stack_test_user'
+
+        self.m = mox.Mox()
+
+        self.ctx = context.get_admin_context()
+        self.m.StubOutWithMock(self.ctx, 'username')
+        self.ctx.username = self.username
+
+        self.m.ReplayAll()
+
+    def tearDown(self):
+        self.m.UnsetStubs()
+
     def test_state_defaults(self):
         stack = parser.Stack(None, 'test_stack', parser.Template({}))
         self.assertEqual(stack.state, None)
@@ -341,6 +356,23 @@ class StackTest(unittest.TestCase):
         self.assertRaises(exception.NotFound, parser.Stack.load,
                           None, -1)
 
+    def test_created_time(self):
+        stack = parser.Stack(self.ctx, 'creation_time_test',
+                             parser.Template({}))
+        self.assertEqual(stack.created_time, None)
+        stack.store()
+        self.assertNotEqual(stack.created_time, None)
+
+    def test_updated_time(self):
+        stack = parser.Stack(self.ctx, 'update_time_test',
+                             parser.Template({}))
+        self.assertEqual(stack.updated_time, None)
+        stack.store()
+        stored_time = stack.updated_time
+        stack.state_set(stack.IN_PROGRESS, 'testing')
+        self.assertNotEqual(stack.updated_time, None)
+        self.assertNotEqual(stack.updated_time, stored_time)
+
 # allows testing of the test directly, shown below
 if __name__ == '__main__':
     sys.argv.append(__file__)
index 915a2e1499a4939d05efbbddd09dd3a350f77ebd..875e975de4e82680c901ae3a9f53a19c6a8f5209 100644 (file)
@@ -28,11 +28,12 @@ from heat.engine import resources
 @attr(speed='fast')
 class ResourceTest(unittest.TestCase):
     def setUp(self):
-        self.stack = parser.Stack(None, 'test_stack', parser.Template({}))
+        self.stack = parser.Stack(None, 'test_stack', parser.Template({}),
+                                  stack_id=-1)
 
     def test_state_defaults(self):
         tmpl = {'Type': 'Foo'}
-        res = resources.GenericResource('test_resource', tmpl, self.stack)
+        res = resources.GenericResource('test_res_def', tmpl, self.stack)
         self.assertEqual(res.state, None)
         self.assertEqual(res.state_description, '')
 
@@ -48,6 +49,22 @@ class ResourceTest(unittest.TestCase):
         res.state_set('blarg', 'wibble')
         self.assertEqual(res.state_description, 'wibble')
 
+    def test_created_time(self):
+        tmpl = {'Type': 'Foo'}
+        res = resources.GenericResource('test_res_new', tmpl, self.stack)
+        self.assertEqual(res.created_time, None)
+        res._store()
+        self.assertNotEqual(res.created_time, None)
+
+    def test_updated_time(self):
+        tmpl = {'Type': 'Foo'}
+        res = resources.GenericResource('test_res_upd', tmpl, self.stack)
+        res._store()
+        stored_time = res.updated_time
+        res.state_set(res.CREATE_IN_PROGRESS, 'testing')
+        self.assertNotEqual(res.updated_time, None)
+        self.assertNotEqual(res.updated_time, stored_time)
+
     def test_parsed_template(self):
         tmpl = {
             'Type': 'Foo',