]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
heat engine : Store stack timeout in database
authorSteven Hardy <shardy@redhat.com>
Thu, 12 Jul 2012 11:56:44 +0000 (12:56 +0100)
committerSteven Hardy <shardy@redhat.com>
Thu, 12 Jul 2012 13:03:12 +0000 (14:03 +0100)
Store the TimeoutInMinutes common query parameter
value in the DB so it can be returned correctly
with show_stack/DescribeStacks
ref #125

Change-Id: I4ccc79b586087f61e415d5d2c24b7bd52844399a
Signed-off-by: Steven Hardy <shardy@redhat.com>
heat/db/sqlalchemy/migrate_repo/versions/010_add_stack_timeout_col.py [new file with mode: 0644]
heat/db/sqlalchemy/models.py
heat/engine/api.py
heat/engine/manager.py
heat/engine/parser.py
heat/tests/test_engine_api_utils.py

diff --git a/heat/db/sqlalchemy/migrate_repo/versions/010_add_stack_timeout_col.py b/heat/db/sqlalchemy/migrate_repo/versions/010_add_stack_timeout_col.py
new file mode 100644 (file)
index 0000000..49b97ff
--- /dev/null
@@ -0,0 +1,25 @@
+from sqlalchemy import *
+from migrate import *
+
+
+def upgrade(migrate_engine):
+    meta = MetaData(bind=migrate_engine)
+    stack = Table('stack', meta, autoload=True)
+
+    # Note hard-coded default 60 (minutes) here from the value in the
+    # engine, means we can upgrade and populate existing rows
+    try:
+        col = Column('timeout', Integer, nullable=False, default=60)
+        col.create(stack, populate_default=True)
+    except Exception as ex:
+        print "Caught exception adding timeout column to stacks %s" % ex
+        # *Hack-alert* Sqlite in the unit tests can't handle the above
+        # approach to nullable=False, so retry with nullable=True
+        Column('timeout', Integer, nullable=True, default=60).create(stack)
+
+
+def downgrade(migrate_engine):
+    meta = MetaData(bind=migrate_engine)
+    stack = Table('stack', meta, autoload=True)
+
+    stack.c.timeout.drop()
index 625ee7fd3e763ea609fb9f1ed011235ec7d44be9..c92bf13117636b67f1943f9f66c767bd8f9e39a3 100644 (file)
@@ -152,6 +152,7 @@ class Stack(BASE, HeatBase):
     user_creds_id = Column(Integer, ForeignKey('user_creds.id'),
                            nullable=False)
     owner_id = Column(Integer, nullable=True)
+    timeout = Column(Integer)
 
 
 class UserCreds(BASE, HeatBase):
index d11c405c13d452aca291a80c6c142b7a4a960296..982988d12be6402fd15582e9ef5dafd47c7549c3 100644 (file)
@@ -71,7 +71,7 @@ def extract_args(params):
         logger.exception('create timeout conversion')
     else:
         if timeout_mins > 0:
-            kwargs['timeout_in_minutes'] = timeout_mins
+            kwargs['timeout_mins'] = timeout_mins
     return kwargs
 
 
@@ -162,6 +162,7 @@ def format_stack(stack, keys=None):
         STACK_TMPL_DESCRIPTION: stack.t[parser.DESCRIPTION],
         STACK_STATUS: s.status,
         STACK_STATUS_DATA: s.status_reason,
+        STACK_TIMEOUT: stack.timeout_mins,
     }
 
     # only show the outputs on a completely created stack
index 247ccb1e3867e098b5ed3368fbf498dee743fd9e..6ee9df5ec190c68e3308c41406d8bf4e67755083 100644 (file)
@@ -122,16 +122,19 @@ class EngineManager(manager.Manager):
             return {'Error': 'Stack already exists with that name.'}
 
         tmpl = parser.Template(template)
-        user_params = parser.Parameters(stack_name, tmpl,
-                                        api.extract_user_params(params))
-        stack = parser.Stack(context, stack_name, tmpl, user_params)
+        # Extract the template parameters, and any common query parameters
+        template_params = parser.Parameters(stack_name, tmpl,
+                                            api.extract_user_params(params))
+        common_params = api.extract_args(params)
+        stack = parser.Stack(context, stack_name, tmpl, template_params,
+                             **common_params)
 
         response = stack.validate()
         if response['Description'] != 'Successfully validated':
             return response
 
         stack_id = stack.store()
