Add composite rule alarm support in aodhclient
Add support of composite alarm feature in client side. blueprint composite-threshold-rule-alarm Change-Id: Ic26c6269ae90ae67a04719999c52e55e8d65f9cc
This commit is contained in:
@@ -219,6 +219,112 @@ class AodhClientTest(base.ClientTestBase):
|
||||
self.assertNotIn(ALARM_ID,
|
||||
[r['alarm_id'] for r in self.parser.listing(result)])
|
||||
|
||||
def test_composite_scenario(self):
|
||||
|
||||
project_id = str(uuid.uuid4())
|
||||
# CREATE
|
||||
result = self.aodh(u'alarm',
|
||||
params=(u"create --type composite --name calarm1 "
|
||||
" --composite-rule '{\"or\":[{\"threshold\""
|
||||
": 0.8,\"meter_name\": \"cpu_util\","
|
||||
"\"type\": \"threshold\"},{\"and\": ["
|
||||
"{\"threshold\": 200, \"meter_name\": "
|
||||
"\"disk.iops\", \"type\": \"threshold\"},"
|
||||
"{\"threshold\": 1000,\"meter_name\":"
|
||||
"\"network.incoming.packets.rate\","
|
||||
"\"type\": \"threshold\"}]}]}' "
|
||||
"--project-id %s" % project_id))
|
||||
alarm = self.details_multiple(result)[0]
|
||||
alarm_id = alarm['alarm_id']
|
||||
self.assertEqual('calarm1', alarm['name'])
|
||||
self.assertEqual('composite', alarm['type'])
|
||||
self.assertIn('composite_rule', alarm)
|
||||
|
||||
# CREATE FAIL
|
||||
result = self.aodh(u'alarm',
|
||||
params=(u"create --type composite --name calarm1 "
|
||||
" --composite-rule '{\"or\":[{\"threshold\""
|
||||
": 0.8,\"meter_name\": \"cpu_util\","
|
||||
"\"type\": \"threshold\"},{\"and\": ["
|
||||
"{\"threshold\": 200, \"meter_name\": "
|
||||
"\"disk.iops\", \"type\": \"threshold\"},"
|
||||
"{\"threshold\": 1000,\"meter_name\":"
|
||||
"\"network.incoming.packets.rate\","
|
||||
"\"type\": \"threshold\"}]}]}' "
|
||||
"--project-id %s" % project_id),
|
||||
fail_ok=True, merge_stderr=True)
|
||||
self.assertFirstLineStartsWith(
|
||||
result.split('\n'), "Alarm with name='calarm1' exists (HTTP 409)")
|
||||
|
||||
# CREATE FAIL MISSING PARAM
|
||||
self.assertRaises(exceptions.CommandFailed,
|
||||
self.aodh, u'alarm',
|
||||
params=(u"create --type composite --name calarm1 "
|
||||
"--project-id %s" % project_id))
|
||||
|
||||
# UPDATE
|
||||
result = self.aodh(
|
||||
'alarm', params=("update %s --severity critical" % alarm_id))
|
||||
alarm_updated = self.details_multiple(result)[0]
|
||||
self.assertEqual(alarm_id, alarm_updated["alarm_id"])
|
||||
self.assertEqual('critical', alarm_updated['severity'])
|
||||
|
||||
# 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('calarm1', alarm_show['name'])
|
||||
|
||||
# LIST
|
||||
result = self.aodh('alarm', params="list --type composite")
|
||||
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('calarm1', alarm_list['name'])
|
||||
|
||||
# SEARCH ALL
|
||||
result = self.aodh('alarm', params="search --type composite")
|
||||
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('calarm1', alarm_list['name'])
|
||||
|
||||
# SEARCH SOME
|
||||
result = self.aodh('alarm',
|
||||
params=("search --type composite --query "
|
||||
"'{\"=\": {\"project_id\": \"%s\"}}'"
|
||||
% project_id))
|
||||
alarm_list = self.parser.listing(result)[0]
|
||||
self.assertEqual(alarm_id, alarm_list["alarm_id"])
|
||||
self.assertEqual('calarm1', 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.split('\n'), expected)
|
||||
|
||||
# DELETE FAIL
|
||||
result = self.aodh('alarm', params="delete %s" % alarm_id,
|
||||
fail_ok=True, merge_stderr=True)
|
||||
self.assertFirstLineStartsWith(result.split('\n'), expected)
|
||||
|
||||
# LIST DOES NOT HAVE ALARM
|
||||
result = self.aodh('alarm', params="list --type composite")
|
||||
self.assertNotIn(alarm_id,
|
||||
[r['alarm_id'] for r in self.parser.listing(result)])
|
||||
|
||||
|
||||
class AodhClientGnocchiRulesTest(base.ClientTestBase):
|
||||
|
||||
|
||||
@@ -189,6 +189,7 @@ class CliAlarmCreateTest(testtools.TestCase):
|
||||
'query': '{}',
|
||||
'resource_type': 'generic'
|
||||
},
|
||||
'composite_rule': None,
|
||||
'type': 'threshold'
|
||||
}
|
||||
alarm_rep = self.cli_alarm_create._alarm_from_args(test_parsed_args)
|
||||
|
||||
@@ -83,6 +83,10 @@ class AlarmManager(base.Manager):
|
||||
'gnocchi_aggregation_by_resources_threshold_rule'))
|
||||
alarm_update.pop(
|
||||
'gnocchi_aggregation_by_resources_threshold_rule')
|
||||
elif 'composite_rule' in alarm_update:
|
||||
if alarm_update['composite_rule']:
|
||||
alarm['composite_rule'] = alarm_update['composite_rule']
|
||||
alarm_update.pop('composite_rule')
|
||||
|
||||
alarm.update(alarm_update)
|
||||
return self._put(
|
||||
|
||||
@@ -13,11 +13,13 @@
|
||||
from cliff import command
|
||||
from cliff import lister
|
||||
from cliff import show
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_utils import strutils
|
||||
|
||||
from aodhclient import utils
|
||||
|
||||
ALARM_TYPES = ['threshold', 'event', 'gnocchi_resources_threshold',
|
||||
ALARM_TYPES = ['threshold', 'event', 'composite',
|
||||
'gnocchi_resources_threshold',
|
||||
'gnocchi_aggregation_by_metrics_threshold',
|
||||
'gnocchi_aggregation_by_resources_threshold']
|
||||
ALARM_STATES = ['ok', 'alarm', 'insufficient data']
|
||||
@@ -61,6 +63,10 @@ class CliAlarmSearch(CliAlarmList):
|
||||
|
||||
|
||||
def _format_alarm(alarm):
|
||||
if alarm.get('composite_rule'):
|
||||
composite_rule = jsonutils.dumps(alarm['composite_rule'], indent=2)
|
||||
alarm['composite_rule'] = composite_rule
|
||||
return alarm
|
||||
for alarm_type in ALARM_TYPES:
|
||||
if alarm.get('%s_rule' % alarm_type):
|
||||
alarm.update(alarm.pop('%s_rule' % alarm_type))
|
||||
@@ -209,7 +215,19 @@ class CliAlarmCreate(show.ShowOne):
|
||||
gnocchi_aggr_metrics_group.add_argument(
|
||||
'--metrics', metavar='<METRICS>', action='append',
|
||||
dest='metrics', help='The list of metric ids.')
|
||||
|
||||
composite_group = parser.add_argument_group('composite alarm')
|
||||
composite_group.add_argument(
|
||||
'--composite-rule', metavar='<COMPOSITE_RULE>',
|
||||
dest='composite_rule',
|
||||
type=jsonutils.loads,
|
||||
help='Composite threshold rule with JSON format, the form can'
|
||||
'be a nested dict which combine threshold/gnocchi rules by'
|
||||
' "and", "or". For example, the form is like: '
|
||||
'{"or":[RULE1, RULE2, {"and": [RULE3, RULE4]}]}, The'
|
||||
'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
|
||||
return parser
|
||||
|
||||
@@ -239,6 +257,10 @@ class CliAlarmCreate(show.ShowOne):
|
||||
'requires --metric, --threshold, '
|
||||
'--aggregation-method, --query and '
|
||||
'--resource_type')
|
||||
elif (parsed_args.type == 'composite' and
|
||||
not parsed_args.composite_rule):
|
||||
self.parser.error('composite alarm requires'
|
||||
' --composite-rule parameter')
|
||||
|
||||
def _alarm_from_args(self, parsed_args):
|
||||
alarm = utils.dict_from_parsed_args(
|
||||
@@ -270,6 +292,7 @@ class CliAlarmCreate(show.ShowOne):
|
||||
'evaluation_periods', 'metric',
|
||||
'query', 'resource_type']))
|
||||
|
||||
alarm['composite_rule'] = parsed_args.composite_rule
|
||||
if self.create:
|
||||
alarm['type'] = parsed_args.type
|
||||
self._validate_args(parsed_args)
|
||||
|
||||
Reference in New Issue
Block a user