/usr/lib/python2.7/dist-packages/aodh/evaluator/combination.py is in python-aodh 2.0.0-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | #
# Copyright 2013 eNovance <licensing@enovance.com>
#
# Authors: Mehdi Abaakouk <mehdi.abaakouk@enovance.com>
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import log
from six import moves
from aodh import evaluator
from aodh.i18n import _, _LE
LOG = log.getLogger(__name__)
COMPARATORS = {'and': all, 'or': any}
class CombinationEvaluator(evaluator.Evaluator):
def _get_alarm_state(self, alarm_id):
try:
alarms = self._storage_conn.get_alarms(alarm_id=alarm_id)
except Exception:
LOG.exception(_LE('alarm %s retrieval failed'), alarm_id)
return None
if not alarms:
LOG.error(_LE("alarm %s doesn't exists anymore"), alarm_id)
return None
return list(alarms)[0].state
def _sufficient_states(self, alarm, states):
"""Check for the sufficiency of the data for evaluation.
Ensure that there is sufficient data for evaluation,
transitioning to unknown otherwise.
"""
# note(sileht): alarm can be evaluated only with
# stable state of other alarm
alarms_missing_states = [alarm_id for alarm_id, state in states
if not state or state == evaluator.UNKNOWN]
sufficient = len(alarms_missing_states) == 0
if not sufficient and alarm.rule['operator'] == 'or':
# if operator is 'or' and there is one alarm, then the combinated
# alarm's state should be 'alarm'
sufficient = bool([alarm_id for alarm_id, state in states
if state == evaluator.ALARM])
if not sufficient and alarm.state != evaluator.UNKNOWN:
reason = (_('Alarms %(alarm_ids)s'
' are in unknown state') %
{'alarm_ids': ",".join(alarms_missing_states)})
reason_data = self._reason_data(alarms_missing_states)
self._refresh(alarm, evaluator.UNKNOWN, reason, reason_data)
return sufficient
@staticmethod
def _reason_data(alarm_ids):
"""Create a reason data dictionary for this evaluator type."""
return {'type': 'combination', 'alarm_ids': alarm_ids}
@classmethod
def _reason(cls, alarm, state, underlying_states):
"""Fabricate reason string."""
transition = alarm.state != state
alarms_to_report = [alarm_id for alarm_id, alarm_state
in underlying_states
if alarm_state == state]
reason_data = cls._reason_data(alarms_to_report)
if transition:
return (_('Transition to %(state)s due to alarms'
' %(alarm_ids)s in state %(state)s') %
{'state': state,
'alarm_ids': ",".join(alarms_to_report)}), reason_data
return (_('Remaining as %(state)s due to alarms'
' %(alarm_ids)s in state %(state)s') %
{'state': state,
'alarm_ids': ",".join(alarms_to_report)}), reason_data
def _transition(self, alarm, underlying_states):
"""Transition alarm state if necessary."""
op = alarm.rule['operator']
if COMPARATORS[op](s == evaluator.ALARM
for __, s in underlying_states):
state = evaluator.ALARM
else:
state = evaluator.OK
continuous = alarm.repeat_actions
reason, reason_data = self._reason(alarm, state, underlying_states)
if alarm.state != state or continuous:
self._refresh(alarm, state, reason, reason_data)
def evaluate(self, alarm):
if not self.within_time_constraint(alarm):
LOG.debug('Attempted to evaluate alarm %s, but it is not '
'within its time constraint.', alarm.alarm_id)
return
states = zip(alarm.rule['alarm_ids'],
moves.map(self._get_alarm_state, alarm.rule['alarm_ids']))
# states is consumed more than once, we need a list
states = list(states)
if self._sufficient_states(alarm, states):
self._transition(alarm, states)
|