From 14903dc1cdc562818b22869371dd2db90093a271 Mon Sep 17 00:00:00 2001 From: ricolin Date: Wed, 8 Mar 2017 16:26:20 +0800 Subject: [PATCH] Mark combination alarm as None resource Combination alarm has been removed from Aodh since Pike. We inherit combination alarm from none resource in this patch. Will schedule to remove the resource in future cycle. Closes-Bug: #1668342 Change-Id: I573f4bde9b4b7b12879c39111cf87c751f71ad7e --- heat/engine/resources/openstack/aodh/alarm.py | 75 ++------ heat/tests/openstack/aodh/test_alarm.py | 169 ------------------ ...placeholder-resource-e243e9692cab52e0.yaml | 10 ++ 3 files changed, 21 insertions(+), 233 deletions(-) create mode 100644 releasenotes/notes/mark-combination-alarm-as-placeholder-resource-e243e9692cab52e0.yaml diff --git a/heat/engine/resources/openstack/aodh/alarm.py b/heat/engine/resources/openstack/aodh/alarm.py index 42df08c568..ca6bb4e4c2 100644 --- a/heat/engine/resources/openstack/aodh/alarm.py +++ b/heat/engine/resources/openstack/aodh/alarm.py @@ -18,6 +18,7 @@ from heat.common.i18n import _ from heat.engine import constraints from heat.engine import properties from heat.engine.resources import alarm_base +from heat.engine.resources.openstack.heat import none_resource from heat.engine import support from heat.engine import watchrule @@ -224,27 +225,23 @@ class AodhAlarm(alarm_base.BaseAlarm): self.client().alarm.get(self.resource_id) -class CombinationAlarm(alarm_base.BaseAlarm): +class CombinationAlarm(none_resource.NoneResource): """A resource that implements combination of Aodh alarms. - Allows to use alarm as a combination of other alarms with some operator: - activate this alarm if any alarm in combination has been activated or - if all alarms in combination have been activated. + This resource is now deleted from Aodh, so will directly inherit from + NoneResource (placeholder resource). For old resources (which not a + placeholder resource), still can be deleted through client. Any newly + created resources will be considered as placeholder resources like none + resource. We will schedule to delete it from heat resources list. """ - alarm_type = 'combination' - - # aodhclient doesn't support to manage combination-alarm, - # so we use ceilometerclient to manage this resource as before, - # after two release cycles, to hidden this resource. - default_client_name = 'ceilometer' - - entity = 'alarms' + default_client_name = 'aodh' + entity = 'alarm' support_status = support.SupportStatus( status=support.HIDDEN, - message=_('OS::Aodh::CombinationAlarm is deprecated, ' - 'use OS::Aodh::CompositeAlarm instead.'), + message=_('OS::Aodh::CombinationAlarm is deprecated and has been ' + 'removed from Aodh, use OS::Aodh::CompositeAlarm instead.'), version='9.0.0', previous_status=support.SupportStatus( status=support.DEPRECATED, @@ -253,56 +250,6 @@ class CombinationAlarm(alarm_base.BaseAlarm): ) ) - PROPERTIES = ( - ALARM_IDS, OPERATOR, - ) = ( - 'alarm_ids', 'operator', - ) - - properties_schema = { - ALARM_IDS: properties.Schema( - properties.Schema.LIST, - _('List of alarm identifiers to combine.'), - required=True, - constraints=[constraints.Length(min=1)], - update_allowed=True), - OPERATOR: properties.Schema( - properties.Schema.STRING, - _('Operator used to combine the alarms.'), - constraints=[constraints.AllowedValues(['and', 'or'])], - update_allowed=True) - } - properties_schema.update(alarm_base.common_properties_schema) - - def handle_create(self): - props = self.actions_to_urls(self.properties) - props['name'] = self.physical_resource_name() - props['type'] = self.alarm_type - alarm = self.client().alarms.create( - **self._reformat_properties(props)) - self.resource_id_set(alarm.alarm_id) - - def handle_update(self, json_snippet, tmpl_diff, prop_diff): - if prop_diff: - kwargs = {'alarm_id': self.resource_id} - new_props = json_snippet.properties(self.properties_schema, - self.context) - kwargs.update(self._reformat_properties( - self.actions_to_urls(new_props))) - alarms_client = self.client().alarms - alarms_client.update(**kwargs) - - def handle_suspend(self): - self.client().alarms.update( - alarm_id=self.resource_id, enabled=False) - - def handle_resume(self): - self.client().alarms.update( - alarm_id=self.resource_id, enabled=True) - - def handle_check(self): - self.client().alarms.get(self.resource_id) - class EventAlarm(alarm_base.BaseAlarm): """A resource that implements event alarms. diff --git a/heat/tests/openstack/aodh/test_alarm.py b/heat/tests/openstack/aodh/test_alarm.py index 3ff48d525d..0411c86701 100644 --- a/heat/tests/openstack/aodh/test_alarm.py +++ b/heat/tests/openstack/aodh/test_alarm.py @@ -15,13 +15,11 @@ import copy import json import mock -import mox import six from heat.common import exception from heat.common import template_format from heat.engine.clients.os import aodh -from heat.engine.clients.os import ceilometer from heat.engine import resource from heat.engine.resources.openstack.aodh import alarm from heat.engine import rsrc_defn @@ -121,24 +119,6 @@ not_string_alarm_template = ''' } ''' -combination_alarm_template = ''' -{ - "AWSTemplateFormatVersion" : "2010-09-09", - "Description" : "Combination Alarm Test", - "Resources" : { - "CombinAlarm": { - "Type": "OS::Aodh::CombinationAlarm", - "Properties": { - "description": "Do stuff in combination", - "alarm_ids": ["alarm1", "alarm2"], - "operator": "and", - "alarm_actions": [], - } - } - } -} -''' - event_alarm_template = ''' { "heat_template_version" : "newton", @@ -164,13 +144,6 @@ event_alarm_template = ''' ''' -class FakeCombinationAlarm(object): - alarm_id = 'foo' - - def __init__(self): - self.to_dict = lambda: {'attr': 'val'} - - FakeAodhAlarm = {'other_attrs': 'val', 'alarm_id': 'foo'} @@ -698,148 +671,6 @@ class AodhAlarmTest(common.HeatTestCase): self.assertEqual(expected, alarm.actions_to_urls(props)) -class CombinationAlarmTest(common.HeatTestCase): - - def setUp(self): - super(CombinationAlarmTest, self).setUp() - self.fc = mock.Mock() - self.m.StubOutWithMock(ceilometer.CeilometerClientPlugin, '_create') - - def create_alarm(self): - ceilometer.CeilometerClientPlugin._create().AndReturn( - self.fc) - self.m.StubOutWithMock(self.fc.alarms, 'create') - self.fc.alarms.create( - alarm_actions=[], - description=u'Do stuff in combination', - enabled=True, - insufficient_data_actions=[], - ok_actions=[], - name=mox.IgnoreArg(), type='combination', - repeat_actions=True, - combination_rule={'alarm_ids': [u'alarm1', u'alarm2'], - 'operator': u'and'}, - time_constraints=[], - severity='low' - ).AndReturn(FakeCombinationAlarm()) - self.tmpl = template_format.parse(combination_alarm_template) - self.stack = utils.parse_stack(self.tmpl) - resource_defns = self.stack.t.resource_definitions(self.stack) - return alarm.CombinationAlarm( - 'CombinAlarm', resource_defns['CombinAlarm'], self.stack) - - def test_create(self): - rsrc = self.create_alarm() - - self.m.ReplayAll() - scheduler.TaskRunner(rsrc.create)() - self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) - self.assertEqual('foo', rsrc.resource_id) - self.m.VerifyAll() - - def test_invalid_alarm_list(self): - snippet = template_format.parse(combination_alarm_template) - snippet['Resources']['CombinAlarm']['Properties']['alarm_ids'] = [] - stack = utils.parse_stack(snippet) - resource_defns = stack.t.resource_definitions(stack) - rsrc = alarm.CombinationAlarm( - 'CombinAlarm', resource_defns['CombinAlarm'], stack) - error = self.assertRaises(exception.StackValidationFailed, - rsrc.validate) - self.assertEqual( - "Property error: Resources.CombinAlarm.Properties.alarm_ids: " - "length (0) is out of range (min: 1, max: None)", - six.text_type(error)) - - def test_update(self): - rsrc = self.create_alarm() - self.m.StubOutWithMock(self.fc.alarms, 'update') - self.fc.alarms.update( - alarm_id='foo', - alarm_actions=[], - description=u'Do stuff in combination', - enabled=True, - insufficient_data_actions=[], - ok_actions=[], - repeat_actions=True, - combination_rule={'alarm_ids': [u'alarm1', u'alarm3'], - 'operator': u'and'}, - time_constraints=[], - severity='low' - ) - - self.m.ReplayAll() - scheduler.TaskRunner(rsrc.create)() - - props = self.tmpl['Resources']['CombinAlarm']['Properties'].copy() - props['alarm_ids'] = ['alarm1', 'alarm3'] - update_template = rsrc.t.freeze(properties=props) - scheduler.TaskRunner(rsrc.update, update_template)() - self.assertEqual((rsrc.UPDATE, rsrc.COMPLETE), rsrc.state) - - self.m.VerifyAll() - - def test_suspend(self): - rsrc = self.create_alarm() - self.m.StubOutWithMock(self.fc.alarms, 'update') - self.fc.alarms.update(alarm_id='foo', enabled=False) - - self.m.ReplayAll() - scheduler.TaskRunner(rsrc.create)() - - scheduler.TaskRunner(rsrc.suspend)() - self.assertEqual((rsrc.SUSPEND, rsrc.COMPLETE), rsrc.state) - - self.m.VerifyAll() - - def test_resume(self): - rsrc = self.create_alarm() - self.m.StubOutWithMock(self.fc.alarms, 'update') - self.fc.alarms.update(alarm_id='foo', enabled=True) - - self.m.ReplayAll() - scheduler.TaskRunner(rsrc.create)() - rsrc.state_set(rsrc.SUSPEND, rsrc.COMPLETE) - - scheduler.TaskRunner(rsrc.resume)() - self.assertEqual((rsrc.RESUME, rsrc.COMPLETE), rsrc.state) - - self.m.VerifyAll() - - def _prepare_resource(self, for_check=True): - snippet = template_format.parse(combination_alarm_template) - self.stack = utils.parse_stack(snippet) - res = self.stack['CombinAlarm'] - if for_check: - res.state_set(res.CREATE, res.COMPLETE) - res.client = mock.Mock() - mock_alarm = mock.Mock(enabled=True, state='ok') - res.client().alarms.get.return_value = mock_alarm - return res - - def test_check(self): - res = self._prepare_resource() - scheduler.TaskRunner(res.check)() - self.assertEqual((res.CHECK, res.COMPLETE), res.state) - - def test_check_failure(self): - res = self._prepare_resource() - res.client().alarms.get.side_effect = Exception('Boom') - - self.assertRaises(exception.ResourceFailure, - scheduler.TaskRunner(res.check)) - self.assertEqual((res.CHECK, res.FAILED), res.state) - self.assertIn('Boom', res.status_reason) - - def test_show_resource(self): - res = self._prepare_resource(for_check=False) - res.client().alarms.create.return_value = mock.MagicMock( - alarm_id='2') - res.client().alarms.get.return_value = FakeCombinationAlarm() - scheduler.TaskRunner(res.create)() - self.assertEqual({'attr': 'val'}, res.FnGetAtt('show')) - - class EventAlarmTest(common.HeatTestCase): def setUp(self): super(EventAlarmTest, self).setUp() diff --git a/releasenotes/notes/mark-combination-alarm-as-placeholder-resource-e243e9692cab52e0.yaml b/releasenotes/notes/mark-combination-alarm-as-placeholder-resource-e243e9692cab52e0.yaml new file mode 100644 index 0000000000..d19c298a31 --- /dev/null +++ b/releasenotes/notes/mark-combination-alarm-as-placeholder-resource-e243e9692cab52e0.yaml @@ -0,0 +1,10 @@ +--- +critical: + - Since Aodh drop support for combination alarm, therefore + OS::Aodh::CombinationAlarm is now mark as hidden resource with + directly inheriting from None resource which will make the + resource do nothing when handling any actions (other than delete). + And please don't use it. Old resource which created with that + resource type still able to delete. It's recommand to switch + that resource type ASAP, since we will remove that resource + soon.