From 86134761cd93375b69c5409482a1bd6eb36863cf Mon Sep 17 00:00:00 2001 From: gordon chung Date: Fri, 8 Jan 2016 19:28:52 -0500 Subject: [PATCH] support alarm type param this patch adds --type option. it is required when creating, listing, or searching alarms. it is not an option for delete/update Change-Id: Ib36b15f782e3cbcda5641b316c18da56023f2bf2 --- aodhclient/tests/functional/test_alarm.py | 24 +++++--- aodhclient/v2/alarm.py | 5 +- aodhclient/v2/alarm_cli.py | 74 ++++++++++++++++------- 3 files changed, 71 insertions(+), 32 deletions(-) diff --git a/aodhclient/tests/functional/test_alarm.py b/aodhclient/tests/functional/test_alarm.py index 1b0f12c..03c3267 100644 --- a/aodhclient/tests/functional/test_alarm.py +++ b/aodhclient/tests/functional/test_alarm.py @@ -12,6 +12,8 @@ import uuid +from tempest_lib import exceptions + from aodhclient.tests.functional import base @@ -31,8 +33,8 @@ class AodhClientTest(base.ClientTestBase): # CREATE result = self.aodh(u'alarm', - params=(u"create --name alarm1 -m meter_name " - " --threshold 5 " + params=(u"create --type threshold --name alarm1 " + " -m meter_name --threshold 5 " "--project-id %s" % PROJECT_ID)) alarm = self.details_multiple(result)[0] ALARM_ID = alarm['alarm_id'] @@ -42,12 +44,18 @@ class AodhClientTest(base.ClientTestBase): # CREATE FAIL result = self.aodh(u'alarm', - params=(u"create --name alarm1 -m meter_name " - " --threshold 5 " + params=(u"create --type threshold --name alarm1 " + "-m meter_name --threshold 5 " "--project-id %s" % PROJECT_ID), fail_ok=True, merge_stderr=True) self.assertEqual(result.strip(), 'Conflict (HTTP 409)') + # CREATE FAIL MISSING PARAM + self.assertRaises(exceptions.CommandFailed, + self.aodh, u'alarm', + params=(u"create --type threshold --name alarm1 " + "--project-id %s" % PROJECT_ID)) + # UPDATE result = self.aodh( 'alarm', params=("update %s --severity critical --threshold 10" @@ -68,7 +76,7 @@ class AodhClientTest(base.ClientTestBase): self.assertEqual('10.0', alarm_show['threshold']) # LIST - result = self.aodh('alarm', params="list") + result = self.aodh('alarm', params="list --type threshold") self.assertIn(ALARM_ID, [r['alarm_id'] for r in self.parser.listing(result)]) for alarm_list in self.parser.listing(result): @@ -76,7 +84,7 @@ class AodhClientTest(base.ClientTestBase): self.assertEqual('alarm1', alarm_list['name']) # SEARCH ALL - result = self.aodh('alarm', params=("search")) + result = self.aodh('alarm', params=("search --type threshold")) self.assertIn(ALARM_ID, [r['alarm_id'] for r in self.parser.listing(result)]) for alarm_list in self.parser.listing(result): @@ -85,7 +93,7 @@ class AodhClientTest(base.ClientTestBase): # SEARCH SOME result = self.aodh('alarm', - params=("search --query " + params=("search --type threshold --query " "'{\"=\": {\"project_id\": \"%s\"}}'" % PROJECT_ID)) alarm_list = self.parser.listing(result)[0] @@ -107,6 +115,6 @@ class AodhClientTest(base.ClientTestBase): self.assertEqual(result.strip(), "Not found (HTTP 404)") # LIST DOES NOT HAVE ALARM - result = self.aodh('alarm', params="list") + result = self.aodh('alarm', params="list --type threshold") self.assertNotIn(ALARM_ID, [r['alarm_id'] for r in self.parser.listing(result)]) diff --git a/aodhclient/v2/alarm.py b/aodhclient/v2/alarm.py index 44417e1..97d2eb4 100644 --- a/aodhclient/v2/alarm.py +++ b/aodhclient/v2/alarm.py @@ -20,9 +20,10 @@ class AlarmManager(base.Manager): url = "v2/alarms" - def list(self): + def list(self, alarm_type): """List alarms""" - return self._get(self.url).json() + return self._get(self.url + '?q.field=type&q.op=eq' + + '&q.value=' + alarm_type).json() def get(self, alarm_id): """Get an alarm diff --git a/aodhclient/v2/alarm_cli.py b/aodhclient/v2/alarm_cli.py index 9279a16..27dbc2d 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_STATES = ['ok', 'alarm', 'insufficient data'] ALARM_SEVERITY = ['low', 'moderate', 'critical'] ALARM_OPERATORS = ['lt', 'le', 'eq', 'ne', 'ge', 'gt'] @@ -27,12 +27,23 @@ STATISTICS = ['max', 'min', 'avg', 'sum', 'count'] class CliAlarmList(lister.Lister): """List alarms""" - COLS = ('alarm_id', 'name', 'state', 'severity', 'enabled', - 'repeat_actions', 'threshold_rule', 'time_constraints') + @staticmethod + def get_columns(alarm_type): + cols = ['alarm_id', 'name', 'state', 'severity', 'enabled', + 'repeat_actions', 'time_constraints'] + if alarm_type == 'threshold': + cols.append('threshold_rule') + return cols + + def get_parser(self, prog_name): + parser = super(CliAlarmList, self).get_parser(prog_name) + parser.add_argument('-t', '--type', required=True, + help='Type of alarm') + return parser def take_action(self, parsed_args): - alarms = self.app.client.alarm.list() - return utils.list2cols(self.COLS, alarms) + alarms = self.app.client.alarm.list(alarm_type=parsed_args.type) + return utils.list2cols(self.get_columns(parsed_args.type), alarms) class CliAlarmSearch(CliAlarmList): @@ -44,8 +55,13 @@ class CliAlarmSearch(CliAlarmList): return parser def take_action(self, parsed_args): - alarms = self.app.client.alarm.search(query=parsed_args.query) - return utils.list2cols(self.COLS, alarms) + type_query = '{"=": {"type": "%s"}}' % parsed_args.type + if parsed_args.query: + query = '{"and": [%s, %s]}' % (type_query, parsed_args.query) + else: + query = type_query + alarms = self.app.client.alarm.search(query=query) + return utils.list2cols(self.get_columns(parsed_args.type), alarms) def _format_alarm(alarm): @@ -73,6 +89,9 @@ class CliAlarmCreate(show.ShowOne): def get_parser(self, prog_name): parser = super(CliAlarmCreate, self).get_parser(prog_name) + parser.add_argument('-t', '--type', metavar='', + required=self.create, + choices=ALARM_TYPES, help='Type of alarm') parser.add_argument('--name', metavar='', required=self.create, help='Name of the alarm') parser.add_argument('--project-id', metavar='', @@ -84,15 +103,16 @@ class CliAlarmCreate(show.ShowOne): parser.add_argument('--description', metavar='', help='Free text description of the alarm') parser.add_argument('--state', metavar='', + choices=ALARM_STATES, help='State of the alarm, one of: ' + str(ALARM_STATES)) parser.add_argument('--severity', metavar='', + choices=ALARM_SEVERITY, help='Severity of the alarm, one of: ' + str(ALARM_SEVERITY)) parser.add_argument('--enabled', type=strutils.bool_from_string, metavar='{True|False}', - help=('True if alarm evaluation/actioning is ' - 'enabled')) + help=('True if alarm evaluation is enabled')) parser.add_argument('--alarm-action', dest='alarm_actions', metavar='', action='append', help=('URL to invoke when state transitions to ' @@ -125,34 +145,43 @@ class CliAlarmCreate(show.ShowOne): help=('True if actions should be repeatedly ' 'notified while alarm remains in target ' 'state')) - parser.add_argument( - '-m', '--meter-name', metavar='', required=self.create, + + threshold_group = parser.add_argument_group('threshold alarm') + threshold_group.add_argument( + '-m', '--meter-name', metavar='', dest='meter_name', help='Metric to evaluate against') - parser.add_argument( + threshold_group.add_argument( + '--threshold', type=float, metavar='', + dest='threshold', help='Threshold to evaluate against.') + threshold_group.add_argument( '--period', type=int, metavar='', dest='period', help='Length of each period (seconds) to evaluate over.') - parser.add_argument( + threshold_group.add_argument( '--evaluation-periods', type=int, metavar='', dest='evaluation_periods', help='Number of periods to evaluate over') - parser.add_argument( + threshold_group.add_argument( '--statistic', metavar='', dest='statistic', + choices=STATISTICS, help='Statistic to evaluate, one of: ' + str(STATISTICS)) - parser.add_argument( + threshold_group.add_argument( '--comparison-operator', metavar='', - dest='comparison_operator', + dest='comparison_operator', choices=ALARM_OPERATORS, help='Operator to compare with, one of: ' + str(ALARM_OPERATORS)) - parser.add_argument( - '--threshold', type=float, metavar='', - required=self.create, dest='threshold', - help='Threshold to evaluate against.') - parser.add_argument( + 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.') + self.parser = parser return parser + def _validate_args(self, parsed_args): + if (parsed_args.type == 'threshold' and + not (parsed_args.meter_name and parsed_args.threshold)): + self.parser.error('threshold requires --meter-name and ' + '--threshold') + def _alarm_from_args(self, parsed_args): alarm = utils.dict_from_parsed_args( parsed_args, ['name', 'project_id', 'user_id', 'description', @@ -164,7 +193,8 @@ class CliAlarmCreate(show.ShowOne): 'statistic', 'comparison_operator', 'threshold', 'query']) if self.create: - alarm['type'] = 'threshold' + alarm['type'] = parsed_args.type + self._validate_args(parsed_args) return alarm def take_action(self, parsed_args):