Adds alarm time constraint support to ceilometer CLI
Time constraints can be specified for create and update
families of commands with the following format:
--time-constraint name=constraint1;start='0 11 * * *';duration=300
This switch can be specified multiple times in the case of
multiple time constraints.
With update commands, time constraints are updated by name,
e.g. --time-constraint name=constraint1;duration=500 updates
the constraint 'constraint1' with a new duration 500.
Time constraints can be removed with update commands using the
switch --remove-time-constraint=constraint1,constraint2 .
Example of display outputs:
> ceilometer alarm-list
+--------------------------------------+-------+-------------------+---------+------------+----------------------------+--------------------------------------------------------------+
| Alarm ID | Name | State | Enabled | Continuous | Alarm condition | Time constraints |
+--------------------------------------+-------+-------------------+---------+------------+----------------------------+--------------------------------------------------------------+
| 2ead776d-2fc7-47a2-b0bb-0f88dcefa457 | test2 | insufficient data | True | False | cpu == 50.0 during 1 x 60s | cons1 at 0 11 * * * for 300s, cons2 at 0 23 * * * for 600s |
+--------------------------------------+-------+-------------------+---------+------------+----------------------------+--------------------------------------------------------------+
> ceilometer alarm-show -a
+---------------------------+-----------------------------------------------------------------------+
| Property | Value |
+---------------------------+-----------------------------------------------------------------------+
| alarm_actions | [] |
| alarm_id | 2ead776d-2fc7-47a2-b0bb-0f88dcefa457 |
| comparison_operator | eq |
| description | Alarm when cpu is eq a avg of 50.0 over 60 seconds |
| enabled | True |
| evaluation_periods | 1 |
| exclude_outliers | False |
| insufficient_data_actions | [] |
| meter_name | cpu |
| name | test2 |
| ok_actions | [] |
| period | 60 |
| project_id | 962f75ad22c24cbf99d40d7b82718505 |
| query | |
| repeat_actions | False |
| state | insufficient data |
| statistic | avg |
| threshold | 50.0 |
| time_constraints | [{name: cons1, |
| | description: Time constraint at 0 11 * * * lasting for 300 seconds, |
| | start: 0 11 * * *, |
| | duration: 300}, |
| | {name: cons2, |
| | description: Time constraint at 0 23 * * * lasting for 600 seconds, |
| | start: 0 23 * * *, |
| | duration: 600}] |
| type | threshold |
| user_id | 76f335df8e2f4c7e9e8185e26ea85759 |
+---------------------------+-----------------------------------------------------------------------+
> ceilometer alarm-history -a 2ead776d-2fc7-47a2-b0bb-0f88dcefa457
+----------+----------------------------+--------------------------------------------------------------------------------+
| Type | Timestamp | Detail |
+----------+----------------------------+--------------------------------------------------------------------------------+
| creation | 2014-03-06T07:41:35.362050 | name: test2 |
| | | description: Alarm when cpu is eq a avg of 50.0 over 60 seconds |
| | | type: threshold |
| | | rule: cpu == 50.0 during 1 x 60s |
| | | time_constraints: cons1 at 0 11 * * * for 300s, cons2 at 0 23 * * * for 600s |
+----------+----------------------------+--------------------------------------------------------------------------------+
Change-Id: I3953276537b4526e46e5e6d229d6fa154f8ab0fc
Closes-Bug: #1288246
This commit is contained in:
@@ -154,6 +154,27 @@ def args_array_to_dict(kwargs, key_to_convert):
|
||||
return kwargs
|
||||
|
||||
|
||||
def args_array_to_list_of_dicts(kwargs, key_to_convert):
|
||||
"""Converts ['a=1;b=2','c=3;d=4'] to [{a:1,b:2},{c:3,d:4}]
|
||||
"""
|
||||
values_to_convert = kwargs.get(key_to_convert)
|
||||
if values_to_convert:
|
||||
try:
|
||||
kwargs[key_to_convert] = []
|
||||
for lst in values_to_convert:
|
||||
pairs = lst.split(";")
|
||||
dct = dict()
|
||||
for pair in pairs:
|
||||
kv = pair.split("=", 1)
|
||||
dct[kv[0]] = kv[1].strip(" \"'") # strip spaces and quotes
|
||||
kwargs[key_to_convert].append(dct)
|
||||
except Exception:
|
||||
raise exc.CommandError(
|
||||
'%s must be a list of key1=value1;key2=value2;... not "%s"' % (
|
||||
key_to_convert, values_to_convert))
|
||||
return kwargs
|
||||
|
||||
|
||||
def key_with_slash_to_nested_dict(kwargs):
|
||||
nested_kwargs = {}
|
||||
for k in list(kwargs):
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
# under the License.
|
||||
|
||||
|
||||
import itertools
|
||||
import mock
|
||||
import six
|
||||
import sys
|
||||
@@ -117,6 +118,33 @@ class UtilsTest(test_utils.BaseTestCase):
|
||||
'other': 'value'
|
||||
})
|
||||
|
||||
def test_args_array_to_list_of_dicts(self):
|
||||
starts = ['0 11 * * *', '"0 11 * * *"', '\'0 11 * * *\'']
|
||||
timezones = [None, 'US/Eastern', '"US/Eastern"', '\'US/Eastern\'']
|
||||
descs = [None, 'de sc', '"de sc"', '\'de sc\'']
|
||||
for start, tz, desc in itertools.product(starts, timezones, descs):
|
||||
my_args = {
|
||||
'time_constraints': ['name=const1;start=%s;duration=1'
|
||||
% start],
|
||||
'other': 'value'
|
||||
}
|
||||
expected = {
|
||||
'time_constraints': [dict(name='const1',
|
||||
start='0 11 * * *',
|
||||
duration='1')],
|
||||
'other': 'value'
|
||||
}
|
||||
if tz:
|
||||
my_args['time_constraints'][0] += ';timezone=%s' % tz
|
||||
expected['time_constraints'][0]['timezone'] = 'US/Eastern'
|
||||
if desc:
|
||||
my_args['time_constraints'][0] += ';description=%s' % desc
|
||||
expected['time_constraints'][0]['description'] = 'de sc'
|
||||
|
||||
cleaned = utils.args_array_to_list_of_dicts(my_args,
|
||||
'time_constraints')
|
||||
self.assertEqual(expected, cleaned)
|
||||
|
||||
def test_key_with_slash_to_nested_dict(self):
|
||||
my_args = {
|
||||
'combination_rule/alarm_ids': ['id1', 'id2'],
|
||||
|
||||
@@ -40,6 +40,16 @@ AN_ALARM = {u'alarm_actions': [u'http://site:8000/alarm'],
|
||||
u'threshold': 200.0,
|
||||
u'comparison_operator': 'gt',
|
||||
},
|
||||
u'time_constraints': [{u'name': u'cons1',
|
||||
u'description': u'desc1',
|
||||
u'start': u'0 11 * * *',
|
||||
u'duration': 300,
|
||||
u'timezone': u''},
|
||||
{u'name': u'cons2',
|
||||
u'description': u'desc2',
|
||||
u'start': u'0 23 * * *',
|
||||
u'duration': 600,
|
||||
u'timezone': ''}],
|
||||
u'timestamp': u'2013-05-09T13:41:23.085000',
|
||||
u'enabled': True,
|
||||
u'alarm_id': u'alarm-id',
|
||||
@@ -54,6 +64,8 @@ CREATE_ALARM = copy.deepcopy(AN_ALARM)
|
||||
del CREATE_ALARM['timestamp']
|
||||
del CREATE_ALARM['state_timestamp']
|
||||
del CREATE_ALARM['alarm_id']
|
||||
CREATE_ALARM_WITHOUT_TC = copy.deepcopy(CREATE_ALARM)
|
||||
del CREATE_ALARM_WITHOUT_TC['time_constraints']
|
||||
DELTA_ALARM = {u'alarm_actions': ['url1', 'url2']}
|
||||
DELTA_ALARM_RULE = {u'comparison_operator': u'lt',
|
||||
u'threshold': 42.1,
|
||||
@@ -61,11 +73,21 @@ DELTA_ALARM_RULE = {u'comparison_operator': u'lt',
|
||||
u'query': [{u'field': u'key_name',
|
||||
u'op': u'eq',
|
||||
u'value': u'key_value'}]}
|
||||
DELTA_ALARM_TC = [{u'name': u'cons1',
|
||||
u'duration': 500}]
|
||||
DELTA_ALARM['time_constraints'] = DELTA_ALARM_TC
|
||||
UPDATED_ALARM = copy.deepcopy(AN_ALARM)
|
||||
UPDATED_ALARM.update(DELTA_ALARM)
|
||||
UPDATED_ALARM['threshold_rule'].update(DELTA_ALARM_RULE)
|
||||
DELTA_ALARM['remove_time_constraints'] = 'cons2'
|
||||
UPDATED_ALARM['time_constraints'] = [{u'name': u'cons1',
|
||||
u'description': u'desc1',
|
||||
u'start': u'0 11 * * *',
|
||||
u'duration': 500,
|
||||
u'timezone': u''}]
|
||||
DELTA_ALARM['threshold_rule'] = DELTA_ALARM_RULE
|
||||
UPDATE_ALARM = copy.deepcopy(UPDATED_ALARM)
|
||||
UPDATE_ALARM['remove_time_constraints'] = 'cons2'
|
||||
del UPDATE_ALARM['user_id']
|
||||
del UPDATE_ALARM['project_id']
|
||||
del UPDATE_ALARM['name']
|
||||
@@ -101,6 +123,9 @@ DELTA_LEGACY_ALARM = {u'alarm_actions': ['url1', 'url2'],
|
||||
u'comparison_operator': u'lt',
|
||||
u'meter_name': u'foobar',
|
||||
u'threshold': 42.1}
|
||||
DELTA_LEGACY_ALARM['time_constraints'] = [{u'name': u'cons1',
|
||||
u'duration': 500}]
|
||||
DELTA_LEGACY_ALARM['remove_time_constraints'] = 'cons2'
|
||||
UPDATED_LEGACY_ALARM = copy.deepcopy(AN_LEGACY_ALARM)
|
||||
UPDATED_LEGACY_ALARM.update(DELTA_LEGACY_ALARM)
|
||||
UPDATE_LEGACY_ALARM = copy.deepcopy(UPDATED_LEGACY_ALARM)
|
||||
@@ -348,7 +373,7 @@ class AlarmLegacyManagerTest(testtools.TestCase):
|
||||
def test_create(self):
|
||||
alarm = self.mgr.create(**CREATE_LEGACY_ALARM)
|
||||
expect = [
|
||||
('POST', '/v2/alarms', {}, CREATE_ALARM),
|
||||
('POST', '/v2/alarms', {}, CREATE_ALARM_WITHOUT_TC),
|
||||
]
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
self.assertTrue(alarm)
|
||||
@@ -360,7 +385,7 @@ class AlarmLegacyManagerTest(testtools.TestCase):
|
||||
del create['meter_name']
|
||||
alarm = self.mgr.create(**create)
|
||||
expect = [
|
||||
('POST', '/v2/alarms', {}, CREATE_ALARM),
|
||||
('POST', '/v2/alarms', {}, CREATE_ALARM_WITHOUT_TC),
|
||||
]
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
self.assertTrue(alarm)
|
||||
@@ -392,3 +417,41 @@ class AlarmLegacyManagerTest(testtools.TestCase):
|
||||
self.assertEqual(alarm.alarm_id, 'alarm-id')
|
||||
for (key, value) in six.iteritems(UPDATED_ALARM):
|
||||
self.assertEqual(getattr(alarm, key), value)
|
||||
|
||||
|
||||
class AlarmTimeConstraintTest(testtools.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(AlarmTimeConstraintTest, self).setUp()
|
||||
self.api = utils.FakeAPI(fixtures)
|
||||
self.mgr = alarms.AlarmManager(self.api)
|
||||
|
||||
def test_add_new(self):
|
||||
new_constraint = dict(name='cons3',
|
||||
start='0 0 * * *',
|
||||
duration=500)
|
||||
kwargs = dict(time_constraints=[new_constraint])
|
||||
self.mgr.update(alarm_id='alarm-id', **kwargs)
|
||||
actual = self.api.calls[1][3]['time_constraints']
|
||||
expected = AN_ALARM[u'time_constraints'] + [new_constraint]
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
def test_update_existing(self):
|
||||
updated_constraint = dict(name='cons2',
|
||||
duration=500)
|
||||
kwargs = dict(time_constraints=[updated_constraint])
|
||||
self.mgr.update(alarm_id='alarm-id', **kwargs)
|
||||
actual = self.api.calls[1][3]['time_constraints']
|
||||
expected = [AN_ALARM[u'time_constraints'][0], dict(name='cons2',
|
||||
description='desc2',
|
||||
start='0 23 * * *',
|
||||
duration=500,
|
||||
timezone='')]
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
def test_remove(self):
|
||||
kwargs = dict(remove_time_constraints=['cons2'])
|
||||
self.mgr.update(alarm_id='alarm-id', **kwargs)
|
||||
actual = self.api.calls[1][3]['time_constraints']
|
||||
expected = [AN_ALARM[u'time_constraints'][0]]
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
@@ -158,6 +158,16 @@ class ShellAlarmCommandTest(utils.BaseTestCase):
|
||||
"value": "INSTANCE_ID",
|
||||
"op": "eq"}],
|
||||
"comparison_operator": "gt"},
|
||||
"time_constraints": [{"name": "cons1",
|
||||
"description": "desc1",
|
||||
"start": "0 11 * * *",
|
||||
"duration": 300,
|
||||
"timezone": ""},
|
||||
{"name": "cons2",
|
||||
"description": "desc2",
|
||||
"start": "0 23 * * *",
|
||||
"duration": 600,
|
||||
"timezone": ""}],
|
||||
"alarm_id": ALARM_ID,
|
||||
"state": "insufficient data",
|
||||
"insufficient_data_actions": [],
|
||||
@@ -276,6 +286,36 @@ class ShellAlarmCommandTest(utils.BaseTestCase):
|
||||
sys.stdout.close()
|
||||
sys.stdout = orig
|
||||
|
||||
def test_alarm_create_time_constraints(self):
|
||||
shell = base_shell.CeilometerShell()
|
||||
argv = ['alarm-threshold-create',
|
||||
'--name', 'cpu_high',
|
||||
'--meter-name', 'cpu_util',
|
||||
'--threshold', '70.0',
|
||||
'--time-constraint',
|
||||
'name=cons1;start="0 11 * * *";duration=300',
|
||||
'--time-constraint',
|
||||
'name=cons2;start="0 23 * * *";duration=600',
|
||||
]
|
||||
_, args = shell.parse_args(argv)
|
||||
|
||||
orig = sys.stdout
|
||||
sys.stdout = six.StringIO()
|
||||
alarm = alarms.Alarm(mock.Mock(), self.ALARM)
|
||||
self.cc.alarms.create.return_value = alarm
|
||||
|
||||
try:
|
||||
ceilometer_shell.do_alarm_threshold_create(self.cc, args)
|
||||
_, kwargs = self.cc.alarms.create.call_args
|
||||
time_constraints = [dict(name='cons1', start='0 11 * * *',
|
||||
duration='300'),
|
||||
dict(name='cons2', start='0 23 * * *',
|
||||
duration='600')]
|
||||
self.assertEqual(time_constraints, kwargs['time_constraints'])
|
||||
finally:
|
||||
sys.stdout.close()
|
||||
sys.stdout = orig
|
||||
|
||||
|
||||
class ShellSampleListCommandTest(utils.BaseTestCase):
|
||||
|
||||
|
||||
@@ -36,7 +36,8 @@ UPDATABLE_ATTRIBUTES = [
|
||||
'threshold_rule',
|
||||
'combination_rule',
|
||||
]
|
||||
CREATION_ATTRIBUTES = UPDATABLE_ATTRIBUTES + ['project_id', 'user_id']
|
||||
CREATION_ATTRIBUTES = UPDATABLE_ATTRIBUTES + ['project_id', 'user_id',
|
||||
'time_constraints']
|
||||
|
||||
|
||||
class Alarm(base.Resource):
|
||||
@@ -111,6 +112,26 @@ class AlarmManager(base.Manager):
|
||||
del kwargs['matching_metadata']
|
||||
kwargs['threshold_rule']['query'] = query
|
||||
|
||||
@staticmethod
|
||||
def _merge_time_constraints(existing_tcs, kwargs):
|
||||
new_tcs = kwargs.get('time_constraints', [])
|
||||
if not existing_tcs:
|
||||
updated_tcs = new_tcs
|
||||
else:
|
||||
updated_tcs = [dict(tc) for tc in existing_tcs]
|
||||
for tc in new_tcs:
|
||||
for i, old_tc in enumerate(updated_tcs):
|
||||
if old_tc['name'] == tc['name']: # if names match, merge
|
||||
utils.merge_nested_dict(updated_tcs[i], tc)
|
||||
break
|
||||
else:
|
||||
updated_tcs.append(tc)
|
||||
tcs_to_remove = kwargs.get('remove_time_constraints', [])
|
||||
for tc in updated_tcs:
|
||||
if tc['name'] in tcs_to_remove:
|
||||
updated_tcs.remove(tc)
|
||||
return updated_tcs
|
||||
|
||||
def create(self, **kwargs):
|
||||
self._compat_legacy_alarm_kwargs(kwargs, create=True)
|
||||
new = dict((key, value) for (key, value) in kwargs.items()
|
||||
@@ -120,6 +141,8 @@ class AlarmManager(base.Manager):
|
||||
def update(self, alarm_id, **kwargs):
|
||||
self._compat_legacy_alarm_kwargs(kwargs)
|
||||
updated = self.get(alarm_id).to_dict()
|
||||
updated['time_constraints'] = self._merge_time_constraints(
|
||||
updated.get('time_constraints', []), kwargs)
|
||||
kwargs = dict((k, v) for k, v in kwargs.items()
|
||||
if k in updated and k in UPDATABLE_ATTRIBUTES)
|
||||
utils.merge_nested_dict(updated, kwargs, depth=1)
|
||||
|
||||
@@ -176,6 +176,24 @@ def alarm_rule_formatter(alarm):
|
||||
return _display_rule(alarm.type, alarm.rule)
|
||||
|
||||
|
||||
def _display_time_constraints(time_constraints):
|
||||
if time_constraints:
|
||||
return ', '.join('%(name)s at %(start)s %(timezone)s for %(duration)ss'
|
||||
% {
|
||||
'name': tc['name'],
|
||||
'start': tc['start'],
|
||||
'duration': tc['duration'],
|
||||
'timezone': tc.get('timezone', '')
|
||||
}
|
||||
for tc in time_constraints)
|
||||
else:
|
||||
return 'None'
|
||||
|
||||
|
||||
def time_constraints_formatter(alarm):
|
||||
return _display_time_constraints(alarm.time_constraints)
|
||||
|
||||
|
||||
def _infer_type(detail):
|
||||
if 'type' in detail:
|
||||
return detail['type']
|
||||
@@ -199,6 +217,10 @@ def alarm_change_detail_formatter(change):
|
||||
detail[k]))
|
||||
else:
|
||||
fields.append('%s: %s' % (k, detail[k]))
|
||||
if 'time_constraints' in detail:
|
||||
fields.append('time_constraints: %s' %
|
||||
_display_time_constraints(
|
||||
detail['time_constraints']))
|
||||
elif change.type == 'rule change':
|
||||
for k, v in six.iteritems(detail):
|
||||
if k == 'rule':
|
||||
@@ -218,11 +240,13 @@ def do_alarm_list(cc, args={}):
|
||||
# omit action initially to keep output width sane
|
||||
# (can switch over to vertical formatting when available from CLIFF)
|
||||
field_labels = ['Alarm ID', 'Name', 'State', 'Enabled', 'Continuous',
|
||||
'Alarm condition']
|
||||
'Alarm condition', 'Time constraints']
|
||||
fields = ['alarm_id', 'name', 'state', 'enabled', 'repeat_actions',
|
||||
'rule']
|
||||
utils.print_list(alarms, fields, field_labels,
|
||||
formatters={'rule': alarm_rule_formatter}, sortby=0)
|
||||
'rule', 'time_constraints']
|
||||
utils.print_list(
|
||||
alarms, fields, field_labels,
|
||||
formatters={'rule': alarm_rule_formatter,
|
||||
'time_constraints': time_constraints_formatter}, sortby=0)
|
||||
|
||||
|
||||
def alarm_query_formater(alarm):
|
||||
@@ -233,6 +257,17 @@ def alarm_query_formater(alarm):
|
||||
return r' AND\n'.join(qs)
|
||||
|
||||
|
||||
def alarm_time_constraints_formatter(alarm):
|
||||
time_constraints = []
|
||||
for tc in alarm.time_constraints:
|
||||
lines = []
|
||||
for k in ['name', 'description', 'start', 'duration', 'timezone']:
|
||||
if k in tc and tc[k]:
|
||||
lines.append(r'%s: %s' % (k, tc[k]))
|
||||
time_constraints.append('{' + r',\n '.join(lines) + '}')
|
||||
return '[' + r',\n '.join(time_constraints) + ']'
|
||||
|
||||
|
||||
def _display_alarm(alarm):
|
||||
fields = ['name', 'description', 'type',
|
||||
'state', 'enabled', 'alarm_id', 'user_id', 'project_id',
|
||||
@@ -242,6 +277,8 @@ def _display_alarm(alarm):
|
||||
data.update(alarm.rule)
|
||||
if alarm.type == 'threshold':
|
||||
data['query'] = alarm_query_formater(alarm)
|
||||
if alarm.time_constraints:
|
||||
data['time_constraints'] = alarm_time_constraints_formatter(alarm)
|
||||
utils.print_dict(data, wrap=72)
|
||||
|
||||
|
||||
@@ -287,6 +324,18 @@ def common_alarm_arguments(create=False):
|
||||
metavar='<Webhook URL>', action='append', default=None,
|
||||
help=('URL to invoke when state transitions to '
|
||||
'insufficient_data. May be used multiple times.'))
|
||||
@utils.arg('--time-constraint', dest='time_constraints',
|
||||
metavar='<Time Constraint>', action='append',
|
||||
default=None,
|
||||
help=('Only evaluate the alarm if the time at evaluation '
|
||||
'is within this time constraint. Start point(s) of '
|
||||
'the constraint are specified with a cron expression '
|
||||
', whereas its duration is given in seconds. '
|
||||
'Can be specified multiple times for multiple '
|
||||
'time constraints, format is: '
|
||||
'name=<CONSTRAINT_NAME>;start=<CRON>;'
|
||||
'duration=<SECONDS>;[description=<DESCRIPTION>;'
|
||||
'[timezone=<IANA Timezone>]]'))
|
||||
@functools.wraps(func)
|
||||
def _wrapped(*args, **kwargs):
|
||||
return func(*args, **kwargs)
|
||||
@@ -320,6 +369,7 @@ def common_alarm_arguments(create=False):
|
||||
def do_alarm_create(cc, args={}):
|
||||
'''Create a new alarm (Deprecated).'''
|
||||
fields = dict(filter(lambda x: not (x[1] is None), vars(args).items()))
|
||||
fields = utils.args_array_to_list_of_dicts(fields, "time_constraints")
|
||||
fields = utils.args_array_to_dict(fields, "matching_metadata")
|
||||
alarm = cc.alarms.create(**fields)
|
||||
_display_alarm(alarm)
|
||||
@@ -357,6 +407,7 @@ def do_alarm_create(cc, args={}):
|
||||
def do_alarm_threshold_create(cc, args={}):
|
||||
'''Create a new alarm based on computed statistics.'''
|
||||
fields = dict(filter(lambda x: not (x[1] is None), vars(args).items()))
|
||||
fields = utils.args_array_to_list_of_dicts(fields, 'time_constraints')
|
||||
fields = utils.key_with_slash_to_nested_dict(fields)
|
||||
fields['type'] = 'threshold'
|
||||
if 'query' in fields['threshold_rule']:
|
||||
@@ -382,6 +433,7 @@ def do_alarm_threshold_create(cc, args={}):
|
||||
def do_alarm_combination_create(cc, args={}):
|
||||
'''Create a new alarm based on state of other alarms.'''
|
||||
fields = dict(filter(lambda x: not (x[1] is None), vars(args).items()))
|
||||
fields = utils.args_array_to_list_of_dicts(fields, 'time_constraints')
|
||||
fields = utils.key_with_slash_to_nested_dict(fields)
|
||||
fields['type'] = 'combination'
|
||||
alarm = cc.alarms.create(**fields)
|
||||
@@ -391,6 +443,10 @@ def do_alarm_combination_create(cc, args={}):
|
||||
@utils.arg('-a', '--alarm_id', metavar='<ALARM_ID>', required=True,
|
||||
help='ID of the alarm to update.')
|
||||
@common_alarm_arguments()
|
||||
@utils.arg('--remove-time-constraint', action='append',
|
||||
metavar='<Constraint names>',
|
||||
dest='remove_time_constraints',
|
||||
help='Name or list of names of the time constraints to remove.')
|
||||
@utils.arg('--period', type=int, metavar='<PERIOD>',
|
||||
help='Length of each period (seconds) to evaluate over.')
|
||||
@utils.arg('--evaluation-periods', type=int, metavar='<COUNT>',
|
||||
@@ -415,6 +471,7 @@ def do_alarm_combination_create(cc, args={}):
|
||||
def do_alarm_update(cc, args={}):
|
||||
'''Update an existing alarm.'''
|
||||
fields = dict(filter(lambda x: not (x[1] is None), vars(args).items()))
|
||||
fields = utils.args_array_to_list_of_dicts(fields, "time_constraints")
|
||||
fields = utils.args_array_to_dict(fields, "matching_metadata")
|
||||
fields.pop('alarm_id')
|
||||
try:
|
||||
@@ -427,6 +484,10 @@ def do_alarm_update(cc, args={}):
|
||||
@utils.arg('-a', '--alarm_id', metavar='<ALARM_ID>', required=True,
|
||||
help='ID of the alarm to update.')
|
||||
@common_alarm_arguments()
|
||||
@utils.arg('--remove-time-constraint', action='append',
|
||||
metavar='<Constraint names>',
|
||||
dest='remove_time_constraints',
|
||||
help='Name or list of names of the time constraints to remove.')
|
||||
@utils.arg('-m', '--meter-name', metavar='<METRIC>',
|
||||
dest='threshold_rule/meter_name',
|
||||
help='Metric to evaluate against.')
|
||||
@@ -457,6 +518,7 @@ def do_alarm_update(cc, args={}):
|
||||
def do_alarm_threshold_update(cc, args={}):
|
||||
'''Update an existing alarm based on computed statistics.'''
|
||||
fields = dict(filter(lambda x: not (x[1] is None), vars(args).items()))
|
||||
fields = utils.args_array_to_list_of_dicts(fields, 'time_constraints')
|
||||
fields = utils.key_with_slash_to_nested_dict(fields)
|
||||
fields.pop('alarm_id')
|
||||
fields['type'] = 'threshold'
|
||||
@@ -473,6 +535,10 @@ def do_alarm_threshold_update(cc, args={}):
|
||||
@utils.arg('-a', '--alarm_id', metavar='<ALARM_ID>', required=True,
|
||||
help='ID of the alarm to update.')
|
||||
@common_alarm_arguments()
|
||||
@utils.arg('--remove-time-constraint', action='append',
|
||||
metavar='<Constraint names>',
|
||||
dest='remove_time_constraints',
|
||||
help='Name or list of names of the time constraints to remove.')
|
||||
@utils.arg('--alarm_ids', action='append', metavar='<ALARM IDS>',
|
||||
dest='combination_rule/alarm_ids',
|
||||
help='List of alarm id.')
|
||||
@@ -487,6 +553,7 @@ def do_alarm_threshold_update(cc, args={}):
|
||||
def do_alarm_combination_update(cc, args={}):
|
||||
'''Update an existing alarm based on state of other alarms.'''
|
||||
fields = dict(filter(lambda x: not (x[1] is None), vars(args).items()))
|
||||
fields = utils.args_array_to_list_of_dicts(fields, 'time_constraints')
|
||||
fields = utils.key_with_slash_to_nested_dict(fields)
|
||||
fields.pop('alarm_id')
|
||||
fields['type'] = 'combination'
|
||||
|
||||
Reference in New Issue
Block a user