Improve the CM shell client alarm visualisation
This change aim to get a better alarm representation in shell. In alarm-list: * it add a short sentence to describe the alarm rule * it remove project_id/user_id because it always show the same id for all alarm for end-user In alarm-show, it show alarm rule attributes as alarm properties instead of a unparsable json in the rule property. example of short sentence for column 'Alarm condition': * combinated states (AND) of 8babd6a2-c457-42d0-9eb5-cdfb3cb50203, d0e11a94-8f59-48a9-8f6d-b0d68aaac8d0 * cpu_util >= 50.0 during 1 x 60s Change-Id: If4df2dc08f9f4cb7796fd98308c7d62e311d1138
This commit is contained in:
@@ -63,17 +63,19 @@ def print_dict(d, dict_property="Property", wrap=0):
|
|||||||
# convert dict to str to check length
|
# convert dict to str to check length
|
||||||
if isinstance(v, dict):
|
if isinstance(v, dict):
|
||||||
v = str(v)
|
v = str(v)
|
||||||
if wrap > 0:
|
|
||||||
v = textwrap.fill(str(v), wrap)
|
|
||||||
# if value has a newline, add in multiple rows
|
# if value has a newline, add in multiple rows
|
||||||
# e.g. fault with stacktrace
|
# e.g. fault with stacktrace
|
||||||
if v and isinstance(v, basestring) and r'\n' in v:
|
if v and isinstance(v, basestring) and r'\n' in v:
|
||||||
lines = v.strip().split(r'\n')
|
lines = v.strip().split(r'\n')
|
||||||
col1 = k
|
col1 = k
|
||||||
for line in lines:
|
for line in lines:
|
||||||
|
if wrap > 0:
|
||||||
|
line = textwrap.fill(str(line), wrap)
|
||||||
pt.add_row([col1, line])
|
pt.add_row([col1, line])
|
||||||
col1 = ''
|
col1 = ''
|
||||||
else:
|
else:
|
||||||
|
if wrap > 0:
|
||||||
|
v = textwrap.fill(str(v), wrap)
|
||||||
pt.add_row([k, v])
|
pt.add_row([k, v])
|
||||||
print pt.get_string()
|
print pt.get_string()
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ ALARM_STATES = ['ok', 'alarm', 'insufficient_data']
|
|||||||
ALARM_OPERATORS = ['lt', 'le', 'eq', 'ne', 'ge', 'gt']
|
ALARM_OPERATORS = ['lt', 'le', 'eq', 'ne', 'ge', 'gt']
|
||||||
ALARM_COMBINATION_OPERATORS = ['and', 'or']
|
ALARM_COMBINATION_OPERATORS = ['and', 'or']
|
||||||
STATISTICS = ['max', 'min', 'avg', 'sum', 'count']
|
STATISTICS = ['max', 'min', 'avg', 'sum', 'count']
|
||||||
|
OPERATORS_STRING = dict(gt='>', ge='>=',
|
||||||
|
lt='<', le="<=",
|
||||||
|
eq='==', ne='!=')
|
||||||
|
|
||||||
|
|
||||||
@utils.arg('-q', '--query', metavar='<QUERY>',
|
@utils.arg('-q', '--query', metavar='<QUERY>',
|
||||||
@@ -128,6 +131,28 @@ def do_meter_list(cc, args={}):
|
|||||||
sortby=0)
|
sortby=0)
|
||||||
|
|
||||||
|
|
||||||
|
def alarm_rule_formatter(alarm):
|
||||||
|
if alarm.type == 'threshold':
|
||||||
|
return ('%(meter_name)s %(comparison_operator)s '
|
||||||
|
'%(threshold)s during %(evaluation_periods)s x %(period)ss' %
|
||||||
|
{
|
||||||
|
'meter_name': alarm.rule['meter_name'],
|
||||||
|
'threshold': alarm.rule['threshold'],
|
||||||
|
'evaluation_periods': alarm.rule['evaluation_periods'],
|
||||||
|
'period': alarm.rule['period'],
|
||||||
|
'comparison_operator': OPERATORS_STRING.get(
|
||||||
|
alarm.rule['comparison_operator'])
|
||||||
|
})
|
||||||
|
elif alarm.type == 'combination':
|
||||||
|
return ('combinated states (%(operator)s) of %(alarms)s' % {
|
||||||
|
'operator': alarm.rule['operator'].upper(),
|
||||||
|
'alarms': ", ".join(alarm.rule['alarm_ids'])})
|
||||||
|
else:
|
||||||
|
# just dump all
|
||||||
|
return "\n".join(["%s: %s" % (f, v)
|
||||||
|
for f, v in alarm.rule.iteritems()])
|
||||||
|
|
||||||
|
|
||||||
@utils.arg('-q', '--query', metavar='<QUERY>',
|
@utils.arg('-q', '--query', metavar='<QUERY>',
|
||||||
help='key[op]value; list.')
|
help='key[op]value; list.')
|
||||||
def do_alarm_list(cc, args={}):
|
def do_alarm_list(cc, args={}):
|
||||||
@@ -135,20 +160,31 @@ def do_alarm_list(cc, args={}):
|
|||||||
alarms = cc.alarms.list(q=options.cli_to_array(args.query))
|
alarms = cc.alarms.list(q=options.cli_to_array(args.query))
|
||||||
# omit action initially to keep output width sane
|
# omit action initially to keep output width sane
|
||||||
# (can switch over to vertical formatting when available from CLIFF)
|
# (can switch over to vertical formatting when available from CLIFF)
|
||||||
field_labels = ['Name', 'Description', 'State', 'Enabled', 'Continuous',
|
field_labels = ['Alarm ID', 'Name', 'State', 'Enabled', 'Continuous',
|
||||||
'Alarm ID', 'User ID', 'Project ID']
|
'Alarm condition']
|
||||||
fields = ['name', 'description', 'state', 'enabled', 'repeat_actions',
|
fields = ['alarm_id', 'name', 'state', 'enabled', 'repeat_actions',
|
||||||
'alarm_id', 'user_id', 'project_id']
|
'rule']
|
||||||
utils.print_list(alarms, fields, field_labels,
|
utils.print_list(alarms, fields, field_labels,
|
||||||
sortby=0)
|
formatters={'rule': alarm_rule_formatter}, sortby=0)
|
||||||
|
|
||||||
|
|
||||||
|
def alarm_query_formater(alarm):
|
||||||
|
qs = []
|
||||||
|
for q in alarm.rule['query']:
|
||||||
|
qs.append('%s %s %s' % (
|
||||||
|
q['field'], OPERATORS_STRING.get(q['op']), q['value']))
|
||||||
|
return r' AND\n'.join(qs)
|
||||||
|
|
||||||
|
|
||||||
def _display_alarm(alarm):
|
def _display_alarm(alarm):
|
||||||
fields = ['name', 'description', 'type', 'rule',
|
fields = ['name', 'description', 'type',
|
||||||
'state', 'enabled', 'alarm_id', 'user_id', 'project_id',
|
'state', 'enabled', 'alarm_id', 'user_id', 'project_id',
|
||||||
'alarm_actions', 'ok_actions', 'insufficient_data_actions',
|
'alarm_actions', 'ok_actions', 'insufficient_data_actions',
|
||||||
'repeat_actions']
|
'repeat_actions']
|
||||||
data = dict([(f, getattr(alarm, f, '')) for f in fields])
|
data = dict([(f, getattr(alarm, f, '')) for f in fields])
|
||||||
|
data.update(alarm.rule)
|
||||||
|
if alarm.type == 'threshold':
|
||||||
|
data['query'] = alarm_query_formater(alarm)
|
||||||
utils.print_dict(data, wrap=72)
|
utils.print_dict(data, wrap=72)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user