]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
cleanup watchrule delete logic/tests
authorSteven Hardy <shardy@redhat.com>
Thu, 4 Jul 2013 09:26:31 +0000 (10:26 +0100)
committerSteven Hardy <shardy@redhat.com>
Thu, 4 Jul 2013 15:30:30 +0000 (16:30 +0100)
Rework watchrule delete interface so we delete by ID, rather than
by name (where we only delete the first rule in the event of multiple
watcherule rows with the same name, which is allowed although not likely
in normal heat operation - it can cause weird behavior in the tests)

Encapsulating the delete in a WatchRule.destroy() is cleaner and more
consistent with the rest of the codebase, and reworking the tests to
ensure proper cleanup reduces the chances of odd errors and cascading
failures between tests on failure.

fixes bug #1197718

Change-Id: I94e9eb610519bb7321a2be7718312fd50f308a8b

heat/db/api.py
heat/db/sqlalchemy/api.py
heat/engine/resources/cloud_watch.py
heat/engine/watchrule.py
heat/tests/test_engine_service.py
heat/tests/test_watch.py
heat/tests/utils.py

index 3835c14631bf5744159397bda6580924bac6e1f9..23cc8b9bdfdc71a5e743d5afabad5c946bb98fff 100644 (file)
@@ -172,8 +172,8 @@ def watch_rule_update(context, watch_id, values):
     return IMPL.watch_rule_update(context, watch_id, values)
 
 
-def watch_rule_delete(context, watch_rule_name):
-    return IMPL.watch_rule_delete(context, watch_rule_name)
+def watch_rule_delete(context, watch_id):
+    return IMPL.watch_rule_delete(context, watch_id)
 
 
 def watch_data_create(context, values):
index 9e825784c39fc535af17092a3534b23e775d2b9f..02941bf77db0bc93a1e32e0b7b003b5cde3b0995 100644 (file)
@@ -302,13 +302,11 @@ def watch_rule_update(context, watch_id, values):
     wr.save(_session(context))
 
 
-def watch_rule_delete(context, watch_name):
-    wr = model_query(context, models.WatchRule).\
-        filter_by(name=watch_name).first()
-
+def watch_rule_delete(context, watch_id):
+    wr = watch_rule_get(context, watch_id)
     if not wr:
         raise exception.NotFound('Attempt to delete watch_rule: %s %s' %
-                                 (watch_name, 'that does not exist'))
+                                 (watch_id, 'that does not exist'))
 
     session = Session.object_session(wr)
 
index 46cbdd3edda8feb17e4ba5b3106fe50a6155e43b..0d2d9ecb4d8648d218b53c8be238343dda4393a4 100644 (file)
@@ -17,7 +17,6 @@ from heat.common import exception
 from heat.engine import watchrule
 from heat.engine import resource
 from heat.engine.properties import Properties
-from heat.db import api as db_api
 
 from heat.openstack.common import log as logging
 
@@ -107,8 +106,9 @@ class CloudWatchAlarm(resource.Resource):
 
     def handle_delete(self):
         try:
-            db_api.watch_rule_delete(self.context,
-                                     self.physical_resource_name())
+            wr = watchrule.WatchRule.load(
+                self.context, watch_name=self.physical_resource_name())
+            wr.destroy()
         except exception.NotFound:
             pass
 
index 0a70ac9333ef9f7bada16f560d00ebc8b67378dd..d646b29b2b18a211a1a382ad4fae3c1083ae9ab5 100644 (file)
@@ -99,6 +99,13 @@ class WatchRule(object):
         else:
             db_api.watch_rule_update(self.context, self.id, wr_values)
 
+    def destroy(self):
+        '''
+        Delete the watchrule from the database.
+        '''
+        if self.id:
+            db_api.watch_rule_delete(self.context, self.id)
+
     def do_data_cmp(self, data, threshold):
         op = self.rule['ComparisonOperator']
         if op == 'GreaterThanThreshold':
index b524aed25ae885a1c70b3dd6a5b11f0323d972c1..8a71eaeed02ccffb16257f5067c415c3f6a109b8 100644 (file)
@@ -1026,25 +1026,34 @@ class stackServiceTest(HeatTestCase):
         self.m.VerifyAll()
 
     @stack_context('service_show_watch_test_stack', False)
+    @utils.wr_delete_after
     def test_show_watch(self):
         # Insert two dummy watch rules into the DB
