event-alarm: add alarm wrapper class
This patch adds a new class 'Alarm' for event alarm evaluation. The parser and helper functions for alarms (type='event') are moved to this new class. All trait values in event_rule/query will be sanitized. Change-Id: If5600113b0552ccc1d3c4cd7d32d4a4ce6057128
This commit is contained in:
parent
cf4cc65be6
commit
af724e0312
@ -112,6 +112,42 @@ class Event(object):
|
|||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
|
class Alarm(object):
|
||||||
|
"""Wrapped alarm object to hold converted values for this evaluator."""
|
||||||
|
|
||||||
|
TRAIT_TYPES = {
|
||||||
|
'none': 0,
|
||||||
|
'string': 1,
|
||||||
|
'integer': 2,
|
||||||
|
'float': 3,
|
||||||
|
'datetime': 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, alarm):
|
||||||
|
self.obj = alarm
|
||||||
|
self.id = alarm.alarm_id
|
||||||
|
self._parse_query()
|
||||||
|
|
||||||
|
def _parse_query(self):
|
||||||
|
self.query = []
|
||||||
|
for q in self.obj.rule.get('query', []):
|
||||||
|
if not q['field'].startswith('traits.'):
|
||||||
|
self.query.append(q)
|
||||||
|
continue
|
||||||
|
type_num = self.TRAIT_TYPES[q.get('type') or 'string']
|
||||||
|
field = q['field']
|
||||||
|
value = _sanitize_trait_value(q.get('value'), type_num)
|
||||||
|
op = COMPARATORS[q.get('op', 'eq')]
|
||||||
|
self.query.append({'field': field, 'value': value, 'op': op})
|
||||||
|
|
||||||
|
def fired_and_no_repeat(self):
|
||||||
|
return (not self.obj.repeat_actions and
|
||||||
|
self.obj.state == evaluator.ALARM)
|
||||||
|
|
||||||
|
def event_type_to_watch(self, event_type):
|
||||||
|
return fnmatch.fnmatch(event_type, self.obj.rule['event_type'])
|
||||||
|
|
||||||
|
|
||||||
class EventAlarmEvaluator(evaluator.Evaluator):
|
class EventAlarmEvaluator(evaluator.Evaluator):
|
||||||
|
|
||||||
def __init__(self, conf, notifier):
|
def __init__(self, conf, notifier):
|
||||||
@ -155,7 +191,7 @@ class EventAlarmEvaluator(evaluator.Evaluator):
|
|||||||
|
|
||||||
# TODO(r-mibu): Implement "changes-since" at the storage API and make
|
# TODO(r-mibu): Implement "changes-since" at the storage API and make
|
||||||
# this function update only alarms changed from the last access.
|
# this function update only alarms changed from the last access.
|
||||||
alarms = {a.alarm_id: a for a in
|
alarms = {a.alarm_id: Alarm(a) for a in
|
||||||
self._storage_conn.get_alarms(enabled=True,
|
self._storage_conn.get_alarms(enabled=True,
|
||||||
alarm_type='event',
|
alarm_type='event',
|
||||||
project=project)}
|
project=project)}
|
||||||
@ -181,28 +217,25 @@ class EventAlarmEvaluator(evaluator.Evaluator):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
LOG.debug('Evaluating alarm (id=%(a)s) triggered by event '
|
LOG.debug('Evaluating alarm (id=%(a)s) triggered by event '
|
||||||
'(message_id=%(e)s).',
|
'(message_id=%(e)s).', {'a': alarm.id, 'e': event.id})
|
||||||
{'a': alarm.alarm_id, 'e': event.id})
|
|
||||||
|
|
||||||
if not alarm.repeat_actions and alarm.state == evaluator.ALARM:
|
if alarm.fired_and_no_repeat():
|
||||||
LOG.debug('Skip evaluation of the alarm id=%s which have already '
|
LOG.debug('Skip evaluation of the alarm id=%s which have already '
|
||||||
'fired.', alarm.alarm_id)
|
'fired.', alarm.id)
|
||||||
return
|
return
|
||||||
|
|
||||||
event_pattern = alarm.rule['event_type']
|
if not alarm.event_type_to_watch(event.obj['event_type']):
|
||||||
if not fnmatch.fnmatch(event.obj['event_type'], event_pattern):
|
LOG.debug('Aborting evaluation of the alarm (id=%s) since '
|
||||||
LOG.debug('Aborting evaluation of the alarm (id=%s) due to '
|
'event_type is not matched.', alarm.id)
|
||||||
'uninterested event_type.', alarm.alarm_id)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _compare(condition):
|
def _compare(condition):
|
||||||
op = COMPARATORS[condition.get('op', 'eq')]
|
|
||||||
v = event.get_value(condition['field'])
|
v = event.get_value(condition['field'])
|
||||||
LOG.debug('Comparing value=%(v)s against condition=%(c)s .',
|
LOG.debug('Comparing value=%(v)s against condition=%(c)s .',
|
||||||
{'v': v, 'c': condition})
|
{'v': v, 'c': condition})
|
||||||
return op(v, condition['value'])
|
return condition['op'](v, condition['value'])
|
||||||
|
|
||||||
for condition in alarm.rule['query']:
|
for condition in alarm.query:
|
||||||
if not _compare(condition):
|
if not _compare(condition):
|
||||||
LOG.debug('Aborting evaluation of the alarm due to '
|
LOG.debug('Aborting evaluation of the alarm due to '
|
||||||
'unmet condition=%s .', condition)
|
'unmet condition=%s .', condition)
|
||||||
@ -216,9 +249,9 @@ class EventAlarmEvaluator(evaluator.Evaluator):
|
|||||||
state = evaluator.ALARM
|
state = evaluator.ALARM
|
||||||
reason = (_('Event (message_id=%(message)s) hit the query of alarm '
|
reason = (_('Event (message_id=%(message)s) hit the query of alarm '
|
||||||
'(id=%(alarm)s)') %
|
'(id=%(alarm)s)') %
|
||||||
{'message': event.id, 'alarm': alarm.alarm_id})
|
{'message': event.id, 'alarm': alarm.id})
|
||||||
reason_data = {'type': 'event', 'event': event.obj}
|
reason_data = {'type': 'event', 'event': event.obj}
|
||||||
self._refresh(alarm, state, reason, reason_data)
|
self._refresh(alarm.obj, state, reason, reason_data)
|
||||||
|
|
||||||
def _refresh(self, alarm, state, reason, reason_data):
|
def _refresh(self, alarm, state, reason, reason_data):
|
||||||
super(EventAlarmEvaluator, self)._refresh(alarm, state,
|
super(EventAlarmEvaluator, self)._refresh(alarm, state,
|
||||||
@ -226,7 +259,7 @@ class EventAlarmEvaluator(evaluator.Evaluator):
|
|||||||
|
|
||||||
project = alarm.project_id
|
project = alarm.project_id
|
||||||
if self.conf.event_alarm_cache_ttl and project in self.caches:
|
if self.conf.event_alarm_cache_ttl and project in self.caches:
|
||||||
self.caches[project]['alarms'][alarm.alarm_id].state = state
|
self.caches[project]['alarms'][alarm.alarm_id].obj.state = state
|
||||||
|
|
||||||
# NOTE(r-mibu): This method won't be used, but we have to define here in
|
# NOTE(r-mibu): This method won't be used, but we have to define here in
|
||||||
# order to overwrite the abstract method in the super class.
|
# order to overwrite the abstract method in the super class.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user