148 lines
4.8 KiB
Python
148 lines
4.8 KiB
Python
# Copyright 2016 - Nokia
|
|
#
|
|
# 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 vitrage.common.constants import DatasourceProperties as DSProps
|
|
from vitrage.common.constants import GraphAction
|
|
from vitrage.datasources.driver_base import DriverBase
|
|
from vitrage.utils import datetime as datetime_utils
|
|
|
|
LOG = log.getLogger(__name__)
|
|
|
|
|
|
class AlarmDriverBase(DriverBase):
|
|
def __init__(self):
|
|
super(DriverBase, self).__init__()
|
|
self.cache = dict()
|
|
|
|
def _vitrage_type(self):
|
|
"""Return the vitrage_type of the datasource """
|
|
pass
|
|
|
|
def _alarm_key(self, alarm):
|
|
"""Return a unique key of the alarm, to identify it in the cache """
|
|
pass
|
|
|
|
def _get_alarms(self):
|
|
"""Return the list of alarms of this plugin """
|
|
pass
|
|
|
|
def _enrich_alarms(self, alarms):
|
|
"""Optionally add more data to the alarms
|
|
|
|
:param alarms: list of alarms to be enriched
|
|
:return:
|
|
"""
|
|
pass
|
|
|
|
def _is_erroneous(self, alarm):
|
|
"""Check if the state of the alarm is erroneous
|
|
|
|
:param alarm:
|
|
:return: True/False based on the alarm state
|
|
"""
|
|
pass
|
|
|
|
def _status_changed(self, new_alarm, old_alarm):
|
|
"""Check if the status of the two alarms is different
|
|
|
|
:param alarm1:
|
|
:param alarm2:
|
|
:return: True/False based on the alarms states
|
|
"""
|
|
pass
|
|
|
|
def _is_valid(self, alarm):
|
|
"""Check if the alarm is valid
|
|
|
|
:param alarm: an alarm to check
|
|
:return: True/False
|
|
"""
|
|
pass
|
|
|
|
def get_all(self, datasource_action):
|
|
return self.make_pickleable(self._get_all_alarms(),
|
|
self._vitrage_type(),
|
|
datasource_action)
|
|
|
|
def get_changes(self, datasource_action):
|
|
return self.make_pickleable(self._get_changed_alarms(),
|
|
self._vitrage_type(),
|
|
datasource_action)
|
|
|
|
def _get_all_alarms(self):
|
|
alarms = self._get_alarms()
|
|
self._enrich_alarms(alarms)
|
|
return self._filter_and_cache_alarms(
|
|
alarms,
|
|
self._filter_get_erroneous)
|
|
|
|
def _get_changed_alarms(self):
|
|
alarms = self._get_alarms()
|
|
self._enrich_alarms(alarms)
|
|
return self._filter_and_cache_alarms(
|
|
alarms,
|
|
self._filter_get_change)
|
|
|
|
def _filter_and_cache_alarms(self, alarms, filter_):
|
|
alarms_to_update = []
|
|
now = datetime_utils.utcnow(False)
|
|
|
|
for alarm in alarms:
|
|
alarm_key = self._alarm_key(alarm)
|
|
old_alarm = self.cache.get(alarm_key, (None, None))[0]
|
|
if self._filter_and_cache_alarm(alarm, old_alarm, filter_, now):
|
|
alarms_to_update.append(alarm)
|
|
|
|
# add alarms that were deleted
|
|
# (i.e. the alarm definition was deleted from the datasource)
|
|
values = list(self.cache.values())
|
|
for cached_alarm, timestamp in values:
|
|
if self._is_erroneous(cached_alarm) and timestamp is not now:
|
|
LOG.debug('deleting cached_alarm %s', cached_alarm)
|
|
cached_alarm[DSProps.EVENT_TYPE] = GraphAction.DELETE_ENTITY
|
|
alarms_to_update.append(cached_alarm)
|
|
self.cache.pop(self._alarm_key(cached_alarm))
|
|
|
|
return alarms_to_update
|
|
|
|
def _filter_get_valid(self, alarm, _):
|
|
return alarm if self._is_valid(alarm) else None
|
|
|
|
def _filter_get_erroneous(self, alarm, old_alarm):
|
|
return alarm \
|
|
if self._is_valid(alarm) and \
|
|
(self._is_erroneous(alarm) or self._is_erroneous(old_alarm)) \
|
|
else None
|
|
|
|
def _filter_get_change(self, alarm, old_alarm):
|
|
if not self._is_valid(alarm):
|
|
return None
|
|
if self._status_changed(alarm, old_alarm):
|
|
return alarm
|
|
elif not old_alarm and self._is_erroneous(alarm):
|
|
return alarm
|
|
else:
|
|
return None
|
|
|
|
def _filter_and_cache_alarm(self, alarm, old_alarm, filter_, time):
|
|
ret = alarm if filter_(alarm, old_alarm) else None
|
|
self.cache[self._alarm_key(alarm)] = alarm, time
|
|
return ret
|
|
|
|
def _old_alarm(self, event):
|
|
alarm_key = self._alarm_key(event)
|
|
return self.cache.get(alarm_key, (None, None))[0]
|