-        values = {'stack_id': self.stack.id,
-                  'state': 'NORMAL',
-                  'name': u'HttpFailureAlarm',
-                  'rule': {u'EvaluationPeriods': u'1',
-                           u'AlarmActions': [u'WebServerRestartPolicy'],
-                           u'AlarmDescription': u'Restart the WikiDatabase',
-                           u'Namespace': u'system/linux',
-                           u'Period': u'300',
-                           u'ComparisonOperator': u'GreaterThanThreshold',
-                           u'Statistic': u'SampleCount',
-                           u'Threshold': u'2',
-                           u'MetricName': u'ServiceFailure'}}
-        db_ret = db_api.watch_rule_create(self.ctx, values)
-        self.assertNotEqual(db_ret, None)
-        values['name'] = "AnotherWatch"
-        db_ret = db_api.watch_rule_create(self.ctx, values)
-        self.assertNotEqual(db_ret, None)
+        rule = {u'EvaluationPeriods': u'1',
+                u'AlarmActions': [u'WebServerRestartPolicy'],
+                u'AlarmDescription': u'Restart the WikiDatabase',
+                u'Namespace': u'system/linux',
+                u'Period': u'300',
+                u'ComparisonOperator': u'GreaterThanThreshold',
+                u'Statistic': u'SampleCount',
+                u'Threshold': u'2',
+                u'MetricName': u'ServiceFailure'}
+        self.wr = []
+        self.wr.append(watchrule.WatchRule(context=self.ctx,
+                                           watch_name='HttpFailureAlarm',
+                                           rule=rule,
+                                           watch_data=[],
+                                           stack_id=self.stack.id,
+                                           state='NORMAL'))
+        self.wr[0].store()
+
+        self.wr.append(watchrule.WatchRule(context=self.ctx,
+                                           watch_name='AnotherWatch',
+                                           rule=rule,
+                                           watch_data=[],
+                                           stack_id=self.stack.id,
+                                           state='NORMAL'))
+        self.wr[1].store()
 
         # watch_name=None should return both watches
         result = self.eng.show_watch(self.ctx, watch_name=None)
@@ -1062,27 +1071,26 @@ class stackServiceTest(HeatTestCase):
         for key in engine_api.WATCH_KEYS:
             self.assertTrue(key in result[0])
 
-        # Cleanup, delete the dummy rules
-        db_api.watch_rule_delete(self.ctx, "HttpFailureAlarm")
-        db_api.watch_rule_delete(self.ctx, "AnotherWatch")
-
     @stack_context('service_show_watch_metric_test_stack', False)
+    @utils.wr_delete_after
     def test_show_watch_metric(self):
         # Insert dummy watch rule into the DB
-        values = {'stack_id': self.stack.id,
-                  'state': 'NORMAL',
-                  'name': u'HttpFailureAlarm',
-                  'rule': {u'EvaluationPeriods': u'1',
-                           u'AlarmActions': [u'WebServerRestartPolicy'],
-                           u'AlarmDescription': u'Restart the WikiDatabase',
-                           u'Namespace': u'system/linux',
-                           u'Period': u'300',
-                           u'ComparisonOperator': u'GreaterThanThreshold',
-                           u'Statistic': u'SampleCount',
-                           u'Threshold': u'2',
-                           u'MetricName': u'ServiceFailure'}}
-        db_ret = db_api.watch_rule_create(self.ctx, values)
-        self.assertNotEqual(db_ret, None)
+        rule = {u'EvaluationPeriods': u'1',
+                u'AlarmActions': [u'WebServerRestartPolicy'],
+                u'AlarmDescription': u'Restart the WikiDatabase',
+                u'Namespace': u'system/linux',
+                u'Period': u'300',
+                u'ComparisonOperator': u'GreaterThanThreshold',
+                u'Statistic': u'SampleCount',
+                u'Threshold': u'2',
+                u'MetricName': u'ServiceFailure'}
+        self.wr = watchrule.WatchRule(context=self.ctx,
+                                      watch_name='HttpFailureAlarm',
+                                      rule=rule,
+                                      watch_data=[],
+                                      stack_id=self.stack.id,
+                                      state='NORMAL')
+        self.wr.store()
 
         # And add a metric datapoint
         watch = db_api.watch_rule_get_by_name(self.ctx, "HttpFailureAlarm")
@@ -1106,30 +1114,30 @@ class stackServiceTest(HeatTestCase):
                                             metric_name=None)
         self.assertEqual(2, len(result))
 
