From 699b229a1d535cd2013e35a44756484131a81357 Mon Sep 17 00:00:00 2001 From: gordon chung Date: Mon, 11 Jan 2016 11:59:53 -0500 Subject: [PATCH] add event alarm support Change-Id: I305fbed1584d2aa842b4590fdfff180c933b56c7 --- aodhclient/tests/functional/test_alarm.py | 90 ++++++++++++++++++++++- aodhclient/v2/alarm.py | 16 +++- aodhclient/v2/alarm_cli.py | 26 +++++-- 3 files changed, 124 insertions(+), 8 deletions(-) diff --git a/aodhclient/tests/functional/test_alarm.py b/aodhclient/tests/functional/test_alarm.py index 03c3267..33c0ebb 100644 --- a/aodhclient/tests/functional/test_alarm.py +++ b/aodhclient/tests/functional/test_alarm.py @@ -27,7 +27,95 @@ class AodhClientTest(base.ClientTestBase): self.aodh("help", params="alarm show") self.aodh("help", params="alarm update") - def test_alarm_scenario(self): + def test_event_scenario(self): + + PROJECT_ID = str(uuid.uuid4()) + + # CREATE + result = self.aodh(u'alarm', + params=(u"create --type event --name ev_alarm1 " + "--project-id %s" % PROJECT_ID)) + alarm = self.details_multiple(result)[0] + ALARM_ID = alarm['alarm_id'] + self.assertEqual('ev_alarm1', alarm['name']) + self.assertEqual('*', alarm['event_type']) + + # CREATE FAIL + result = self.aodh(u'alarm', + params=(u"create --type event --name ev_alarm1 " + "--project-id %s" % PROJECT_ID), + fail_ok=True, merge_stderr=True) + self.assertEqual(result.strip(), 'Conflict (HTTP 409)') + + # UPDATE IGNORE INVALID + result = self.aodh( + 'alarm', params=("update %s --severity critical --threshold 10" + % ALARM_ID)) + alarm_updated = self.details_multiple(result)[0] + self.assertEqual(ALARM_ID, alarm_updated["alarm_id"]) + self.assertEqual('critical', alarm_updated['severity']) + + # UPDATE IGNORE INVALID + result = self.aodh( + 'alarm', params=("update %s --event-type dummy" % ALARM_ID)) + alarm_updated = self.details_multiple(result)[0] + self.assertEqual(ALARM_ID, alarm_updated["alarm_id"]) + self.assertEqual('dummy', alarm_updated['event_type']) + + # GET + result = self.aodh( + 'alarm', params="show %s" % ALARM_ID) + alarm_show = self.details_multiple(result)[0] + self.assertEqual(ALARM_ID, alarm_show["alarm_id"]) + self.assertEqual(PROJECT_ID, alarm_show["project_id"]) + self.assertEqual('ev_alarm1', alarm_show['name']) + self.assertEqual('dummy', alarm_show['event_type']) + + # LIST + result = self.aodh('alarm', params="list --type event") + self.assertIn(ALARM_ID, + [r['alarm_id'] for r in self.parser.listing(result)]) + for alarm_list in self.parser.listing(result): + if alarm_list["alarm_id"] == ALARM_ID: + self.assertEqual('ev_alarm1', alarm_list['name']) + + # SEARCH ALL + result = self.aodh('alarm', params=("search --type event")) + self.assertIn(ALARM_ID, + [r['alarm_id'] for r in self.parser.listing(result)]) + for alarm_list in self.parser.listing(result): + if alarm_list["alarm_id"] == ALARM_ID: + self.assertEqual('ev_alarm1', alarm_list['name']) + + # SEARCH SOME + result = self.aodh('alarm', + params=("search --type event --query " + "'{\"=\": {\"project_id\": \"%s\"}}'" + % PROJECT_ID)) + alarm_list = self.parser.listing(result)[0] + self.assertEqual(ALARM_ID, alarm_list["alarm_id"]) + self.assertEqual('ev_alarm1', alarm_list['name']) + + # DELETE + result = self.aodh('alarm', params="delete %s" % ALARM_ID) + self.assertEqual("", result) + + # GET FAIL + result = self.aodh('alarm', params="show %s" % ALARM_ID, + fail_ok=True, merge_stderr=True) + self.assertEqual(result.strip(), "Not found (HTTP 404)") + + # DELETE FAIL + result = self.aodh('alarm', params="delete %s" % ALARM_ID, + fail_ok=True, merge_stderr=True) + self.assertEqual(result.strip(), "Not found (HTTP 404)") + + # LIST DOES NOT HAVE ALARM + result = self.aodh('alarm', params="list --type event") + self.assertNotIn(ALARM_ID, + [r['alarm_id'] for r in self.parser.listing(result)]) + + def test_threshold_scenario(self): PROJECT_ID = str(uuid.uuid4()) diff --git a/aodhclient/v2/alarm.py b/aodhclient/v2/alarm.py index 97d2eb4..61315d8 100644 --- a/aodhclient/v2/alarm.py +++ b/aodhclient/v2/alarm.py @@ -13,6 +13,7 @@ from oslo_serialization import jsonutils +from aodhclient.v2.alarm_cli import ALARM_TYPES from aodhclient.v2 import base @@ -33,12 +34,19 @@ class AlarmManager(base.Manager): """ return self._get(self.url + '/' + alarm_id).json() + @staticmethod + def _clean_rules(alarm_type, alarm): + for rule in ALARM_TYPES: + if rule != alarm_type: + alarm.pop('%s_rule' % rule, None) + def create(self, alarm): """Create an alarm :param alarm: the alarm :type alarm: dict """ + self._clean_rules(alarm['type'], alarm) return self._post( self.url, headers={'Content-Type': "application/json"}, data=jsonutils.dumps(alarm)).json() @@ -52,9 +60,15 @@ class AlarmManager(base.Manager): :type attributes: dict """ alarm = self._get(self.url + '/' + alarm_id).json() - if alarm_update.get('threshold_rule'): + self._clean_rules(alarm['type'], alarm_update) + + if 'threshold_rule' in alarm_update: alarm['threshold_rule'].update(alarm_update.get('threshold_rule')) alarm_update.pop('threshold_rule') + elif 'event_rule' in alarm_update: + alarm['event_rule'].update(alarm_update.get('event_rule')) + alarm_update.pop('event_rule') + alarm.update(alarm_update) return self._put( self.url + '/' + alarm_id, diff --git a/aodhclient/v2/alarm_cli.py b/aodhclient/v2/alarm_cli.py index 27dbc2d..5831dee 100644 --- a/aodhclient/v2/alarm_cli.py +++ b/aodhclient/v2/alarm_cli.py @@ -17,7 +17,7 @@ from oslo_utils import strutils from aodhclient import utils -ALARM_TYPES = ['threshold'] +ALARM_TYPES = ['threshold', 'event'] ALARM_STATES = ['ok', 'alarm', 'insufficient data'] ALARM_SEVERITY = ['low', 'moderate', 'critical'] ALARM_OPERATORS = ['lt', 'le', 'eq', 'ne', 'ge', 'gt'] @@ -33,6 +33,8 @@ class CliAlarmList(lister.Lister): 'repeat_actions', 'time_constraints'] if alarm_type == 'threshold': cols.append('threshold_rule') + elif alarm_type == 'event': + cols.append('event_rule') return cols def get_parser(self, prog_name): @@ -65,7 +67,9 @@ class CliAlarmSearch(CliAlarmList): def _format_alarm(alarm): - alarm.update(alarm.pop('threshold_rule')) + for alarm_type in ALARM_TYPES: + if alarm.get('%s_rule' % alarm_type): + alarm.update(alarm.pop('%s_rule' % alarm_type)) return alarm @@ -146,6 +150,13 @@ class CliAlarmCreate(show.ShowOne): 'notified while alarm remains in target ' 'state')) + common_group = parser.add_argument_group('common alarm rules') + common_group.add_argument( + '-q', '--query', metavar='', dest='query', + help='key[op]data_type::value; list. data_type is optional, ' + 'but if supplied must be string, integer, float, or boolean. ' + 'Used by threshold and event alarms') + threshold_group = parser.add_argument_group('threshold alarm') threshold_group.add_argument( '-m', '--meter-name', metavar='', @@ -168,10 +179,11 @@ class CliAlarmCreate(show.ShowOne): '--comparison-operator', metavar='', dest='comparison_operator', choices=ALARM_OPERATORS, help='Operator to compare with, one of: ' + str(ALARM_OPERATORS)) - threshold_group.add_argument( - '-q', '--query', metavar='', dest='query', - help='key[op]data_type::value; list. data_type is optional, ' - 'but if supplied must be string, integer, float, or boolean.') + + event_group = parser.add_argument_group('event alarm') + event_group.add_argument( + '--event-type', metavar='', + dest='event_type', help='Event type to evaluate against') self.parser = parser return parser @@ -192,6 +204,8 @@ class CliAlarmCreate(show.ShowOne): parsed_args, ['meter_name', 'period', 'evaluation_periods', 'statistic', 'comparison_operator', 'threshold', 'query']) + alarm['event_rule'] = utils.dict_from_parsed_args( + parsed_args, ['event_type', 'query']) if self.create: alarm['type'] = parsed_args.type self._validate_args(parsed_args)