diff --git a/heat/db/api.py b/heat/db/api.py index 3835c14631..23cc8b9bdf 100644 --- a/heat/db/api.py +++ b/heat/db/api.py @@ -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): diff --git a/heat/db/sqlalchemy/api.py b/heat/db/sqlalchemy/api.py index 9e825784c3..02941bf77d 100644 --- a/heat/db/sqlalchemy/api.py +++ b/heat/db/sqlalchemy/api.py @@ -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) diff --git a/heat/engine/resources/cloud_watch.py b/heat/engine/resources/cloud_watch.py index 46cbdd3edd..0d2d9ecb4d 100644 --- a/heat/engine/resources/cloud_watch.py +++ b/heat/engine/resources/cloud_watch.py @@ -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 diff --git a/heat/engine/watchrule.py b/heat/engine/watchrule.py index 0a70ac9333..d646b29b2b 100644 --- a/heat/engine/watchrule.py +++ b/heat/engine/watchrule.py @@ -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': diff --git a/heat/tests/test_engine_service.py b/heat/tests/test_engine_service.py index b524aed25a..8a71eaeed0 100644 --- a/heat/tests/test_engine_service.py +++ b/heat/tests/test_engine_service.py @@ -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 diff --git a/heat/tests/test_watch.py b/heat/tests/test_watch.py index 1c342dd704..2ac4cc328b 100644 --- a/heat/tests/test_watch.py +++ b/heat/tests/test_watch.py @@ -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") diff --git a/heat/tests/utils.py b/heat/tests/utils.py index 66567480c0..2c622beeb1 100644 --- a/heat/tests/utils.py +++ b/heat/tests/utils.py @@ -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()