-        # Cleanup, delete the dummy rule
-        db_api.watch_rule_delete(self.ctx, "HttpFailureAlarm")
-
         # Check the response has all keys defined in the engine API
         for key in engine_api.WATCH_DATA_KEYS:
             self.assertTrue(key in result[0])
 
     @stack_context('service_show_watch_state_test_stack')
+    @utils.wr_delete_after
     def test_set_watch_state(self):
         # Insert dummy watch rule into the DB
-        values = {'stack_id': self.stack.id,
-                  'state': 'NORMAL',
-                  'name': u'OverrideAlarm',
-                  'rule': {u'EvaluationPeriods': u'1',
-                           u'AlarmActions': [u'WebServerRestartPolicy'],
-                           u'AlarmDescription': u'Restart the WikiDatabase',
-                           u'Namespace': u'system/linux',
-                           u'Period': u'300',
-                           u'ComparisonOperator': u'GreaterThanThreshold',
-                           u'Statistic': u'SampleCount',
-                           u'Threshold': u'2',
-                           u'MetricName': u'ServiceFailure'}}
-        db_ret = db_api.watch_rule_create(self.ctx, values)
-        self.assertNotEqual(db_ret, None)
+        rule = {u'EvaluationPeriods': u'1',
+                u'AlarmActions': [u'WebServerRestartPolicy'],
+                u'AlarmDescription': u'Restart the WikiDatabase',
+                u'Namespace': u'system/linux',
+                u'Period': u'300',
+                u'ComparisonOperator': u'GreaterThanThreshold',
+                u'Statistic': u'SampleCount',
+                u'Threshold': u'2',
+                u'MetricName': u'ServiceFailure'}
+        self.wr = watchrule.WatchRule(context=self.ctx,
+                                      watch_name='OverrideAlarm',
+                                      rule=rule,
+                                      watch_data=[],
+                                      stack_id=self.stack.id,
+                                      state='NORMAL')
+        self.wr.store()
 
         class DummyAction:
             alarm = "dummyfoo"
@@ -1168,26 +1176,27 @@ class stackServiceTest(HeatTestCase):
                          [DummyAction.alarm])
 
         self.m.VerifyAll()
-        # Cleanup, delete the dummy rule
-        db_api.watch_rule_delete(self.ctx, "OverrideAlarm")
 
     @stack_context('service_show_watch_state_badstate_test_stack')
+    @utils.wr_delete_after
     def test_set_watch_state_badstate(self):
         # Insert dummy watch rule into the DB
-        values = {'stack_id': self.stack.id,
-                  'state': 'NORMAL',
-                  'name': u'OverrideAlarm2',
-                  'rule': {u'EvaluationPeriods': u'1',
-                           u'AlarmActions': [u'WebServerRestartPolicy'],
-                           u'AlarmDescription': u'Restart the WikiDatabase',
-                           u'Namespace': u'system/linux',
-                           u'Period': u'300',
-                           u'ComparisonOperator': u'GreaterThanThreshold',
-                           u'Statistic': u'SampleCount',
-                           u'Threshold': u'2',
-                           u'MetricName': u'ServiceFailure'}}
-        db_ret = db_api.watch_rule_create(self.ctx, values)
-        self.assertNotEqual(db_ret, None)
+        rule = {u'EvaluationPeriods': u'1',
+                u'AlarmActions': [u'WebServerRestartPolicy'],
+                u'AlarmDescription': u'Restart the WikiDatabase',
+                u'Namespace': u'system/linux',
+                u'Period': u'300',
+                u'ComparisonOperator': u'GreaterThanThreshold',
+                u'Statistic': u'SampleCount',
+                u'Threshold': u'2',
+                u'MetricName': u'ServiceFailure'}
+        self.wr = watchrule.WatchRule(context=self.ctx,
+                                      watch_name='OverrideAlarm2',
+                                      rule=rule,
+                                      watch_data=[],
+                                      stack_id=self.stack.id,
+                                      state='NORMAL')
+        self.wr.store()
 
         self.m.StubOutWithMock(watchrule.WatchRule, 'set_watch_state')
         for state in ["HGJHGJHG", "1234", "!\*(&%"]:
@@ -1203,9 +1212,6 @@ class stackServiceTest(HeatTestCase):
 
         self.m.VerifyAll()
 
