remove threshold alarms

ceilometer-api is gone. NOTE: CEILOMETER IS NOT GONE. JUST THE API.
use gnocchi or something else for storage if required.

Change-Id: Ie37eaaa0abd8b0cf530895bcedd55c9370d3e558
This commit is contained in:
gord chung 2018-01-30 21:31:13 +00:00
parent b98d471260
commit 86ac8fd3d3
9 changed files with 138 additions and 277 deletions

View File

@ -184,171 +184,27 @@ class AodhClientTest(base.ClientTestBase):
self.assertNotIn(ALARM_ID, self.assertNotIn(ALARM_ID,
[r['alarm_id'] for r in self.parser.listing(result)]) [r['alarm_id'] for r in self.parser.listing(result)])
def test_threshold_scenario(self):
PROJECT_ID = uuidutils.generate_uuid()
# CREATE
result = self.aodh(u'alarm',
params=(u"create --type threshold --name alarm_th "
"-m meter_name --threshold 5 "
"--project-id %s" % PROJECT_ID))
alarm = self.details_multiple(result)[0]
ALARM_ID = alarm['alarm_id']
self.assertEqual('alarm_th', alarm['name'])
self.assertEqual('meter_name', alarm['meter_name'])
self.assertEqual('5.0', alarm['threshold'])
# CREATE WITH --TIME-CONSTRAINT
result = self.aodh(
u'alarm',
params=(u"create --type threshold --name alarm_tc "
"-m meter_name --threshold 5 "
"--time-constraint "
"name=cons1;start='0 11 * * *';duration=300 "
"--time-constraint "
"name=cons2;start='0 23 * * *';duration=600 "
"--project-id %s" % PROJECT_ID))
alarm = self.details_multiple(result)[0]
self.assertEqual('alarm_tc', alarm['name'])
self.assertEqual('meter_name', alarm['meter_name'])
self.assertEqual('5.0', alarm['threshold'])
self.assertIsNotNone(alarm['time_constraints'])
# CREATE FAIL MISSING PARAM
self.assertRaises(exceptions.CommandFailed,
self.aodh, u'alarm',
params=(u"create --type threshold --name alarm_th "
"--project-id %s" % PROJECT_ID))
# UPDATE
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'])
self.assertEqual('10.0', alarm_updated["threshold"])
# 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('alarm_th', alarm_show['name'])
self.assertEqual('meter_name', alarm_show['meter_name'])
self.assertEqual('10.0', alarm_show['threshold'])
# GET BY NAME
result = self.aodh(
'alarm', params="show --name alarm_th")
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('alarm_th', alarm_show['name'])
self.assertEqual('meter_name', alarm_show['meter_name'])
self.assertEqual('10.0', alarm_show['threshold'])
# GET BY NAME AND ID ERROR
self.assertRaises(exceptions.CommandFailed,
self.aodh, u'alarm',
params=(u"show %s --name alarm_th" %
ALARM_ID))
# LIST
result = self.aodh('alarm', params="list")
self.assertIn(ALARM_ID,
[r['alarm_id'] for r in self.parser.listing(result)])
output_colums = ['alarm_id', 'type', 'name', 'state', 'severity',
'enabled']
for alarm_list in self.parser.listing(result):
self.assertEqual(sorted(output_colums), sorted(alarm_list.keys()))
if alarm_list["alarm_id"] == ALARM_ID:
self.assertEqual('alarm_th', alarm_list['name'])
# LIST WITH PAGINATION
# list with limit
result = self.aodh('alarm',
params="list --limit 1")
alarm_list = self.parser.listing(result)
self.assertEqual(1, len(alarm_list))
# list with sort with key=name dir=asc
result = self.aodh('alarm',
params="list --sort name:asc")
names = [r['name'] for r in self.parser.listing(result)]
sorted_name = sorted(names)
self.assertEqual(sorted_name, names)
# list with sort with key=name dir=asc and key=alarm_id dir=asc
result = self.aodh(u'alarm',
params=(u"create --type threshold --name alarm_th "
"-m meter_name --threshold 5 "
"--project-id %s" % PROJECT_ID))
created_alarm_id = self.details_multiple(result)[0]['alarm_id']
result = self.aodh('alarm',
params="list --sort name:asc --sort alarm_id:asc")
alarm_list = self.parser.listing(result)
ids_with_same_name = []
names = []
for alarm in alarm_list:
names.append(['alarm_name'])
if alarm['name'] == 'alarm_th':
ids_with_same_name.append(alarm['alarm_id'])
sorted_ids = sorted(ids_with_same_name)
sorted_names = sorted(names)
self.assertEqual(sorted_names, names)
self.assertEqual(sorted_ids, ids_with_same_name)
# list with sort with key=name dir=desc and with the marker equal to
# the alarm_id of the alarm_th we created for this test.
result = self.aodh('alarm',
params="list --sort name:desc "
"--marker %s" % created_alarm_id)
self.assertIn('alarm_tc',
[r['name'] for r in self.parser.listing(result)])
self.aodh('alarm', params="delete %s" % created_alarm_id)
# LIST WITH QUERY
result = self.aodh('alarm',
params=("list --query project_id=%s" % PROJECT_ID))
alarm_list = self.parser.listing(result)[0]
self.assertEqual(ALARM_ID, alarm_list["alarm_id"])
self.assertEqual('alarm_th', 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)
expected = "Alarm %s not found (HTTP 404)" % ALARM_ID
self.assertFirstLineStartsWith(result.splitlines(), expected)
# DELETE FAIL
result = self.aodh('alarm', params="delete %s" % ALARM_ID,
fail_ok=True, merge_stderr=True)
self.assertFirstLineStartsWith(result.splitlines(), expected)
# LIST DOES NOT HAVE ALARM
result = self.aodh('alarm', params="list")
self.assertNotIn(ALARM_ID,
[r['alarm_id'] for r in self.parser.listing(result)])
def test_composite_scenario(self): def test_composite_scenario(self):
project_id = uuidutils.generate_uuid() project_id = uuidutils.generate_uuid()
res_id = uuidutils.generate_uuid()
# CREATE # CREATE
result = self.aodh(u'alarm', result = self.aodh(
params=(u'create --type composite --name calarm1 ' u'alarm',
' --composite-rule \'{"or":[{"threshold"' params=(u'create --type composite --name calarm1 --composite-rule '
': 0.8,"meter_name": "cpu_util",' '\'{"or":[{"threshold": 0.8, "metric": "cpu_util", '
'"type": "threshold"},{"and": [' '"type": "gnocchi_resources_threshold", "resource_type": '
'{"threshold": 200, "meter_name": ' '"generic", "resource_id": "%s", '
'"disk.iops", "type": "threshold"},' '"aggregation_method": "mean"},'
'{"threshold": 1000,"meter_name":' '{"and": [{"threshold": 200, "metric": "disk.iops", '
'"network.incoming.packets.rate",' '"type": "gnocchi_resources_threshold", "resource_type": '
'"type": "threshold"}]}]}\' ' '"generic", "resource_id": "%s", '
'--project-id %s' % project_id)) '"aggregation_method": "mean"},'
'{"threshold": 1000, "metric": "memory",'
'"type": "gnocchi_resources_threshold", "resource_type": '
'"generic", "resource_id": "%s", '
'"aggregation_method": "mean"}]}]}\' --project-id %s' %
(res_id, res_id, res_id, project_id)))
alarm = self.details_multiple(result)[0] alarm = self.details_multiple(result)[0]
alarm_id = alarm['alarm_id'] alarm_id = alarm['alarm_id']
self.assertEqual('calarm1', alarm['name']) self.assertEqual('calarm1', alarm['name'])
@ -442,25 +298,6 @@ class AodhClientTest(base.ClientTestBase):
test(params) test(params)
self.aodh('alarm', params='delete %s' % alarm['alarm_id']) self.aodh('alarm', params='delete %s' % alarm['alarm_id'])
def test_threshold_alarm_create_show_query(self):
params = ('create --type threshold --name alarm-multiple-query '
'-m cpu_util --threshold 90 --query "project_id=123;'
'resource_id=456"')
expected_lines = {
'query': 'project_id = 123 AND',
'': 'resource_id = 456'
}
self._test_alarm_create_show_query(params, expected_lines)
params = ('create --type threshold --name alarm-single-query '
'-m cpu_util --threshold 90 --query project_id=123')
expected_lines = {'query': 'project_id = 123'}
self._test_alarm_create_show_query(params, expected_lines)
params = ('create --type threshold --name alarm-no-query '
'-m cpu_util --threshold 90')
self._test_alarm_create_show_query(params, {'query': ''})
def test_event_alarm_create_show_query(self): def test_event_alarm_create_show_query(self):
params = ('create --type event --name alarm-multiple-query ' params = ('create --type event --name alarm-multiple-query '
'--query "traits.project_id=789;traits.resource_id=012"') '--query "traits.project_id=789;traits.resource_id=012"')
@ -481,8 +318,8 @@ class AodhClientTest(base.ClientTestBase):
def test_set_get_alarm_state(self): def test_set_get_alarm_state(self):
result = self.aodh( result = self.aodh(
'alarm', 'alarm',
params=("create --type threshold --name alarm_state_test " params=('create --type event --name alarm_state_test '
"-m meter_name --threshold 5")) '--query "traits.project_id=789;traits.resource_id=012"'))
alarm = self.details_multiple(result)[0] alarm = self.details_multiple(result)[0]
alarm_id = alarm['alarm_id'] alarm_id = alarm['alarm_id']
result = self.aodh( result = self.aodh(
@ -535,6 +372,23 @@ class AodhClientGnocchiRulesTest(base.ClientTestBase):
alarm['resource_id']) alarm['resource_id'])
self.assertEqual('generic', alarm['resource_type']) self.assertEqual('generic', alarm['resource_type'])
# CREATE WITH --TIME-CONSTRAINT
result = self.aodh(
u'alarm',
params=(u"create --type gnocchi_resources_threshold "
"--name alarm_tc --metric cpu_util --threshold 80 "
"--resource-id %s --resource-type generic "
"--aggregation-method last --project-id %s "
"--time-constraint "
"name=cons1;start='0 11 * * *';duration=300 "
"--time-constraint "
"name=cons2;start='0 23 * * *';duration=600 "
% (RESOURCE_ID, PROJECT_ID)))
alarm = self.details_multiple(result)[0]
self.assertEqual('alarm_tc', alarm['name'])
self.assertEqual('80.0', alarm['threshold'])
self.assertIsNotNone(alarm['time_constraints'])
# CREATE FAIL MISSING PARAM # CREATE FAIL MISSING PARAM
self.assertRaises(exceptions.CommandFailed, self.assertRaises(exceptions.CommandFailed,
self.aodh, u'alarm', self.aodh, u'alarm',
@ -597,6 +451,49 @@ class AodhClientGnocchiRulesTest(base.ClientTestBase):
if alarm_list["alarm_id"] == ALARM_ID: if alarm_list["alarm_id"] == ALARM_ID:
self.assertEqual('alarm_gn1', alarm_list['name']) self.assertEqual('alarm_gn1', alarm_list['name'])
# LIST WITH PAGINATION
# list with limit
result = self.aodh('alarm',
params="list --limit 1")
alarm_list = self.parser.listing(result)
self.assertEqual(1, len(alarm_list))
# list with sort with key=name dir=asc
result = self.aodh('alarm',
params="list --sort name:asc")
names = [r['name'] for r in self.parser.listing(result)]
sorted_name = sorted(names)
self.assertEqual(sorted_name, names)
# list with sort with key=name dir=asc and key=alarm_id dir=asc
result = self.aodh(
u'alarm',
params=(u"create --type gnocchi_resources_threshold "
"--name alarm_th --metric cpu_util --threshold 80 "
"--resource-id %s --resource-type generic "
"--aggregation-method last --project-id %s "
% (RESOURCE_ID, PROJECT_ID)))
created_alarm_id = self.details_multiple(result)[0]['alarm_id']
result = self.aodh('alarm',
params="list --sort name:asc --sort alarm_id:asc")
alarm_list = self.parser.listing(result)
ids_with_same_name = []
names = []
for alarm in alarm_list:
names.append(['alarm_name'])
if alarm['name'] == 'alarm_th':
ids_with_same_name.append(alarm['alarm_id'])
sorted_ids = sorted(ids_with_same_name)
sorted_names = sorted(names)
self.assertEqual(sorted_names, names)
self.assertEqual(sorted_ids, ids_with_same_name)
# list with sort with key=name dir=desc and with the marker equal to
# the alarm_id of the alarm_th we created for this test.
result = self.aodh('alarm',
params="list --sort name:desc "
"--marker %s" % created_alarm_id)
self.assertIn('alarm_tc',
[r['name'] for r in self.parser.listing(result)])
self.aodh('alarm', params="delete %s" % created_alarm_id)
# LIST WITH QUERY # LIST WITH QUERY
result = self.aodh('alarm', result = self.aodh('alarm',
params=("list --query project_id=%s" % PROJECT_ID)) params=("list --query project_id=%s" % PROJECT_ID))

View File

@ -25,17 +25,28 @@ class AlarmHistoryTest(base.ClientTestBase):
def test_alarm_history_scenario(self): def test_alarm_history_scenario(self):
PROJECT_ID = uuidutils.generate_uuid() PROJECT_ID = uuidutils.generate_uuid()
RESOURCE_ID = uuidutils.generate_uuid()
result = self.aodh(u'alarm', result = self.aodh(u'alarm',
params=(u"create --type threshold --name history1 " params=(u"create "
"-m meter_name --threshold 5 " "--type gnocchi_resources_threshold "
"--project-id %s" % PROJECT_ID)) "--name history1 --metric cpu_util "
"--threshold 5 "
"--resource-id %s --resource-type generic "
"--aggregation-method last "
"--project-id %s"
% (RESOURCE_ID, PROJECT_ID)))
alarm = self.details_multiple(result)[0] alarm = self.details_multiple(result)[0]
ALARM_ID = alarm['alarm_id'] ALARM_ID = alarm['alarm_id']
result = self.aodh(u'alarm', result = self.aodh(u'alarm',
params=(u"create --type threshold --name history2 " params=(u"create "
"-m meter_name --threshold 10 " "--type gnocchi_resources_threshold "
"--project-id %s" % PROJECT_ID)) "--name history2 --metric cpu_util "
"--threshold 10 "
"--resource-id %s --resource-type generic "
"--aggregation-method last "
"--project-id %s"
% (RESOURCE_ID, PROJECT_ID)))
alarm = self.details_multiple(result)[0] alarm = self.details_multiple(result)[0]
ALARM_ID2 = alarm['alarm_id'] ALARM_ID2 = alarm['alarm_id']

View File

@ -49,22 +49,6 @@ class CliAlarmCreateTest(testtools.TestCase):
'--threshold, --resource-id, --resource-type and ' '--threshold, --resource-id, --resource-type and '
'--aggregation-method') '--aggregation-method')
@mock.patch.object(argparse.ArgumentParser, 'error')
def test_validate_args_threshold(self, mock_arg):
# Cover the test case of the method _validate_args for
# threshold
parser = self.cli_alarm_create.get_parser('aodh alarm create')
test_parsed_args = parser.parse_args([
'--name', 'threshold_test',
'--type', 'threshold',
'--threshold', '80'
])
self.cli_alarm_create._validate_args(test_parsed_args)
mock_arg.assert_called_once_with(
'Threshold alarm requires -m/--meter-name and '
'--threshold parameters. Meter name can be '
'found in Ceilometer')
@mock.patch.object(argparse.ArgumentParser, 'error') @mock.patch.object(argparse.ArgumentParser, 'error')
def test_validate_args_composite(self, mock_arg): def test_validate_args_composite(self, mock_arg):
# Cover the test case of the method _validate_args for # Cover the test case of the method _validate_args for
@ -117,7 +101,7 @@ class CliAlarmCreateTest(testtools.TestCase):
# The test case to cover the method _alarm_from_args # The test case to cover the method _alarm_from_args
parser = self.cli_alarm_create.get_parser('aodh alarm create') parser = self.cli_alarm_create.get_parser('aodh alarm create')
test_parsed_args = parser.parse_args([ test_parsed_args = parser.parse_args([
'--type', 'threshold', '--type', 'event',
'--name', 'alarm_from_args_test', '--name', 'alarm_from_args_test',
'--project-id', '01919bbd-8b0e-451c-be28-abe250ae9b1b', '--project-id', '01919bbd-8b0e-451c-be28-abe250ae9b1b',
'--user-id', '01919bbd-8b0e-451c-be28-abe250ae9c1c', '--user-id', '01919bbd-8b0e-451c-be28-abe250ae9c1c',
@ -132,10 +116,7 @@ class CliAlarmCreateTest(testtools.TestCase):
'http://something/insufficient', 'http://something/insufficient',
'--time-constraint', '--time-constraint',
'name=cons1;start="0 11 * * *";duration=300;description=desc1', 'name=cons1;start="0 11 * * *";duration=300;description=desc1',
'--meter-name', 'cpu',
'--period', '60',
'--evaluation-periods', '60', '--evaluation-periods', '60',
'--statistic', 'max',
'--comparison-operator', 'le', '--comparison-operator', 'le',
'--threshold', '80', '--threshold', '80',
'--event-type', 'event', '--event-type', 'event',
@ -165,18 +146,6 @@ class CliAlarmCreateTest(testtools.TestCase):
'name': 'cons1', 'name': 'cons1',
'start': '0 11 * * *'}], 'start': '0 11 * * *'}],
'repeat_actions': True, 'repeat_actions': True,
'threshold_rule': {
'meter_name': 'cpu',
'period': 60,
'evaluation_periods': 60,
'statistic': 'max',
'comparison_operator': 'le',
'threshold': 80.0,
'query': [{'field': 'resource',
'op': 'eq',
'type': '',
'value': 'fake-resource-id'}]
},
'event_rule': { 'event_rule': {
'event_type': 'event', 'event_type': 'event',
'query': [{'field': 'resource', 'query': [{'field': 'resource',
@ -215,7 +184,7 @@ class CliAlarmCreateTest(testtools.TestCase):
'resource_type': 'generic' 'resource_type': 'generic'
}, },
'composite_rule': None, 'composite_rule': None,
'type': 'threshold' 'type': 'event'
} }
alarm_rep = self.cli_alarm_create._alarm_from_args(test_parsed_args) alarm_rep = self.cli_alarm_create._alarm_from_args(test_parsed_args)
self.assertEqual(alarm, alarm_rep) self.assertEqual(alarm, alarm_rep)

View File

@ -37,13 +37,14 @@ class AlarmHistoryManagerTest(testtools.TestCase):
@mock.patch.object(alarm_history.AlarmHistoryManager, '_post') @mock.patch.object(alarm_history.AlarmHistoryManager, '_post')
def test_search(self, mock_ahm): def test_search(self, mock_ahm):
ahm = alarm_history.AlarmHistoryManager(self.client) ahm = alarm_history.AlarmHistoryManager(self.client)
q = ('{"and": [{"=": {"type": "threshold"}}, ' q = ('{"and": [{"=": {"type": "gnocchi_resources_threshold"}}, '
'{"=": {"alarm_id": "87bacbcb-a09c-4cb9-86d0-ad410dd8ad98"}}]}') '{"=": {"alarm_id": "87bacbcb-a09c-4cb9-86d0-ad410dd8ad98"}}]}')
ahm.search(q) ahm.search(q)
expected_called_data = ('{"filter": "{\\"and\\": [{\\"=\\": ' expected_called_data = (
'{\\"type\\": \\"threshold\\"}}, ' '{"filter": "{\\"and\\": ['
'{\\"=\\": {\\"alarm_id\\": \\"87bacbcb-' '{\\"=\\": {\\"type\\": \\"gnocchi_resources_threshold\\"}}, '
'a09c-4cb9-86d0-ad410dd8ad98\\"}}]}"}') '{\\"=\\": {\\"alarm_id\\": '
'\\"87bacbcb-a09c-4cb9-86d0-ad410dd8ad98\\"}}]}"}')
mock_ahm.assert_called_with( mock_ahm.assert_called_with(
'v2/query/alarms/history', 'v2/query/alarms/history',
data=expected_called_data, data=expected_called_data,

View File

@ -29,7 +29,6 @@ class AlarmManagerTest(testtools.TestCase):
'gnocchi_aggregation_by_metrics_threshold_rule': {}, 'gnocchi_aggregation_by_metrics_threshold_rule': {},
'gnocchi_resources_threshold_rule': {}, 'gnocchi_resources_threshold_rule': {},
'name': 'event_alarm', 'name': 'event_alarm',
'threshold_rule': {},
'gnocchi_aggregation_by_resources_threshold_rule': {}, 'gnocchi_aggregation_by_resources_threshold_rule': {},
'event_rule': {}, 'event_rule': {},
'type': 'event'} 'type': 'event'}
@ -63,10 +62,11 @@ class AlarmManagerTest(testtools.TestCase):
@mock.patch.object(alarm.AlarmManager, '_get') @mock.patch.object(alarm.AlarmManager, '_get')
def test_list_with_filters(self, mock_am): def test_list_with_filters(self, mock_am):
am = alarm.AlarmManager(self.client) am = alarm.AlarmManager(self.client)
filters = dict(type='threshold', severity='low') filters = dict(type='gnocchi_resources_threshold', severity='low')
am.list(filters=filters) am.list(filters=filters)
expected_url = ("v2/alarms?q.field=severity&q.op=eq&q.value=low&" expected_url = (
"q.field=type&q.op=eq&q.value=threshold") "v2/alarms?q.field=severity&q.op=eq&q.value=low&"
"q.field=type&q.op=eq&q.value=gnocchi_resources_threshold")
mock_am.assert_called_with(expected_url) mock_am.assert_called_with(expected_url)
@mock.patch.object(alarm.AlarmManager, '_get') @mock.patch.object(alarm.AlarmManager, '_get')

View File

@ -35,8 +35,9 @@ class AlarmManager(base.Manager):
"""List alarms. """List alarms.
:param filters: A dict includes filters parameters, for example, :param filters: A dict includes filters parameters, for example,
{'type': 'threshold', 'severity': 'low'} represent {'type': 'gnocchi_resources_threshold',
filters to query alarms with type='threshold' and 'severity': 'low'} represent filters to query alarms
with type='gnocchi_resources_threshold' and
severity='low'. severity='low'.
:type filters: dict :type filters: dict
:param limit: maximum number of resources to return :param limit: maximum number of resources to return
@ -64,8 +65,9 @@ class AlarmManager(base.Manager):
"""Query alarms. """Query alarms.
:param query: A json format complex query expression, like this: :param query: A json format complex query expression, like this:
'{"=":{"type":"threshold"}}', this expression is used to '{"=":{"type":"gnocchi_resources_threshold"}}', this
query all the threshold type alarms. expression is used to query all the
gnocchi_resources_threshold type alarms.
:type query: json :type query: json
""" """
query = {'filter': query} query = {'filter': query}
@ -110,10 +112,7 @@ class AlarmManager(base.Manager):
alarm = self._get(self.url + '/' + alarm_id).json() alarm = self._get(self.url + '/' + alarm_id).json()
self._clean_rules(alarm['type'], alarm_update) self._clean_rules(alarm['type'], alarm_update)
if 'threshold_rule' in alarm_update: if 'event_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['event_rule'].update(alarm_update.get('event_rule'))
alarm_update.pop('event_rule') alarm_update.pop('event_rule')
elif 'gnocchi_resources_threshold_rule' in alarm_update: elif 'gnocchi_resources_threshold_rule' in alarm_update:

View File

@ -24,7 +24,7 @@ from aodhclient import exceptions
from aodhclient.i18n import _ from aodhclient.i18n import _
from aodhclient import utils from aodhclient import utils
ALARM_TYPES = ['threshold', 'event', 'composite', ALARM_TYPES = ['event', 'composite',
'gnocchi_resources_threshold', 'gnocchi_resources_threshold',
'gnocchi_aggregation_by_metrics_threshold', 'gnocchi_aggregation_by_metrics_threshold',
'gnocchi_aggregation_by_resources_threshold'] 'gnocchi_aggregation_by_resources_threshold']
@ -32,7 +32,6 @@ ALARM_STATES = ['ok', 'alarm', 'insufficient data']
ALARM_SEVERITY = ['low', 'moderate', 'critical'] ALARM_SEVERITY = ['low', 'moderate', 'critical']
ALARM_OPERATORS = ['lt', 'le', 'eq', 'ne', 'ge', 'gt'] ALARM_OPERATORS = ['lt', 'le', 'eq', 'ne', 'ge', 'gt']
ALARM_OP_MAP = dict(zip(ALARM_OPERATORS, ('<', '<=', '=', '!=', '>=', '>'))) ALARM_OP_MAP = dict(zip(ALARM_OPERATORS, ('<', '<=', '=', '!=', '>=', '>')))
STATISTICS = ['max', 'min', 'avg', 'sum', 'count']
ALARM_LIST_COLS = ['alarm_id', 'type', 'name', 'state', 'severity', 'enabled'] ALARM_LIST_COLS = ['alarm_id', 'type', 'name', 'state', 'severity', 'enabled']
@ -103,7 +102,7 @@ def _format_alarm(alarm):
alarm["time_constraints"] = jsonutils.dumps(alarm["time_constraints"], alarm["time_constraints"] = jsonutils.dumps(alarm["time_constraints"],
sort_keys=True, sort_keys=True,
indent=2) indent=2)
# only works for threshold and event alarm # only works for event alarm
if isinstance(alarm.get('query'), list): if isinstance(alarm.get('query'), list):
query_rows = [] query_rows = []
for q in alarm['query']: for q in alarm['query']:
@ -265,7 +264,7 @@ class CliAlarmCreate(show.ShowOne):
common_group = parser.add_argument_group('common alarm rules') common_group = parser.add_argument_group('common alarm rules')
common_group.add_argument( common_group.add_argument(
'--query', metavar='<QUERY>', dest='query', '--query', metavar='<QUERY>', dest='query',
help="For alarms of type threshold or event: " help="For alarms of type event: "
"key[op]data_type::value; list. data_type is optional, " "key[op]data_type::value; list. data_type is optional, "
"but if supplied must be string, integer, float, or boolean. " "but if supplied must be string, integer, float, or boolean. "
'For alarms of ' 'For alarms of '
@ -287,20 +286,6 @@ class CliAlarmCreate(show.ShowOne):
'--metric', metavar='<METRIC>', '--metric', metavar='<METRIC>',
dest='metric', help='Metric to evaluate against.') dest='metric', help='Metric to evaluate against.')
threshold_group = parser.add_argument_group('threshold alarm')
threshold_group.add_argument(
'-m', '--meter-name', metavar='<METER NAME>',
dest='meter_name', help='Meter to evaluate against')
threshold_group.add_argument(
'--period', type=int, metavar='<PERIOD>', dest='period',
help='Length of each period (seconds) to evaluate over.')
threshold_group.add_argument(
'--statistic', metavar='<STATISTIC>', dest='statistic',
choices=STATISTICS,
help='Statistic to evaluate, one of: ' + str(STATISTICS))
event_group = parser.add_argument_group('event alarm') event_group = parser.add_argument_group('event alarm')
event_group.add_argument( event_group.add_argument(
'--event-type', metavar='<EVENT_TYPE>', '--event-type', metavar='<EVENT_TYPE>',
@ -337,12 +322,9 @@ class CliAlarmCreate(show.ShowOne):
dest='composite_rule', dest='composite_rule',
type=jsonutils.loads, type=jsonutils.loads,
help='Composite threshold rule with JSON format, the form can ' help='Composite threshold rule with JSON format, the form can '
'be a nested dict which combine threshold/gnocchi rules by ' 'be a nested dict which combine gnocchi rules by '
'"and", "or". For example, the form is like: ' '"and", "or". For example, the form is like: '
'{"or":[RULE1, RULE2, {"and": [RULE3, RULE4]}]}, The ' '{"or":[RULE1, RULE2, {"and": [RULE3, RULE4]}]}.'
'RULEx can be basic threshold rules but must include a '
'"type" field, like this: {"threshold": 0.8,'
'"meter_name":"cpu_util","type":"threshold"}'
) )
self.parser = parser self.parser = parser
return parser return parser
@ -361,15 +343,10 @@ class CliAlarmCreate(show.ShowOne):
raise argparse.ArgumentTypeError(msg) raise argparse.ArgumentTypeError(msg)
def _validate_args(self, parsed_args): def _validate_args(self, parsed_args):
if (parsed_args.type == 'threshold' and if (parsed_args.type == 'gnocchi_resources_threshold' and
not (parsed_args.meter_name and parsed_args.threshold)): not (parsed_args.metric and parsed_args.threshold and
self.parser.error('Threshold alarm requires -m/--meter-name and ' parsed_args.resource_id and parsed_args.resource_type
'--threshold parameters. Meter name can be ' and parsed_args.aggregation_method)):
'found in Ceilometer')
elif (parsed_args.type == 'gnocchi_resources_threshold' and
not (parsed_args.metric and parsed_args.threshold and
parsed_args.resource_id and parsed_args.resource_type
and parsed_args.aggregation_method)):
self.parser.error('gnocchi_resources_threshold requires --metric, ' self.parser.error('gnocchi_resources_threshold requires --metric, '
'--threshold, --resource-id, --resource-type ' '--threshold, --resource-id, --resource-type '
'and --aggregation-method') 'and --aggregation-method')
@ -398,12 +375,8 @@ class CliAlarmCreate(show.ShowOne):
'state', 'severity', 'enabled', 'alarm_actions', 'state', 'severity', 'enabled', 'alarm_actions',
'ok_actions', 'insufficient_data_actions', 'ok_actions', 'insufficient_data_actions',
'time_constraints', 'repeat_actions']) 'time_constraints', 'repeat_actions'])
if parsed_args.type in ('threshold', 'event') and parsed_args.query: if parsed_args.type == 'event' and parsed_args.query:
parsed_args.query = utils.cli_to_array(parsed_args.query) parsed_args.query = utils.cli_to_array(parsed_args.query)
alarm['threshold_rule'] = utils.dict_from_parsed_args(
parsed_args, ['meter_name', 'period', 'evaluation_periods',
'statistic', 'comparison_operator', 'threshold',
'query'])
alarm['event_rule'] = utils.dict_from_parsed_args( alarm['event_rule'] = utils.dict_from_parsed_args(
parsed_args, ['event_type', 'query']) parsed_args, ['event_type', 'query'])
alarm['gnocchi_resources_threshold_rule'] = ( alarm['gnocchi_resources_threshold_rule'] = (

View File

@ -66,7 +66,9 @@ Examples
Create an alarm:: Create an alarm::
aodh alarm create -t threshold --name alarm1 -m cpu_util --threshold 5 aodh alarm create -t gnocchi_resources_threshold --name alarm1 \
--metric cpu_util --threshold 5 --resource_id <RES_ID> \
--resource_type generic --aggregation_method mean --project-id <PROJ_ID>
List alarms:: List alarms::
@ -74,7 +76,7 @@ List alarms::
List alarm with query parameters:: List alarm with query parameters::
aodh alarm list --query "state=alarm and type=threshold" aodh alarm list --query "state=alarm and type=gnocchi_resources_threshold"
Show an alarm's history:: Show an alarm's history::

View File

@ -0,0 +1,9 @@
---
features:
- |
Ceilometer alarms are no longer supported.
upgrade:
- |
Ceilometer alarms will need to be recreated as alarms that target Gnocchi
as storage is not provided in Ceilometer anymore. You must downgrade client
if you still continue to use Ceilometer storage in older deployments.