From 9e504033844149d250ed54191759fec406f62535 Mon Sep 17 00:00:00 2001 From: Sergey Kraynev Date: Tue, 24 Dec 2013 09:27:18 -0500 Subject: [PATCH] Fix ceilometer alarm properties schema The patch contains the following changes: Type changes: - evaluation_periods from String to Integer - threshold from String to Number - period from String to Integer Next options are not required now: - evaluation_period - statistic - period - comparison_operator Change-Id: I645673ca7bf52649322e3f4adf851145b9d1a244 Closes-Bug: #1261390 (cherry picked from commit ffc913cb930748e0cba0df5b485255d4ec41d5ee) --- heat/engine/resources/ceilometer/alarm.py | 10 +-- heat/tests/test_ceilometer_alarm.py | 94 +++++++++++++++++++++++ 2 files changed, 97 insertions(+), 7 deletions(-) diff --git a/heat/engine/resources/ceilometer/alarm.py b/heat/engine/resources/ceilometer/alarm.py index 9e69de4d44..ca9bfaa5c4 100644 --- a/heat/engine/resources/ceilometer/alarm.py +++ b/heat/engine/resources/ceilometer/alarm.py @@ -106,7 +106,6 @@ class CeilometerAlarm(resource.Resource): COMPARISON_OPERATOR: properties.Schema( properties.Schema.STRING, _('Operator used to compare specified statistic with threshold.'), - required=True, constraints=[ constraints.AllowedValues(['ge', 'gt', 'eq', 'ne', 'lt', 'le']), @@ -114,9 +113,8 @@ class CeilometerAlarm(resource.Resource): update_allowed=True ), EVALUATION_PERIODS: properties.Schema( - properties.Schema.STRING, + properties.Schema.INTEGER, _('Number of periods to evaluate over.'), - required=True, update_allowed=True ), METER_NAME: properties.Schema( @@ -125,15 +123,13 @@ class CeilometerAlarm(resource.Resource): required=True ), PERIOD: properties.Schema( - properties.Schema.STRING, + properties.Schema.INTEGER, _('Period (seconds) to evaluate over.'), - required=True, update_allowed=True ), STATISTIC: properties.Schema( properties.Schema.STRING, _('Meter statistic to evaluate.'), - required=True, constraints=[ constraints.AllowedValues(['count', 'avg', 'sum', 'min', 'max']), @@ -141,7 +137,7 @@ class CeilometerAlarm(resource.Resource): update_allowed=True ), THRESHOLD: properties.Schema( - properties.Schema.STRING, + properties.Schema.NUMBER, _('Threshold to evaluate against.'), required=True, update_allowed=True diff --git a/heat/tests/test_ceilometer_alarm.py b/heat/tests/test_ceilometer_alarm.py index ef2c3932d5..8135927795 100644 --- a/heat/tests/test_ceilometer_alarm.py +++ b/heat/tests/test_ceilometer_alarm.py @@ -66,6 +66,33 @@ alarm_template = ''' } ''' +not_string_alarm_template = ''' +{ + "AWSTemplateFormatVersion" : "2010-09-09", + "Description" : "Alarm Test", + "Parameters" : {}, + "Resources" : { + "MEMAlarmHigh": { + "Type": "OS::Ceilometer::Alarm", + "Properties": { + "description": "Scale-up if MEM > 50% for 1 minute", + "meter_name": "MemoryUtilization", + "statistic": "avg", + "period": 60, + "evaluation_periods": 1, + "threshold": 50, + "alarm_actions": [], + "matching_metadata": {}, + "comparison_operator": "gt" + } + }, + "signal_handler" : { + "Type" : "SignalResourceType" + } + } +} +''' + combination_alarm_template = ''' { "AWSTemplateFormatVersion" : "2010-09-09", @@ -240,6 +267,73 @@ class CeilometerAlarmTest(HeatTestCase): self.m.VerifyAll() + @utils.stack_delete_after + def test_mem_alarm_high_correct_int_parameters(self): + self.stack = self.create_stack(not_string_alarm_template) + + self.m.ReplayAll() + self.stack.create() + rsrc = self.stack['MEMAlarmHigh'] + self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) + self.assertIsNone(rsrc.validate()) + + self.assertIsInstance(rsrc.properties['evaluation_periods'], int) + self.assertIsInstance(rsrc.properties['period'], int) + self.assertIsInstance(rsrc.properties['threshold'], int) + + self.m.VerifyAll() + + def test_mem_alarm_high_not_correct_string_parameters(self): + snippet = template_format.parse(not_string_alarm_template) + for p in ('period', 'evaluation_periods'): + snippet['Resources']['MEMAlarmHigh']['Properties'][p] = '60a' + stack = utils.parse_stack(snippet) + + rsrc = alarm.CeilometerAlarm( + 'MEMAlarmHigh', snippet['Resources']['MEMAlarmHigh'], stack) + error = self.assertRaises(exception.StackValidationFailed, + rsrc.validate) + self.assertEqual( + "Property error : MEMAlarmHigh: %s Value '60a' is not an " + "integer" % p, str(error)) + + def test_mem_alarm_high_not_integer_parameters(self): + snippet = template_format.parse(not_string_alarm_template) + for p in ('period', 'evaluation_periods'): + snippet['Resources']['MEMAlarmHigh']['Properties'][p] = [60] + stack = utils.parse_stack(snippet) + + rsrc = alarm.CeilometerAlarm( + 'MEMAlarmHigh', snippet['Resources']['MEMAlarmHigh'], stack) + error = self.assertRaises(exception.StackValidationFailed, + rsrc.validate) + self.assertEqual( + "Property error : MEMAlarmHigh: %s int() argument must be " + "a string or a number, not 'list'" % p, str(error)) + + def test_mem_alarm_high_check_not_required_parameters(self): + snippet = template_format.parse(not_string_alarm_template) + snippet['Resources']['MEMAlarmHigh']['Properties'].pop('meter_name') + stack = utils.parse_stack(snippet) + + rsrc = alarm.CeilometerAlarm( + 'MEMAlarmHigh', snippet['Resources']['MEMAlarmHigh'], stack) + error = self.assertRaises(exception.StackValidationFailed, + rsrc.validate) + self.assertEqual( + "Property error : MEMAlarmHigh: Property meter_name not assigned", + str(error)) + + for p in ('period', 'evaluation_periods', 'statistic', + 'comparison_operator'): + snippet = template_format.parse(not_string_alarm_template) + snippet['Resources']['MEMAlarmHigh']['Properties'].pop(p) + stack = utils.parse_stack(snippet) + + rsrc = alarm.CeilometerAlarm( + 'MEMAlarmHigh', snippet['Resources']['MEMAlarmHigh'], stack) + self.assertIsNone(rsrc.validate()) + @testtools.skipIf(ceilometerclient is None, 'ceilometerclient unavailable') class CombinationAlarmTest(HeatTestCase):