-        greenpool.spawn_n(stack.create, **api.extract_args(params))
+        greenpool.spawn_n(stack.create)
 
         return {'StackId': stack.stack_id()}
 
index e3c02e16cbac8573b3e77d180ac6a01771cf039e..1c0cc8b529f2f97a1c23d550a4c0392bf566727a 100644 (file)
@@ -235,7 +235,8 @@ class Stack(object):
     DELETE_COMPLETE = 'DELETE_COMPLETE'
 
     def __init__(self, context, stack_name, template, parameters=None,
-                 stack_id=None, state=None, state_description=''):
+                 stack_id=None, state=None, state_description='',
+                 timeout_mins=60):
         '''
         Initialise from a context, name, Template object and (optionally)
         Parameters object. The database ID may also be initialised, if the
@@ -247,6 +248,7 @@ class Stack(object):
         self.name = stack_name
         self.state = state
         self.state_description = state_description
+        self.timeout_mins = timeout_mins
 
         if parameters is None:
             parameters = Parameters(stack_name, template)
@@ -280,7 +282,7 @@ class Stack(object):
         template = Template.load(context, s.raw_template_id)
         params = Parameters(s.name, template, s.parameters)
         stack = cls(context, s.name, template, params,
-                    stack_id, s.status, s.status_reason)
+                    stack_id, s.status, s.status_reason, s.timeout)
 
         return stack
 
@@ -298,6 +300,7 @@ class Stack(object):
                 'username': self.context.username,
                 'status': self.state,
                 'status_reason': self.state_description,
+                'timeout': self.timeout_mins,
             }
             new_s = db_api.stack_create(self.context, s)
             self.id = new_s.id
@@ -388,12 +391,12 @@ class Stack(object):
         stack.update_and_save({'status': new_status,
                                'status_reason': reason})
 
-    def create(self, timeout_in_minutes=60):
+    def create(self):
         '''
         Create the stack and all of the resources.
 
         Creation will fail if it exceeds the specified timeout. The default is
-        60 minutes.
+        60 minutes, set in the constructor
         '''
         self.state_set(self.IN_PROGRESS, 'Stack creation started')
 
@@ -401,7 +404,7 @@ class Stack(object):
         reason = 'Stack successfully created'
         res = None
 
-        with eventlet.Timeout(timeout_in_minutes * 60) as tmo:
+        with eventlet.Timeout(self.timeout_mins * 60) as tmo:
             try:
                 for res in self:
                     if stack_status != self.CREATE_FAILED:
index 453af34ac4c0d35f490aacd38c64285b72807c98..9dc589cbf80d11311bc4c0a3a6dfb3e24028718f 100644 (file)
@@ -72,23 +72,23 @@ class EngineApiTest(unittest.TestCase):
     def test_timeout_extract(self):
         p = {'TimeoutInMinutes': '5'}
         args = api.extract_args(p)
-        self.assertEqual(args['timeout_in_minutes'], 5)
+        self.assertEqual(args['timeout_mins'], 5)
 
     def test_timeout_extract_zero(self):
         p = {'TimeoutInMinutes': '0'}
         args = api.extract_args(p)
-        self.assertTrue('timeout_in_minutes' not in args)
+        self.assertTrue('timeout_mins' not in args)
 
     def test_timeout_extract_garbage(self):
         p = {'TimeoutInMinutes': 'wibble'}
         args = api.extract_args(p)
-        self.assertTrue('timeout_in_minutes' not in args)
+        self.assertTrue('timeout_mins' not in args)
 
     def test_timeout_extract_none(self):
         p = {'TimeoutInMinutes': None}
         args = api.extract_args(p)
-        self.assertTrue('timeout_in_minutes' not in args)
+        self.assertTrue('timeout_mins' not in args)
 
     def test_timeout_extract_not_present(self):
         args = api.extract_args({})
-        self.assertTrue('timeout_in_minutes' not in args)
+        self.assertTrue('timeout_mins' not in args)