-        # Cleanup, delete the dummy rule
-        db_api.watch_rule_delete(self.ctx, "OverrideAlarm2")
-
     def test_set_watch_state_noexist(self):
         state = watchrule.WatchRule.ALARM   # State valid
 
index 1c342dd7042e21469b34209e3568ba5aac59113d..2ac4cc328b82d0e275b04efbbac17564e533288e 100644 (file)
@@ -18,6 +18,7 @@ import mox
 from heat.common import context
 import heat.db.api as db_api
 
+from heat.common import exception
 from heat.openstack.common import timeutils
 from heat.engine import watchrule
 from heat.engine import parser
@@ -97,23 +98,23 @@ class WatchRuleTest(HeatTestCase):
         data.append(WatchData(53, now - datetime.timedelta(seconds=150)))
 
         # all > 50 -> NORMAL
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=data,
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
-        new_state = watcher.get_alarm_state()
+        new_state = self.wr.get_alarm_state()
         self.assertEqual(new_state, 'NORMAL')
 
         data.append(WatchData(25, now - datetime.timedelta(seconds=250)))
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=data,
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
-        new_state = watcher.get_alarm_state()
+        new_state = self.wr.get_alarm_state()
         self.assertEqual(new_state, 'ALARM')
 
     def test_maximum(self):
@@ -130,25 +131,25 @@ class WatchRuleTest(HeatTestCase):
         data.append(WatchData(23, now - datetime.timedelta(seconds=150)))
 
         # all < 30 -> NORMAL
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=data,
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
-        watcher.now = now
-        new_state = watcher.get_alarm_state()
+        self.wr.now = now
+        new_state = self.wr.get_alarm_state()
         self.assertEqual(new_state, 'NORMAL')
 
         data.append(WatchData(35, now - datetime.timedelta(seconds=150)))
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=data,
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
-        watcher.now = now
-        new_state = watcher.get_alarm_state()
+        self.wr.now = now
+        new_state = self.wr.get_alarm_state()
         self.assertEqual(new_state, 'ALARM')
 
     def test_samplecount(self):
@@ -166,39 +167,39 @@ class WatchRuleTest(HeatTestCase):
         data.append(WatchData(1, now - datetime.timedelta(seconds=150)))
 
         # only 2 samples -> NORMAL
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=data,
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
-        watcher.now = now
-        new_state = watcher.get_alarm_state()
+        self.wr.now = now
+        new_state = self.wr.get_alarm_state()
         self.assertEqual(new_state, 'NORMAL')
 
         # only 3 samples -> ALARM
         data.append(WatchData(1, now - datetime.timedelta(seconds=200)))
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=data,
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
-        watcher.now = now
-        new_state = watcher.get_alarm_state()
+        self.wr.now = now
+        new_state = self.wr.get_alarm_state()
         self.assertEqual(new_state, 'ALARM')
 
         # only 3 samples (one old) -> NORMAL
         data.pop(0)
         data.append(WatchData(1, now - datetime.timedelta(seconds=400)))
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=data,
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
-        watcher.now = now
-        new_state = watcher.get_alarm_state()
+        self.wr.now = now
+        new_state = self.wr.get_alarm_state()
         self.assertEqual(new_state, 'NORMAL')
 
     def test_sum(self):
@@ -215,26 +216,26 @@ class WatchRuleTest(HeatTestCase):
         data.append(WatchData(23, now - datetime.timedelta(seconds=150)))
 
         # all < 40 -> NORMAL
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=data,
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
-        watcher.now = now
-        new_state = watcher.get_alarm_state()
+        self.wr.now = now
+        new_state = self.wr.get_alarm_state()
         self.assertEqual(new_state, 'NORMAL')
 
         # sum > 100 -> ALARM
         data.append(WatchData(85, now - datetime.timedelta(seconds=150)))
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=data,
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
-        watcher.now = now
-        new_state = watcher.get_alarm_state()
+        self.wr.now = now
+        new_state = self.wr.get_alarm_state()
         self.assertEqual(new_state, 'ALARM')
 
     def test_ave(self):
@@ -250,46 +251,55 @@ class WatchRuleTest(HeatTestCase):
         data = [WatchData(117, now - datetime.timedelta(seconds=100))]
         data.append(WatchData(23, now - datetime.timedelta(seconds=150)))
 
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=data,
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
-        watcher.now = now
-        new_state = watcher.get_alarm_state()
+        self.wr.now = now
+        new_state = self.wr.get_alarm_state()
         self.assertEqual(new_state, 'NORMAL')
 
         data.append(WatchData(195, now - datetime.timedelta(seconds=250)))
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=data,
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
-        watcher.now = now
-        new_state = watcher.get_alarm_state()
+        self.wr.now = now
+        new_state = self.wr.get_alarm_state()
         self.assertEqual(new_state, 'ALARM')
 
+    @utils.wr_delete_after
     def test_load(self):
         # Insert two dummy watch rules into the DB
-        values = {'stack_id': self.stack_id,
-                  'state': 'NORMAL',
-                  'name': u'HttpFailureAlarm',
-                  'rule': {u'EvaluationPeriods': u'1',
-                           u'AlarmActions': [u'WebServerRestartPolicy'],
-                           u'AlarmDescription': u'Restart the WikiDatabase',
-                           u'Namespace': u'system/linux',
-                           u'Period': u'300',
-                           u'ComparisonOperator': u'GreaterThanThreshold',
-                           u'Statistic': u'SampleCount',
-                           u'Threshold': u'2',
-                           u'MetricName': u'ServiceFailure'}}
-        db_ret = db_api.watch_rule_create(self.ctx, values)
-        self.assertNotEqual(db_ret, None)
-        values['name'] = 'AnotherWatch'
-        db_ret = db_api.watch_rule_create(self.ctx, values)
-        self.assertNotEqual(db_ret, None)
+        rule = {u'EvaluationPeriods': u'1',
+                u'AlarmActions': [u'WebServerRestartPolicy'],
+                u'AlarmDescription': u'Restart the WikiDatabase',
+                u'Namespace': u'system/linux',
+                u'Period': u'300',
+                u'ComparisonOperator': u'GreaterThanThreshold',
+                u'Statistic': u'SampleCount',
+                u'Threshold': u'2',
+                u'MetricName': u'ServiceFailure'}
+        self.wr = []
+        self.wr.append(watchrule.WatchRule(context=self.ctx,
+                                           watch_name='HttpFailureAlarm',
+                                           rule=rule,
+                                           watch_data=[],
+                                           stack_id=self.stack_id,
+                                           state='NORMAL'))
+        self.wr[0].store()
+
+        self.wr.append(watchrule.WatchRule(context=self.ctx,
+                                           watch_name='AnotherWatch',
+                                           rule=rule,
+                                           watch_data=[],
+                                           stack_id=self.stack_id,
+                                           state='NORMAL'))
+        self.wr[1].store()
 
         # Then use WatchRule.load() to retrieve each by name
         # and check that the object properties match the data above
@@ -297,15 +307,12 @@ class WatchRuleTest(HeatTestCase):
             wr = watchrule.WatchRule.load(self.ctx, wn)
             self.assertEqual(type(wr), watchrule.WatchRule)
             self.assertEqual(wr.name, wn)
-            self.assertEqual(wr.state, values['state'])
-            self.assertEqual(wr.rule, values['rule'])
+            self.assertEqual(wr.state, 'NORMAL')
+            self.assertEqual(wr.rule, rule)
             self.assertEqual(wr.timeperiod, datetime.timedelta(
-                             seconds=int(values['rule']['Period'])))
-
-        # Cleanup
-        db_api.watch_rule_delete(self.ctx, 'HttpFailureAlarm')
-        db_api.watch_rule_delete(self.ctx, 'AnotherWatch')
+                             seconds=int(rule['Period'])))
 
+    @utils.wr_delete_after
     def test_store(self):
         rule = {u'EvaluationPeriods': u'1',
                 u'AlarmActions': [u'WebServerRestartPolicy'],
@@ -316,9 +323,9 @@ class WatchRuleTest(HeatTestCase):
                 u'Statistic': u'SampleCount',
                 u'Threshold': u'2',
                 u'MetricName': u'ServiceFailure'}
-        wr = watchrule.WatchRule(context=self.ctx, watch_name='storetest',
-                                 stack_id=self.stack_id, rule=rule)
-        wr.store()
+        self.wr = watchrule.WatchRule(context=self.ctx, watch_name='storetest',
+                                      stack_id=self.stack_id, rule=rule)
+        self.wr.store()
 
         dbwr = db_api.watch_rule_get_by_name(self.ctx, 'storetest')
         self.assertNotEqual(dbwr, None)
@@ -326,9 +333,7 @@ class WatchRuleTest(HeatTestCase):
         self.assertEqual(dbwr.state, watchrule.WatchRule.NODATA)
         self.assertEqual(dbwr.rule, rule)
 
-        # Cleanup
-        db_api.watch_rule_delete(self.ctx, 'storetest')
-
+    @utils.wr_delete_after
     def test_evaluate(self):
         rule = {'EvaluationPeriods': '1',
                 'MetricName': 'test_metric',
@@ -345,47 +350,48 @@ class WatchRuleTest(HeatTestCase):
         # It's not time to evaluate, so should stay NODATA
         last = now - datetime.timedelta(seconds=299)
         data = WatchData(25, now - datetime.timedelta(seconds=150))
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=[data],
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
 
-        actions = watcher.evaluate()
-        self.assertEqual(watcher.state, 'NODATA')
+        actions = self.wr.evaluate()
+        self.assertEqual(self.wr.state, 'NODATA')
         self.assertEqual(actions, [])
 
         # now - last == Period, so should set NORMAL
         last = now - datetime.timedelta(seconds=300)
         data = WatchData(25, now - datetime.timedelta(seconds=150))
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=[data],
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
 
-        actions = watcher.evaluate()
-        self.assertEqual(watcher.state, 'NORMAL')
-        self.assertEqual(watcher.last_evaluated, now)
+        actions = self.wr.evaluate()
+        self.assertEqual(self.wr.state, 'NORMAL')
+        self.assertEqual(self.wr.last_evaluated, now)
         self.assertEqual(actions, [])
 
         # Now data breaches Threshold, so should set ALARM
         last = now - datetime.timedelta(seconds=300)
         data = WatchData(35, now - datetime.timedelta(seconds=150))
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=[data],
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
 
-        actions = watcher.evaluate()
-        self.assertEqual(watcher.state, 'ALARM')
-        self.assertEqual(watcher.last_evaluated, now)
+        actions = self.wr.evaluate()
+        self.assertEqual(self.wr.state, 'ALARM')
+        self.assertEqual(self.wr.last_evaluated, now)
         self.assertEqual(actions, [])
 
+    @utils.wr_delete_after
     def test_rule_actions_alarm_normal(self):
         rule = {'EvaluationPeriods': '1',
                 'MetricName': 'test_metric',
@@ -401,18 +407,19 @@ class WatchRuleTest(HeatTestCase):
         # Set data so rule evaluates to NORMAL state
         last = now - datetime.timedelta(seconds=300)
         data = WatchData(25, now - datetime.timedelta(seconds=150))
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=[data],
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
 
-        actions = watcher.evaluate()
-        self.assertEqual(watcher.state, 'NORMAL')
+        actions = self.wr.evaluate()
+        self.assertEqual(self.wr.state, 'NORMAL')
         self.assertEqual(actions, [])
         self.m.VerifyAll()
 
+    @utils.wr_delete_after
     def test_rule_actions_alarm_alarm(self):
         rule = {'EvaluationPeriods': '1',
                 'MetricName': 'test_metric',
@@ -428,25 +435,26 @@ class WatchRuleTest(HeatTestCase):
         # Set data so rule evaluates to ALARM state
         last = now - datetime.timedelta(seconds=300)
         data = WatchData(35, now - datetime.timedelta(seconds=150))
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=[data],
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
 
-        actions = watcher.evaluate()
-        self.assertEqual(watcher.state, 'ALARM')
+        actions = self.wr.evaluate()
+        self.assertEqual(self.wr.state, 'ALARM')
         self.assertEqual(actions, ['DummyAction'])
 
         # re-set last_evaluated so the rule will be evaluated again.
         last = now - datetime.timedelta(seconds=300)
-        watcher.last_evaluated = last
-        actions = watcher.evaluate()
-        self.assertEqual(watcher.state, 'ALARM')
+        self.wr.last_evaluated = last
+        actions = self.wr.evaluate()
+        self.assertEqual(self.wr.state, 'ALARM')
         self.assertEqual(actions, ['DummyAction'])
         self.m.VerifyAll()
 
+    @utils.wr_delete_after
     def test_rule_actions_alarm_two_actions(self):
         rule = {'EvaluationPeriods': '1',
                 'MetricName': 'test_metric',
@@ -462,18 +470,19 @@ class WatchRuleTest(HeatTestCase):
         # Set data so rule evaluates to ALARM state
         last = now - datetime.timedelta(seconds=300)
         data = WatchData(35, now - datetime.timedelta(seconds=150))
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=[data],
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
 
-        actions = watcher.evaluate()
-        self.assertEqual(watcher.state, 'ALARM')
+        actions = self.wr.evaluate()
+        self.assertEqual(self.wr.state, 'ALARM')
         self.assertEqual(actions, ['DummyAction', 'DummyAction'])
         self.m.VerifyAll()
 
+    @utils.wr_delete_after
     def test_rule_actions_ok_alarm(self):
         rule = {'EvaluationPeriods': '1',
                 'MetricName': 'test_metric',
@@ -488,15 +497,15 @@ class WatchRuleTest(HeatTestCase):
 
         # On creation the rule evaluates to NODATA state
         last = now - datetime.timedelta(seconds=300)
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=[],
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
 
-        actions = watcher.evaluate()
-        self.assertEqual(watcher.state, 'NODATA')
+        actions = self.wr.evaluate()
+        self.assertEqual(self.wr.state, 'NODATA')
         self.assertEqual(actions, [])
 
         # Move time forward and add data below threshold so we transition from
@@ -507,13 +516,14 @@ class WatchRuleTest(HeatTestCase):
         self._action_set_stubs(now)
 
         data = WatchData(25, now - datetime.timedelta(seconds=150))
-        watcher.watch_data = [data]
+        self.wr.watch_data = [data]
 
-        actions = watcher.evaluate()
-        self.assertEqual(watcher.state, 'NORMAL')
+        actions = self.wr.evaluate()
+        self.assertEqual(self.wr.state, 'NORMAL')
         self.assertEqual(actions, ['DummyAction'])
         self.m.VerifyAll()
 
+    @utils.wr_delete_after
     def test_rule_actions_nodata(self):
         rule = {'EvaluationPeriods': '1',
                 'MetricName': 'test_metric',
@@ -529,15 +539,15 @@ class WatchRuleTest(HeatTestCase):
         # Set data so rule evaluates to ALARM state
         last = now - datetime.timedelta(seconds=300)
         data = WatchData(35, now - datetime.timedelta(seconds=150))
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=[data],
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
 
-        actions = watcher.evaluate()
-        self.assertEqual(watcher.state, 'ALARM')
+        actions = self.wr.evaluate()
+        self.assertEqual(self.wr.state, 'ALARM')
         self.assertEqual(actions, [])
 
         # Move time forward and don't add data so we transition from
@@ -547,11 +557,12 @@ class WatchRuleTest(HeatTestCase):
         self.m.UnsetStubs()
         self._action_set_stubs(now)
 
-        actions = watcher.evaluate()
-        self.assertEqual(watcher.state, 'NODATA')
+        actions = self.wr.evaluate()
+        self.assertEqual(self.wr.state, 'NODATA')
         self.assertEqual(actions, ['DummyAction'])
         self.m.VerifyAll()
 
+    @utils.wr_delete_after
     def test_create_watch_data(self):
         rule = {u'EvaluationPeriods': u'1',
                 u'AlarmDescription': u'test alarm',
@@ -560,16 +571,16 @@ class WatchRuleTest(HeatTestCase):
                 u'Statistic': u'SampleCount',
                 u'Threshold': u'2',
                 u'MetricName': u'CreateDataMetric'}
-        wr = watchrule.WatchRule(context=self.ctx,
-                                 watch_name='create_data_test',
-                                 stack_id=self.stack_id, rule=rule)
+        self.wr = watchrule.WatchRule(context=self.ctx,
+                                      watch_name='create_data_test',
+                                      stack_id=self.stack_id, rule=rule)
 
-        wr.store()
+        self.wr.store()
 
         data = {u'CreateDataMetric': {"Unit": "Counter",
                                       "Value": "1",
                                       "Dimensions": []}}
-        wr.create_watch_data(data)
+        self.wr.create_watch_data(data)
 
         dbwr = db_api.watch_rule_get_by_name(self.ctx, 'create_data_test')
         self.assertEqual(dbwr.watch_data[0].data, data)
@@ -581,8 +592,33 @@ class WatchRuleTest(HeatTestCase):
         # correctly get a list of all datapoints where watch_rule_id ==
         # watch_rule.id, so leave it as a single-datapoint test for now.
 
-        # Cleanup
-        db_api.watch_rule_delete(self.ctx, 'create_data_test')
+    def test_destroy(self):
+        rule = {'EvaluationPeriods': '1',
+                'MetricName': 'test_metric',
+                'AlarmActions': ['DummyAction'],
+                'Period': '300',
+                'Statistic': 'Maximum',
+                'ComparisonOperator': 'GreaterThanOrEqualToThreshold',
+                'Threshold': '30'}
+
+        last = timeutils.utcnow()
+        self.wr = watchrule.WatchRule(context=self.ctx,
+                                      watch_name="testwatch_destroy",
+                                      rule=rule,
+                                      watch_data=[],
+                                      stack_id=self.stack_id,
+                                      last_evaluated=last)
+
+        self.wr.store()
+
+        check = watchrule.WatchRule.load(context=self.ctx,
+                                         watch_name="testwatch_destroy")
+        self.assertTrue(isinstance(check, watchrule.WatchRule))
+
+        self.wr.destroy()
+        self.assertRaises(exception.WatchRuleNotFound,
+                          watchrule.WatchRule.load, context=self.ctx,
+                          watch_name="testwatch_destroy")
 
     def test_set_watch_state(self):
         rule = {'EvaluationPeriods': '1',
@@ -598,20 +634,20 @@ class WatchRuleTest(HeatTestCase):
 
         # Set data so rule evaluates to ALARM state
         last = now - datetime.timedelta(seconds=200)
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=[],
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
 
-        actions = watcher.set_watch_state(watchrule.WatchRule.NODATA)
+        actions = self.wr.set_watch_state(watchrule.WatchRule.NODATA)
         self.assertEqual(actions, [])
 
-        actions = watcher.set_watch_state(watchrule.WatchRule.NORMAL)
+        actions = self.wr.set_watch_state(watchrule.WatchRule.NORMAL)
         self.assertEqual(actions, [])
 
-        actions = watcher.set_watch_state(watchrule.WatchRule.ALARM)
+        actions = self.wr.set_watch_state(watchrule.WatchRule.ALARM)
         self.assertEqual(actions, ['DummyAction'])
         self.m.VerifyAll()
 
@@ -627,13 +663,13 @@ class WatchRuleTest(HeatTestCase):
         now = timeutils.utcnow()
 
         last = now - datetime.timedelta(seconds=200)
-        watcher = watchrule.WatchRule(context=self.ctx,
+        self.wr = watchrule.WatchRule(context=self.ctx,
                                       watch_name="testwatch",
                                       rule=rule,
                                       watch_data=[],
                                       stack_id=self.stack_id,
                                       last_evaluated=last)
 
-        self.assertRaises(ValueError, watcher.set_watch_state, None)
+        self.assertRaises(ValueError, self.wr.set_watch_state, None)
 
-        self.assertRaises(ValueError, watcher.set_watch_state, "BADSTATE")
+        self.assertRaises(ValueError, self.wr.set_watch_state, "BADSTATE")
index 66567480c09db06e5508500b09e49eac9c10ff1a..2c622beeb1b9f9903c4aa5e7473a7f124d9a507b 100644 (file)
@@ -16,6 +16,7 @@ import sys
 import functools
 
 from heat.common import context
+from heat.common import exception
 from heat.engine import environment
 from heat.engine import parser
 
@@ -49,6 +50,44 @@ def stack_delete_after(test_fn):
     return wrapped_test
 
 
+def wr_delete_after(test_fn):
+    """
+    Decorator which calls test class self.wr.destroy()
+    to ensure tests clean up their watchrule regardless of test success/failure
+    Used by tests which create watchrule objects directly to cleanup correctly
+    self.wr can be either a single watchrule, or a list of several watchrules
+    """
+    @functools.wraps(test_fn)
+    def wrapped_test(test_case, *args, **kwargs):
+
+        def delete_wrs():
+            wr = getattr(test_case, 'wr', None)
+            try:
+                for w in wr:
+                    delete_wr(w)
+            except TypeError:
+                delete_wr(wr)
+
+        def delete_wr(w):
+            if w.id is not None:
+                try:
+                    w.destroy()
+                except exception.NotFound:
+                    pass
+        try:
+            test_fn(test_case, *args, **kwargs)
+        except:
+            exc_class, exc_val, exc_tb = sys.exc_info()
+            try:
+                delete_wrs()
+            finally:
+                raise exc_class, exc_val, exc_tb
+        else:
+            delete_wrs()
+
+    return wrapped_test
+
+
 def setup_dummy_db():
     migration.db_sync()
     engine = get_engine()