Пример #1
0
    def a_snooze(self, event, action, name):
        """
        Snooze event checks

        :param dict event: event to be snoozed
        :param dict action: action
        :param str name: name of the rule

        :returns: True if a snooze has been sent, False otherwise
        :rtype: boolean
        """
        if event.get('event_type') == 'snooze':
            return False
        # Only check events can trigger an auto-snooze
        if event.get('event_type') != 'check':
            return False

        # A check OK cannot trigger an auto-snooze
        if event.get('state') == 0:
            return False

        # Alerts manager caching
        if not hasattr(self, 'am'):
            self.am = Alerts(*Alerts.provide_default_basics())

        # Context manager caching
        if not hasattr(self, 'cm'):
            self.cm = ContextGraph(self.logger)

        entity_id = self.cm.get_id(event)

        current_alarm = self.am.get_current_alarm(entity_id)
        if current_alarm is None:
            snooze = {
                'connector': event.get('connector', ''),
                'connector_name': event.get('connector_name', ''),
                'source_type': event.get('source_type', ''),
                'component': event.get('component', ''),
                'event_type': 'snooze',
                'duration': action['duration'],
                'author': 'event_filter',
                'output': 'Auto snooze generated by rule "{}"'.format(name),
                'timestamp': int(time.time())
            }

            if event.get('resource', ''):
                snooze['resource'] = event['resource']

            try:
                self.work_amqp_publisher.direct_event(snooze,
                                                      'Engine_event_filter')
            except Exception as e:
                self.logger.exception("Unable to send snooze event")

            return True

        return False
Пример #2
0
def exports(ws):
    el_kwargs = {'el_storage': EventsLog.provide_default_basics()}
    manager = singleton_per_scope(EventsLog, kwargs=el_kwargs)
    am = Alerts(*Alerts.provide_default_basics())

    @ws.application.post('/api/v2/event')
    def send_event_post():
        try:
            events = request.json
        except ValueError as verror:
            return gen_json_error(
                {'description': 'malformed JSON : {0}'.format(verror)},
                HTTP_ERROR)

        if events is None:
            return gen_json_error({'description': 'nothing to return'},
                                  HTTPError)

        return send_events(ws, am, events)

    @route(ws.application.post, name='event', payload=['event', 'url'])
    @route(ws.application.put, name='event', payload=['event', 'url'])
    def send_event(event, url=None):
        if ws.enable_crossdomain_send_events and url is not None:
            payload = {'event': json.dumps(event)}

            response = requests.post(url, data=payload)

            if response.status_code != 200:
                api_response = json.loads(response.text)

                return (api_response['data'], api_response['total'])

            return HTTPError(response.status_code, response.text)

        return send_events(ws, am, event)

    @route(ws.application.get,
           name='eventslog/count',
           payload=['tstart', 'tstop', 'limit', 'select'])
    def get_event_count_per_day(tstart, tstop, limit=100, select={}):
        """ get eventslog log count for each days in a given period
            :param tstart: timestamp of the begin period
            :param tstop: timestamp of the end period
            :param limit: limit the count number per day
            :param select: filter for eventslog collection
            :return: list in which each item contains an interval and the
            related count
            :rtype: list
        """

        results = manager.get_eventlog_count_by_period(tstart,
                                                       tstop,
                                                       limit=limit,
                                                       query=select)

        return results
Пример #3
0
    def a_snooze(self, event, action, name):
        """
        Snooze event checks

        :param dict event: event to be snoozed
        :param dict action: action
        :param str name: name of the rule

        :returns: True if a snooze has been sent, False otherwise
        :rtype: boolean
        """
        if event.get('event_type') == 'snooze':
            return False
        # Only check events can trigger an auto-snooze
        if event.get('event_type') != 'check':
            return False

        # A check OK cannot trigger an auto-snooze
        if event.get('state') == 0:
            return False

        # Alerts manager caching
        if not hasattr(self, 'am'):
            self.am = Alerts(*Alerts.provide_default_basics())

        # Context manager caching
        if not hasattr(self, 'cm'):
            self.cm = ContextGraph(self.logger)

        entity_id = self.cm.get_id(event)

        current_alarm = self.am.get_current_alarm(entity_id)
        if current_alarm is None:
            snooze = {
                'connector': event.get('connector', ''),
                'connector_name': event.get('connector_name', ''),
                'source_type': event.get('source_type', ''),
                'component': event.get('component', ''),
                'event_type': 'snooze',
                'duration': action['duration'],
                'author': 'event_filter',
                'output': 'Auto snooze generated by rule "{}"'.format(name),
                'timestamp': int(time.time())
            }

            if event.get('resource', ''):
                snooze['resource'] = event['resource']

            try:
                self.work_amqp_publisher.direct_event(
                    snooze, 'Engine_event_filter')
            except Exception as e:
                self.logger.exception("Unable to send snooze event")

            return True

        return False
Пример #4
0
    def setUp(self):
        self.logger = logging.getLogger('alerts')

        self.alerts_storage = Middleware.get_middleware_by_uri(
            'storage-periodical-testalarm://')
        self.config_storage = Middleware.get_middleware_by_uri(
            'storage-default-testconfig://')
        self.config_storage.put_element(element={
            '_id': 'test_config',
            'crecord_type': 'statusmanagement',
            'bagot_time': 3600,
            'bagot_freq': 10,
            'stealthy_time': 300,
            'restore_event': True,
            'auto_snooze': False,
            'snooze_default_time': 300,
        },
                                        _id='test_config')
        self.filter_storage = Middleware.get_middleware_by_uri(
            'storage-default-testalarmfilter://')

        self.context_graph_storage = Middleware.get_middleware_by_uri(
            'storage-default-testentities://')
        self.cg_manager = ContextGraph(self.logger)
        self.cg_manager.ent_storage = self.context_graph_storage
        self.watcher_manager = Watcher()

        conf = Configuration.load(Alerts.CONF_PATH, Ini)
        filter_ = {'crecord_type': 'statusmanagement'}
        self.config_data = EtherealData(collection=MongoCollection(
            self.config_storage._backend),
                                        filter_=filter_)

        self.event_publisher = Mock(spec=StatEventPublisher)

        self.manager = Alerts(config=conf,
                              logger=self.logger,
                              alerts_storage=self.alerts_storage,
                              config_data=self.config_data,
                              filter_storage=self.filter_storage,
                              context_graph=self.cg_manager,
                              watcher=self.watcher_manager,
                              event_publisher=self.event_publisher)
Пример #5
0
    def a_snooze(self, event, action, name):
        """
        Snooze event checks

        :param dict event: event to be snoozed
        :param dict action: action
        :param str name: name of the rule

        :returns: True if a snooze has been sent, False otherwise
        :rtype: boolean
        """
        # Only check events can trigger an auto-snooze
        if event['event_type'] != 'check':
            return False

        # A check OK cannot trigger an auto-snooze
        if event['state'] == 0:
            return False

        # Alerts manager caching
        if not hasattr(self, 'am'):
            self.am = Alerts()

        # Context manager caching
        if not hasattr(self, 'cm'):
            self.cm = Context()

        entity = self.cm.get_entity(event)
        entity_id = self.cm.get_entity_id(entity)

        current_alarm = self.am.get_current_alarm(entity_id)
        if current_alarm is None:
            snooze = {
                'connector': event.get('connector', ''),
                'connector_name': event.get('connector_name', ''),
                'source_type': event.get('source_type', ''),
                'component': event.get('component', ''),
                'event_type': 'snooze',
                'duration': action['duration'],
                'author': 'event_filter',
                'output': 'Auto snooze generated by rule "{}"'.format(name),
            }

            if 'resource' in event:
                snooze['resource'] = event['resource']

            publish(event=snooze, publisher=self.amqp)

            return True

        return False
Пример #6
0
# ---------------------------------

from __future__ import unicode_literals

from canopsis.alarms.adapters import AlarmAdapter
from canopsis.alarms.services import AlarmService
from canopsis.alerts.manager import Alerts
from canopsis.alerts.reader import AlertsReader
from canopsis.task.core import register_task
from canopsis.watcher.manager import Watcher
from canopsis.common.mongo_store import MongoStore

# import this module so tasks are registered in canopsis.tasks.core
import canopsis.alerts.tasks as __alerts_tasks

work_alerts_manager = Alerts(*Alerts.provide_default_basics())
beat_alerts_manager = Alerts(*Alerts.provide_default_basics())
alertsreader_manager = AlertsReader(*AlertsReader.provide_default_basics())

mongo_store = MongoStore.get_default()


@register_task
def event_processing(engine, event, alertsmgr=None, **kwargs):
    """
    AMQP Event processing.
    """
    if alertsmgr is None:
        alertsmgr = work_alerts_manager

    encoded_event = {}
Пример #7
0
from bottle import request
import json as j
import os
from uuid import uuid4

from canopsis.common import root_path
from canopsis.common.ws import route
from canopsis.alerts.manager import Alerts
from canopsis.common.converters import id_filter
from canopsis.confng import Configuration, Ini
from canopsis.context_graph.import_ctx import ImportKey, Manager
from canopsis.context_graph.manager import ContextGraph
from canopsis.webcore.utils import gen_json, gen_json_error, HTTP_ERROR

import_col_man = Manager(Configuration.load(Manager.CONF_FILE, Ini))
alerts_manager = Alerts(*Alerts.provide_default_basics())


__IMPORT_ID = "import_id"
__ERROR = "error"
__OTHER_ERROR = "An error occured : {0}."
__EVT_ERROR = "error while sending a event to the task : {0}."
__STORE_ERROR = "Impossible to store the import: {0}."


event_body = {ImportKey.EVT_IMPORT_UUID: None,
              ImportKey.EVT_JOBID: None}

RK = "task_importctx"

Пример #8
0
class BaseTest(TestCase):

    def setUp(self):
        self.logger = logging.getLogger('alerts')

        self.alerts_storage = Middleware.get_middleware_by_uri(
            'storage-periodical-testalarm://'
        )
        self.config_storage = Middleware.get_middleware_by_uri(
            'storage-default-testconfig://'
        )
        self.config_storage.put_element(
            element={
                '_id': 'test_config',
                'crecord_type': 'statusmanagement',
                'bagot_time': 3600,
                'bagot_freq': 10,
                'stealthy_time': 300,
                'restore_event': True,
                'auto_snooze': False,
                'snooze_default_time': 300,
            },
            _id='test_config'
        )
        self.filter_storage = Middleware.get_middleware_by_uri(
            'storage-default-testalarmfilter://'
        )

        self.context_graph_storage = Middleware.get_middleware_by_uri(
            'storage-default-testentities://'
        )
        self.cg_manager = ContextGraph(self.logger)
        self.cg_manager.ent_storage = self.context_graph_storage
        self.watcher_manager = Watcher()

        conf = Configuration.load(Alerts.CONF_PATH, Ini)
        filter_ = {'crecord_type': 'statusmanagement'}
        self.config_data = EtherealData(
            collection=MongoCollection(self.config_storage._backend),
            filter_=filter_)

        self.event_publisher = Mock(spec=StatEventPublisher)


        mongo = MongoStore.get_default()
        collection = mongo.get_collection("default_testpbehavior")
        pb_collection = MongoCollection(collection)

        logger = Logger.get('test_pb', None, output_cls=OutputNull)

        config = Configuration.load(PBehaviorManager.CONF_PATH, Ini)

        self.pbm = PBehaviorManager(config=config,
                                    logger=logger,
                                    pb_collection=pb_collection)

        self.manager = Alerts(config=conf,
                              logger=self.logger,
                              alerts_storage=self.alerts_storage,
                              config_data=self.config_data,
                              filter_storage=self.filter_storage,
                              context_graph=self.cg_manager,
                              watcher=self.watcher_manager,
                              event_publisher=self.event_publisher,
                              pbehavior=self.pbm)

    def tearDown(self):
        """Teardown"""
        self.alerts_storage.remove_elements()
        self.config_storage.remove_elements()
        self.filter_storage.remove_elements()
        self.context_graph_storage.remove_elements()

    def gen_fake_alarm(self, update={}, moment=None):
        """
        Generate a fake alarm/value.
        """
        if moment is None:
            moment = int(time.mktime(datetime.now().timetuple()))

        alarm_id = '/fake/alarm/id'
        alarm = self.manager.make_alarm(
            alarm_id,
            {
                'connector': 'fake-connector',
                'connector_name': 'fake-connector-name',
                'component': 'c',
                'output': 'out',
                'timestamp': moment
            }
        )

        value = alarm[self.manager.alerts_storage.VALUE]
        value[AlarmField.state.value] = {
            't': moment,
            'val': Check.MINOR
        }
        value[AlarmField.steps.value] = [
            {
                '_t': 'stateinc',
                't': moment,
                'a': 'fake-author',
                'm': 'fake-message',
                'val': Check.MINOR
            }
        ]

        dictio = merge_two_dicts(alarm, update)

        return dictio, value

    def gen_alarm_filter(self, update={}, storage=None):
        """
        Generate a standard alarm filter.
        """
        base = {
            AlarmFilter.LIMIT: 180.0,
            AlarmFilter.FILTER: '',
            AlarmFilter.CONDITION: {},
            AlarmFilter.TASKS: ['alerts.systemaction.state_increase'],
        }

        dictio = merge_two_dicts(base, update)

        return AlarmFilter(dictio, logger=self.logger, storage=storage)
Пример #9
0
def exports(ws):

    ws.application.router.add_filter('id_filter', id_filter)

    context_manager = ContextGraph(ws.logger)
    am = Alerts(*Alerts.provide_default_basics())
    ar = AlertsReader(*AlertsReader.provide_default_basics())
    ma_rule_manager = MetaAlarmRuleManager(
        *MetaAlarmRuleManager.provide_default_basics())
    pbm = PBehaviorManager(*PBehaviorManager.provide_default_basics())

    @route(ws.application.get,
           name='alerts/get-alarms',
           payload=[
               'authkey', 'tstart', 'tstop', 'opened', 'resolved', 'lookups',
               'filter', 'search', 'sort_key', 'sort_dir', 'skip', 'limit',
               'with_steps', 'natural_search', 'active_columns',
               'hide_resources', 'with_consequences', 'with_causes',
               'correlation'
           ])
    def get_alarms(authkey=None,
                   tstart=None,
                   tstop=None,
                   opened=True,
                   resolved=False,
                   lookups=[],
                   filter={},
                   search='',
                   sort_key='opened',
                   sort_dir='DESC',
                   skip=0,
                   limit=None,
                   with_steps=False,
                   natural_search=False,
                   active_columns=None,
                   hide_resources=False,
                   with_consequences=False,
                   with_causes=False,
                   correlation=False):
        """
        Return filtered, sorted and paginated alarms.

        :param tstart: Beginning timestamp of requested period
        :param tstop: End timestamp of requested period
        :type tstart: int or None
        :type tstop: int or None

        :param bool opened: If True, consider alarms that are currently opened
        :param bool resolved: If True, consider alarms that have been resolved

        :param list lookups: List of extra columns to compute for each
          returned alarm. Extra columns are "pbehaviors".

        :param dict filter: Mongo filter. Keys are UI column names.
        :param str search: Search expression in custom DSL

        :param str sort_key: Name of the column to sort
        :param str sort_dir: Either "ASC" or "DESC"

        :param int skip: Number of alarms to skip (pagination)
        :param int limit: Maximum number of alarms to return

        :param list active_columns: list of active columns on the brick
        listalarm .

        :param bool hide_resources: hide_resources if component has an alarm

        :returns: List of sorted alarms + pagination informations
        :rtype: dict
        """
        if isinstance(search, int):
            search = str(search)

        try:
            alarms = ar.get(tstart=tstart,
                            tstop=tstop,
                            opened=opened,
                            resolved=resolved,
                            lookups=lookups,
                            filter_=filter,
                            search=search.strip(),
                            sort_key=sort_key,
                            sort_dir=sort_dir,
                            skip=skip,
                            limit=limit,
                            with_steps=with_steps,
                            natural_search=natural_search,
                            active_columns=active_columns,
                            hide_resources=hide_resources,
                            with_consequences=with_consequences,
                            correlation=correlation)
        except OperationFailure as of_err:
            message = 'Operation failure on get-alarms: {}'.format(of_err)
            raise WebServiceError(message)

        alarms_ids, consequences_children = [], []
        alarm_children = {'alarms': [], 'total': 0}
        for alarm in alarms['alarms']:
            if with_consequences:
                consequences_children.extend(
                    alarm.get('consequences', {}).get('data', []))
            elif with_causes and alarm.get('v') and alarm['v'].get('parents'):
                consequences_children.extend(alarm['v']['parents'])
            tmp_id = alarm.get('d')
            if tmp_id:
                alarms_ids.append(tmp_id)
        entities = context_manager.get_entities_by_id(alarms_ids,
                                                      with_links=False)

        entity_dict = {}
        for entity in entities:
            entity_dict[entity.get('_id')] = entity

        if consequences_children:
            alarm_children = ar.get(
                tstart=tstart,
                tstop=tstop,
                opened=True,
                resolved=True,
                lookups=lookups,
                filter_={'d': {
                    '$in': consequences_children
                }},
                sort_key=sort_key,
                sort_dir=sort_dir,
                skip=skip,
                limit=None,
                natural_search=natural_search,
                active_columns=active_columns,
                hide_resources=hide_resources,
                correlation=correlation,
                consequences_children=True)

        list_alarm = []
        rule_ids = set()
        if 'rules' in alarms:
            for alarm_rules in alarms['rules'].values():
                for v in alarm_rules:
                    rule_ids.add(v)
            named_rules = ma_rule_manager.read_rules_with_names(list(rule_ids))
            for d, alarm_rules in alarms['rules'].items():
                alarm_named_rules = []
                for v in alarm_rules:
                    alarm_named_rules.append({
                        'id': v,
                        'name': named_rules.get(v, "")
                    })
                alarms['rules'][d] = alarm_named_rules
        else:
            alarms['rules'] = dict()

        children_ent_ids = set()
        for alarm in alarms['alarms']:
            rules = alarms['rules'].get(alarm['d'], []) if 'd' in alarm and 'v' in alarm and \
                alarm['v'].get('parents') else None
            if rules:
                if with_causes:
                    alarm['causes'] = {
                        'total': len(alarm_children['alarms']),
                        'data': alarm_children['alarms'],
                    }
                    for al_child in alarm_children['alarms']:
                        children_ent_ids.add(al_child['d'])
                else:
                    alarm['causes'] = {
                        'total': len(rules),
                        'rules': rules,
                    }

            if alarm.get('v') is None:
                alarm['v'] = dict()
            if alarm.get('v').get('meta'):
                del alarm['v']['meta']

            if isinstance(alarm.get('rule'),
                          basestring) and alarm['rule'] != "":
                alarm['rule'] = {
                    'id': alarm['rule'],
                    'name': named_rules.get(alarm['rule'], alarm['rule'])
                }

            now = int(time())

            alarm_end = alarm.get('v', {}).get('resolved')
            if not alarm_end:
                alarm_end = now
            alarm["v"]['duration'] = (
                alarm_end - alarm.get('v', {}).get('creation_date', alarm_end))

            state_time = alarm.get('v', {}).get('state', {}).get('t', now)
            alarm["v"]['current_state_duration'] = now - state_time
            tmp_entity_id = alarm['d']

            if alarm['d'] in entity_dict:
                alarm[
                    'links'] = context_manager.enrich_links_to_entity_with_alarm(
                        entity_dict[alarm['d']], alarm)

                # TODO: 'infos' is already present in entity.
                # Remove this one if unused.
                if tmp_entity_id in entity_dict:
                    data = entity_dict[alarm['d']]['infos']
                    if alarm.get('infos'):
                        alarm['infos'].update(data)
                    else:
                        alarm['infos'] = data

            alarm = compat_go_crop_states(alarm)

            if with_consequences and isinstance(
                    alarm.get('consequences'),
                    dict) and alarm_children['total'] > 0:
                map(
                    lambda al_ch: al_ch.update(
                        {'causes': {
                            'rules': [alarm['rule']],
                            'total': 1
                        }}), alarm_children['alarms'])
                alarm['consequences']['data'] = alarm_children['alarms']
                alarm['consequences']['total'] = alarm_children['total']
                for al_child in alarm_children['alarms']:
                    children_ent_ids.add(al_child['d'])

            list_alarm.append(alarm)

        if children_ent_ids:
            children_entities = context_manager.get_entities_by_id(
                list(children_ent_ids), with_links=False)
            for entity in children_entities:
                entity_dict[entity.get('_id')] = entity

            for alarm in alarms['alarms']:
                for cat in ('causes', 'consequences'):
                    if cat in alarm and alarm[cat].get('data'):
                        for child in alarm[cat]['data']:
                            if child['d'] in entity_dict:
                                child[
                                    'links'] = context_manager.enrich_links_to_entity_with_alarm(
                                        entity_dict[child['d']], child)

        del alarms['rules']
        alarms['alarms'] = list_alarm

        return alarms

    @route(ws.application.get,
           name='alerts/get-counters',
           payload=[
               'tstart', 'tstop', 'opened', 'resolved', 'lookups', 'filter',
               'search', 'sort_key', 'sort_dir', 'skip', 'limit', 'with_steps',
               'natural_search', 'active_columns', 'hide_resources'
           ])
    def get_counters(tstart=None,
                     tstop=None,
                     opened=True,
                     resolved=False,
                     lookups=[],
                     filter={},
                     search='',
                     sort_key='opened',
                     sort_dir='DESC',
                     skip=0,
                     limit=None,
                     with_steps=False,
                     natural_search=False,
                     active_columns=None,
                     hide_resources=False):

        if isinstance(search, int):
            search = str(search)

        try:
            alarms = ar.get(tstart=tstart,
                            tstop=tstop,
                            opened=opened,
                            resolved=resolved,
                            lookups=lookups,
                            filter_=filter,
                            search=search.strip(),
                            sort_key=sort_key,
                            sort_dir=sort_dir,
                            skip=skip,
                            limit=limit,
                            with_steps=with_steps,
                            natural_search=natural_search,
                            active_columns=active_columns,
                            hide_resources=hide_resources,
                            add_pbh_filter=False)
        except OperationFailure as of_err:
            message = 'Operation failure on get-alarms: {}'.format(of_err)
            raise WebServiceError(message)

        counters = {
            "total": len(alarms['alarms']),
            "total_active": 0,
            "snooze": 0,
            "ack": 0,
            "ticket": 0,
            "pbehavior_active": 0
        }

        alarms_ids = []
        for alarm in alarms['alarms']:
            tmp_id = alarm.get('d')
            if tmp_id:
                alarms_ids.append(tmp_id)
        entities = context_manager.get_entities_by_id(alarms_ids,
                                                      with_links=True)
        entity_id = []
        for entity in entities:
            _id = entity.get('_id')
            if _id:
                entity_id.append(_id)

        active_pbh = pbm.get_active_pbehaviors_on_entities(entity_id)
        enabled_pbh_entity_dict = set()
        for pbh in active_pbh:
            if pbh[PBehavior.ENABLED]:
                for eid in pbh.get(PBehavior.EIDS, []):
                    if eid in entity_id:
                        enabled_pbh_entity_dict.add(eid)

        pbehavior_active_snooze = 0

        for alarm in alarms['alarms']:
            v = alarm.get('v')
            snoozed = False
            if isinstance(v, dict):
                if v.get('ack', {}).get('_t') == 'ack':
                    counters['ack'] += 1
                snoozed = v.get('snooze', {}).get('_t') == 'snooze'
                if snoozed:
                    counters['snooze'] += 1
                if v.get('ticket',
                         {}).get('_t') in ['declareticket', 'assocticket']:
                    counters['ticket'] += 1
            d = alarm.get('d')
            if d in enabled_pbh_entity_dict:
                counters['pbehavior_active'] += 1
                if snoozed:
                    pbehavior_active_snooze += 1

        counters['total_active'] = counters['total'] - counters['pbehavior_active'] - counters['snooze'] + \
            pbehavior_active_snooze
        return counters

    @route(ws.application.get,
           name='alerts/search/validate',
           payload=['expression'])
    def validate_search(expression):
        """
        Tell if a search expression is valid from a grammatical propespective.

        :param str expression: Search expression

        :returns: True if valid, False otherwise
        :rtype: bool
        """

        try:
            ar.interpret_search(expression)

        except Exception:
            return False

        else:
            return True

    @route(
        ws.application.get,
        name='alerts/count',
        payload=['start', 'stop', 'limit', 'select'],
    )
    def count_by_period(
        start,
        stop,
        limit=100,
        select=None,
    ):
        """
        Count alarms that have been opened during (stop - start) period.

        :param start: Beginning timestamp of period
        :type start: int

        :param stop: End timestamp of period
        :type stop: int

        :param limit: Counts cannot exceed this value
        :type limit: int

        :param query: Custom mongodb filter for alarms
        :type query: dict

        :return: List in which each item contains a time interval and the
                 related count
        :rtype: list
        """

        return ar.count_alarms_by_period(
            start,
            stop,
            limit=limit,
            query=select,
        )

    @route(
        ws.application.get,
        name='alerts/get-current-alarm',
        payload=['entity_id'],
    )
    def get_current_alarm(entity_id):
        """
        Get current unresolved alarm for a entity.

        :param str entity_id: Entity ID of the alarm

        :returns: Alarm as dict if something is opened, else None
        """

        return am.get_current_alarm(entity_id)

    @ws.application.get('/api/v2/alerts/filters/<entity_id:id_filter>')
    def get_filter(entity_id):
        """
        Get all filters linked with an alarm.

        :param str entity_id: Entity ID of the alarm-filter

        :returns: a list of <AlarmFilter>
        """
        filters = am.alarm_filters.get_filter(entity_id)
        if filters is None:
            return gen_json_error({'description': 'nothing to return'},
                                  HTTP_ERROR)

        return gen_json([l.serialize() for l in filters])

    @ws.application.post('/api/v2/alerts/filters')
    def create_filter():
        """
        Create a new alarm filter.

        :returns: an <AlarmFilter>
        """
        # element is a full AlarmFilter (dict) to insert
        element = request.json

        if element is None:
            return gen_json_error({'description': 'nothing to insert'},
                                  HTTP_ERROR)

        new = am.alarm_filters.create_filter(element=element)
        new.save()

        return gen_json(new.serialize())

    @ws.application.put('/api/v2/alerts/filters/<entity_id:id_filter>')
    def update_filter(entity_id):
        """
        Update an existing alam filter.

        :param entity_id: Entity ID of the alarm-filter
        :type entity_id: str
        :returns: <AlarmFilter>
        :rtype: dict
        """
        dico = request.json

        if dico is None or not isinstance(dico, dict) or len(dico) <= 0:
            return gen_json_error({'description': 'wrong update dict'},
                                  HTTP_ERROR)

        af = am.alarm_filters.update_filter(filter_id=entity_id, values=dico)
        if not isinstance(af, AlarmFilter):
            return gen_json_error({'description': 'failed to update filter'},
                                  HTTP_ERROR)

        return gen_json(af.serialize())

    @ws.application.delete('/api/v2/alerts/filters/<entity_id:id_filter>')
    def delete_id(entity_id):
        """
        Delete a filter, based on his id.

        :param entity_id: Entity ID of the alarm-filter
        :type entity_id: str

        :rtype: dict
        """
        ws.logger.info('Delete alarm-filter : {}'.format(entity_id))

        return gen_json(am.alarm_filters.delete_filter(entity_id))

    @ws.application.delete('/api/v2/alerts/<mfilter>')
    def delete_filter(mfilter):
        """
        :param str mfilter: mongo filter
        :rtype: dict
        """
        return gen_json(ar.alarm_storage._backend.remove(json.loads(mfilter)))

    @ws.application.post('/api/v2/alerts/done')
    def done_action():
        """
        Trigger done action.

        For json payload, see doc/docs/fr/guide_developpeur/apis/v2/alerts.md

        :rtype: dict
        """
        dico = request.json

        if dico is None or not isinstance(dico, dict) or len(dico) <= 0:
            return gen_json_error({'description': 'wrong done dict'},
                                  HTTP_ERROR)

        author = dico.get(am.AUTHOR)
        event = forger(event_type=Check.EVENT_TYPE,
                       author=author,
                       connector=dico.get('connector'),
                       connector_name=dico.get('connector_name'),
                       component=dico.get('component'),
                       output=dico.get('comment'))
        if dico.get('source_type', None) == 'resource':
            event['resource'] = dico['resource']
            event['source_type'] = 'resource'
        ws.logger.debug('Received done action: {}'.format(event))

        entity_id = am.context_manager.get_id(event)
        retour = am.execute_task('alerts.useraction.done',
                                 event=event,
                                 author=author,
                                 entity_id=entity_id)
        return gen_json(retour)
Пример #10
0
class engine(Engine):
    etype = 'event_filter'

    def __init__(self, *args, **kargs):
        super(engine, self).__init__(*args, **kargs)

        account = Account(user="******", group="root")
        self.storage = get_storage(logging_level=self.logging_level,
                                   account=account)
        self.derogations = []
        self.name = kargs['name']
        self.drop_event_count = 0
        self.pass_event_count = 0

    def pre_run(self):
        self.beat()

    def time_conditions(self, derogation):
        conditions = derogation.get('time_conditions', None)

        if not isinstance(conditions, list):
            self.logger.error(("Invalid time conditions field in '%s': %s"
                               % (derogation['_id'], conditions)))
            self.logger.debug(derogation)
            return False

        result = False

        now = time()
        for condition in conditions:
            if (condition['type'] == 'time_interval'
                    and condition['startTs']
                    and condition['stopTs']):
                always = condition.get('always', False)

                if always:
                    self.logger.debug(" + 'time_interval' is 'always'")
                    result = True

                elif (now >= condition['startTs']
                      and now < condition['stopTs']):
                    self.logger.debug(" + 'time_interval' Match")
                    result = True

        return result

    def a_override(self, event, action):
        """Override a field from event or add a new one if it does not have
        one.
        """

        afield = action.get('field', None)
        avalue = action.get('value', None)

        # This must be a hard check because value can be a boolean or a null
        # integer
        if afield is None or avalue is None:
            self.logger.error(
                "Malformed action ('field' and 'value' required): {}".format(
                    action
                )
            )
            return False

        if afield not in event:
            self.logger.debug("Overriding: '{}' -> '{}'".format(
                afield, avalue))
            event[afield] = avalue
            return True

        # afield is in event
        if not isinstance(avalue, list):
            if isinstance(event[afield], list):
                self.logger.debug("Appending: '{}' to '{}'".format(
                    avalue, afield))
                event[afield].append(avalue)

            else:
                self.logger.debug("Overriding: '{}' -> '{}'".format(
                    afield, avalue))
                event[afield] = avalue

            return True

        else:
            # operation field is supported only for list values
            op = action.get('operation', 'append')

            if op == 'override':
                self.logger.debug("Overriding: '{}' -> '{}'".format(
                    afield, avalue))
                event[afield] = avalue
                return True

            elif op == 'append':
                self.logger.debug("Appending: '{}' to '{}'".format(
                    avalue, afield))

                if isinstance(event[afield], list):
                    event[afield] += avalue
                else:
                    event[afield] = [event[afield]] + avalue

                return True

            else:
                self.logger.error(
                    "Operation '{}' unsupported (action '{}')".format(
                        op, action
                    )
                )
                return False

    def a_remove(self, event, action):
        """Remove an event from a field in event or the whole field if no
        element is specified.
        """

        akey = action.get('key', None)
        aelement = action.get('element', None)
        del_met = action.get('met', 0)

        if akey:
            if aelement:
                if del_met:
                    for i, met in enumerate(event[akey]):
                        if met['name'] == aelement:
                            del event[akey][i]
                            break
                elif isinstance(event[akey], dict):
                    del event[akey][aelement]
                elif isinstance(event[akey], list):
                    del event[akey][event[akey].index(aelement)]

                self.logger.debug(u"    + {}: Removed: '{}' from '{}'".format(
                    event['rk'],
                    aelement,
                    akey))

            else:
                del event[akey]
                self.logger.debug(u"    + {}: Removed: '{}'".format(
                    event['rk'],
                    akey))

            return True

        else:
            self.logger.error(
                u"Action malformed (needs 'key' and/or 'element'): {}".format(
                    action))
            return False

    def a_modify(self, event, action, name):
        """
        Args:
            event map of the event to be modified
            action map of type action
            _name of the rule
        Returns:
            ``None``
        """

        derogated = False
        atype = action.get('type')
        actionMap = {
            'override': self.a_override,
            'remove': self.a_remove
        }

        if atype in actionMap:
            derogated = actionMap[atype](event, action)

        else:
            self.logger.warning(u"Unknown action '{}'".format(atype))

        # If the event was derogated, fill some informations
        if derogated:
            self.logger.debug(u"Event changed by rule '{}'".format(name))

        return None

    def a_drop(self, event, action, name):
        """ Drop the event.

        Args:
            event map of the event to be modified
            action map of type action
            _name of the rule
        Returns:
            ``None``
        """

        self.logger.debug(u"Event dropped by rule '{}'".format(name))
        self.drop_event_count += 1

        return DROP

    def a_pass(self, event, action, name):
        """Pass the event to the next queue.

        Args:
            event map of the event to be modified
            action map of type action
            _name of the rule
        Returns:
            ``None``
        """

        self.logger.debug(u"Event passed by rule '{}'".format(name))
        self.pass_event_count += 1

        return event

    def a_route(self, event, action, name):
        """
        Change the route to which an event will be sent
        Args:
            event: map of the event to be modified
            action: map of type action
            name: of the rule
        Returns:
            ``None``
        """

        if "route" in action:
            self.next_amqp_queues = [action["route"]]
            self.logger.debug(u"Event re-routed by rule '{}'".format(name))
        else:
            self.logger.error(
                u"Action malformed (needs 'route'): {}".format(action))

        return None

    def a_exec_job(self, event, action, name):
        records = self.storage.find(
            {'crecord_type': 'job', '_id': action['job']}
        )
        for record in records:
            job = record.dump()
            job['context'] = event
            publish(
                publisher=self.amqp,
                event=job,
                rk='Engine_scheduler',
                exchange='amq.direct'
            )
            # publish(publisher=self.amqp, event=job, rk='Engine_scheduler')
        return True

    def a_snooze(self, event, action, name):
        """
        Snooze event checks

        :param dict event: event to be snoozed
        :param dict action: action
        :param str name: name of the rule

        :returns: True if a snooze has been sent, False otherwise
        :rtype: boolean
        """
        # Only check events can trigger an auto-snooze
        if event['event_type'] != 'check':
            return False

        # A check OK cannot trigger an auto-snooze
        if event['state'] == 0:
            return False

        # Alerts manager caching
        if not hasattr(self, 'am'):
            self.am = Alerts()

        # Context manager caching
        if not hasattr(self, 'cm'):
            self.cm = Context()

        entity = self.cm.get_entity(event)
        entity_id = self.cm.get_entity_id(entity)

        current_alarm = self.am.get_current_alarm(entity_id)
        if current_alarm is None:
            snooze = {
                'connector': event.get('connector', ''),
                'connector_name': event.get('connector_name', ''),
                'source_type': event.get('source_type', ''),
                'component': event.get('component', ''),
                'event_type': 'snooze',
                'duration': action['duration'],
                'author': 'event_filter',
                'output': 'Auto snooze generated by rule "{}"'.format(name),
            }

            if 'resource' in event:
                snooze['resource'] = event['resource']

            publish(event=snooze, publisher=self.amqp)

            return True

        return False

    def apply_actions(self, event, actions):
        pass_event = False
        actionMap = {
            'drop': self.a_drop,
            'pass': self.a_pass,
            'override': self.a_modify,
            'remove': self.a_modify,
            'execjob': self.a_exec_job,
            'route': self.a_route,
            'snooze': self.a_snooze,
        }

        for name, action in actions:
            if action['type'] in actionMap:
                ret = actionMap[action['type'].lower()](event, action, name)
                if ret:
                    pass_event = True
            else:
                self.logger.warning(u"Unknown action '{}'".format(action))

        return pass_event

    def work(self, event, *xargs, **kwargs):

        rk = get_routingkey(event)
        default_action = self.configuration.get('default_action', 'pass')

        # list of supported actions

        rules = self.configuration.get('rules', [])
        to_apply = []

        self.logger.debug(u'event {}'.format(event))

        # When list configuration then check black and
        # white lists depending on json configuration
        for filterItem in rules:
            actions = filterItem.get('actions')
            name = filterItem.get('name', 'no_name')

            self.logger.debug(u'rule {}'.format(filterItem))
            self.logger.debug(u'filter is {}'.format(filterItem['mfilter']))
            # Try filter rules on current event
            if filterItem['mfilter'] and check(filterItem['mfilter'], event):

                self.logger.debug(
                    u'Event: {}, filter matches'.format(event.get('rk', event))
                )

                for action in actions:
                    if action['type'].lower() == 'drop':
                        self.apply_actions(event, to_apply)
                        return self.a_drop(event, None, name)
                    to_apply.append((name, action))

                if filterItem.get('break', 0):
                    self.logger.debug(
                        u' + Filter {} broke the next filters processing'
                        .format(
                            filterItem.get('name', 'filter')
                        )
                    )
                    break

        if len(to_apply):
            if self.apply_actions(event, to_apply):
                self.logger.debug(
                    u'Event before sent to next engine: %s' % event
                )
                event['rk'] = event['_id'] = get_routingkey(event)
                return event

        # No rules matched
        if default_action == 'drop':
            self.logger.debug("Event '%s' dropped by default action" % (rk))
            self.drop_event_count += 1
            return DROP

        self.logger.debug("Event '%s' passed by default action" % (rk))
        self.pass_event_count += 1

        self.logger.debug(u'Event before sent to next engine: %s' % event)
        event['rk'] = event['_id'] = get_routingkey(event)
        return event

    def beat(self, *args, **kargs):
        """ Configuration reload for realtime ui changes handling """

        self.derogations = []
        self.configuration = {
            'rules': [],
            'default_action': self.find_default_action()
        }

        self.logger.debug(u'Reload configuration rules')
        records = self.storage.find(
            {'crecord_type': 'filter', 'enable': True},
            sort='priority'
        )

        for record in records:

            record_dump = record.dump()
            self.set_loaded(record_dump)

            try:
                record_dump["mfilter"] = loads(record_dump["mfilter"])
            except Exception:
                self.logger.info(u'Invalid mfilter {}, filter {}'.format(
                    record_dump['mfilter'],
                    record_dump['name'],

                ))

            self.logger.debug(u'Loading record_dump:')
            self.logger.debug(record_dump)
            self.configuration['rules'].append(record_dump)

        self.logger.info(
            'Loaded {} rules'.format(len(self.configuration['rules']))
        )
        self.send_stat_event()

    def set_loaded(self, record):

        if 'run_once' in record and not record['run_once']:
            self.storage.update(record['_id'], {'run_once': True})
            self.logger.info(
                'record {} has been run once'.format(record['_id'])
            )

    def send_stat_event(self):
        """ Send AMQP Event for drop and pass metrics """

        message_dropped = '{} event dropped since {}'.format(
            self.drop_event_count,
            self.beat_interval
        )
        message_passed = '{} event passed since {}'.format(
            self.pass_event_count,
            self.beat_interval
        )
        event = forger(
            connector='Engine',
            connector_name='engine',
            event_type='check',
            source_type='resource',
            resource=self.amqp_queue + '_data',
            state=0,
            state_type=1,
            output=message_dropped,
            perf_data_array=[
                {'metric': 'pass_event',
                 'value': self.pass_event_count,
                 'type': 'GAUGE'},
                {'metric': 'drop_event',
                 'value': self.drop_event_count,
                 'type': 'GAUGE'}
            ]
        )

        self.logger.debug(message_dropped)
        self.logger.debug(message_passed)
        publish(publisher=self.amqp, event=event)
        self.drop_event_count = 0
        self.pass_event_count = 0

    def find_default_action(self):
        """Find the default action stored and returns it, else assume it
        default action is pass.
        """

        records = self.storage.find({'crecord_type': 'defaultrule'})
        if records:
            return records[0].dump()["action"]

        self.logger.debug(
            "No default action found. Assuming default action is pass"
        )
        return 'pass'
Пример #11
0
class ComputeState(BaseTest):

    def setUp(self):
        super(ComputeState, self).setUp()
        pbehavior_storage = Middleware.get_middleware_by_uri(
            'storage-default-testpbehavior://'
        )
        filter_storage = Middleware.get_middleware_by_uri(
            'storage-default-testalarmfilter://'
        )
        config_storage = Middleware.get_middleware_by_uri(
            'storage-default-testconfig://'
        )
        config_storage.put_element(
            element={
                '_id': 'test_config',
                'crecord_type': 'statusmanagement',
                'bagot_time': 3600,
                'bagot_freq': 10,
                'stealthy_time': 300,
                'restore_event': True,
                'auto_snooze': False,
                'snooze_default_time': 300,
            },
            _id='test_config'
        )
        logger = Logger.get('test_pb', None, output_cls=OutputNull)

        config = Configuration.load(PBehaviorManager.CONF_PATH, Ini)

        self.pbm = PBehaviorManager(config=config,
                                    logger=logger,
                                    pb_storage=pbehavior_storage)
        self.pbm.context = self.context_graph_manager
        self.manager.pbehavior_manager = self.pbm

        conf = Configuration.load(Alerts.CONF_PATH, Ini)
        filter_ = {'crecord_type': 'statusmanagement'}
        config_data = EtherealData(collection=config_storage._backend,
                                   filter_=filter_)

        event_publisher = Mock(spec=StatEventPublisher)

        self.alert_manager = Alerts(config=conf,
                                    logger=logger,
                                    alerts_storage=self.alerts_storage,
                                    config_data=config_data,
                                    filter_storage=filter_storage,
                                    context_graph=self.context_graph_manager,
                                    watcher=self.manager,
                                    event_publisher=event_publisher)

        # Creating entity
        self.type_ = 'resource'
        self.name = 'morticia'
        entity = ContextGraph.create_entity_dict(
            id=self.name,
            etype=self.type_,
            name=self.name
        )
        self.context_graph_manager.create_entity(entity)

        # Creating coresponding alarm
        event = {
            'connector': self.type_,
            'connector_name': 'connector_name',
            'component': self.name,
            'output': 'tadaTaDA tic tic',
            'timestamp': 0
        }
        alarm = self.alert_manager.make_alarm(self.name, event)
        self.state = 2
        alarm = self.alert_manager.update_state(alarm, self.state, event)
        new_value = alarm[self.alert_manager.alerts_storage.VALUE]
        self.alert_manager.update_current_alarm(alarm, new_value)

    def tearDown(self):
        super(ComputeState, self).tearDown()
        self.pbm.pb_storage.remove_elements()

    def test_compute_state_issue427(self):
        # Aka: state desyncro
        watcher_id = 'addams'
        watcher = {
            '_id': watcher_id,
            'mfilter': '{"name": {"$in": ["morticia"]}}',
            'display_name': 'family'
        }
        self.assertTrue(self.manager.create_watcher(watcher))

        res = self.manager.get_watcher(watcher_id)
        self.assertEqual(res['state'], self.state)

        # Creating pbehavior on it
        now = datetime.utcnow()
        self.pbm.create(
            name='addam',
            filter=loads('{"name": "morticia"}'),
            author='addams',
            tstart=timegm(now.timetuple()),
            tstop=timegm((now + timedelta(seconds=2)).timetuple()),
            rrule=None,
            enabled=True
        )
        self.pbm.compute_pbehaviors_filters()

        res = self.manager.get_watcher(watcher_id)
        self.assertEqual(res['state'], self.state)

        self.manager.compute_watchers()

        res = self.manager.get_watcher(watcher_id)
        self.assertEqual(res['state'], 0)

        sleep(3)
        self.pbm.compute_pbehaviors_filters()
        self.manager.compute_watchers()

        res = self.manager.get_watcher(watcher_id)
        self.assertEqual(res['state'], self.state)
Пример #12
0
def exports(ws):

    ws.application.router.add_filter('id_filter', id_filter)

    context_manager = ContextGraph(ws.logger)
    am = Alerts(*Alerts.provide_default_basics())
    ar = AlertsReader(*AlertsReader.provide_default_basics())

    @route(
        ws.application.get,
        name='alerts/get-alarms',
        payload=[
            'tstart',
            'tstop',
            'opened',
            'resolved',
            'lookups',
            'filter',
            'search',
            'sort_key',
            'sort_dir',
            'skip',
            'limit',
            'with_steps',
            'natural_search',
            'active_columns',
            'hide_resources'
        ]
    )
    def get_alarms(
            tstart=None,
            tstop=None,
            opened=True,
            resolved=False,
            lookups=[],
            filter={},
            search='',
            sort_key='opened',
            sort_dir='DESC',
            skip=0,
            limit=50,
            with_steps=False,
            natural_search=False,
            active_columns=None,
            hide_resources=False
    ):
        """
        Return filtered, sorted and paginated alarms.

        :param tstart: Beginning timestamp of requested period
        :param tstop: End timestamp of requested period
        :type tstart: int or None
        :type tstop: int or None

        :param bool opened: If True, consider alarms that are currently opened
        :param bool resolved: If True, consider alarms that have been resolved

        :param list lookups: List of extra columns to compute for each
          returned alarm. Extra columns are "pbehaviors".

        :param dict filter: Mongo filter. Keys are UI column names.
        :param str search: Search expression in custom DSL

        :param str sort_key: Name of the column to sort
        :param str sort_dir: Either "ASC" or "DESC"

        :param int skip: Number of alarms to skip (pagination)
        :param int limit: Maximum number of alarms to return

        :param list active_columns: list of active columns on the brick
        listalarm .

        :param bool hide_resources: hide_resources if component has an alarm

        :returns: List of sorted alarms + pagination informations
        :rtype: dict
        """
        if isinstance(search, int):
            search = str(search)

        try:
            alarms = ar.get(
                tstart=tstart,
                tstop=tstop,
                opened=opened,
                resolved=resolved,
                lookups=lookups,
                filter_=filter,
                search=search.strip(),
                sort_key=sort_key,
                sort_dir=sort_dir,
                skip=skip,
                limit=limit,
                with_steps=with_steps,
                natural_search=natural_search,
                active_columns=active_columns,
                hide_resources=hide_resources
            )
        except OperationFailure as of_err:
            message = 'Operation failure on get-alarms: {}'.format(of_err)
            raise WebServiceError(message)

        alarms_ids = []
        for alarm in alarms['alarms']:
            tmp_id = alarm.get('d')
            if tmp_id:
                alarms_ids.append(tmp_id)
        entities = context_manager.get_entities_by_id(alarms_ids, with_links=True)
        entity_dict = {}
        for entity in entities:
            entity_dict[entity.get('_id')] = entity

        list_alarm = []
        for alarm in alarms['alarms']:
            now = int(time())
            alarm["v"]['duration'] = now - alarm.get('v', {}).get('creation_date', now)
            state_time = alarm.get('v', {}).get('state', {}).get('t', now)
            alarm["v"]['current_state_duration'] = now - state_time
            tmp_entity_id = alarm['d']

            if alarm['d'] in entity_dict:
                alarm['links'] = entity_dict[alarm['d']]['links']

                # TODO: 'infos' is already present in entity.
                # Remove this one if unused.
                if tmp_entity_id in entity_dict:
                    data = entity_dict[alarm['d']]['infos']
                    if alarm.get('infos'):
                        alarm['infos'].update(data)
                    else:
                        alarm['infos'] = data

            alarm = compat_go_crop_states(alarm)

            list_alarm.append(alarm)

        alarms['alarms'] = list_alarm

        return alarms

    @route(
        ws.application.get,
        name='alerts/search/validate',
        payload=['expression']
    )
    def validate_search(expression):
        """
        Tell if a search expression is valid from a grammatical propespective.

        :param str expression: Search expression

        :returns: True if valid, False otherwise
        :rtype: bool
        """

        try:
            ar.interpret_search(expression)

        except Exception:
            return False

        else:
            return True

    @route(
        ws.application.get,
        name='alerts/count',
        payload=['start', 'stop', 'limit', 'select'],
    )
    def count_by_period(
            start,
            stop,
            limit=100,
            select=None,
    ):
        """
        Count alarms that have been opened during (stop - start) period.

        :param start: Beginning timestamp of period
        :type start: int

        :param stop: End timestamp of period
        :type stop: int

        :param limit: Counts cannot exceed this value
        :type limit: int

        :param query: Custom mongodb filter for alarms
        :type query: dict

        :return: List in which each item contains a time interval and the
                 related count
        :rtype: list
        """

        return ar.count_alarms_by_period(
            start,
            stop,
            limit=limit,
            query=select,
        )

    @route(
        ws.application.get,
        name='alerts/get-current-alarm',
        payload=['entity_id'],
    )
    def get_current_alarm(entity_id):
        """
        Get current unresolved alarm for a entity.

        :param str entity_id: Entity ID of the alarm

        :returns: Alarm as dict if something is opened, else None
        """

        return am.get_current_alarm(entity_id)

    @ws.application.get(
        '/api/v2/alerts/filters/<entity_id:id_filter>'
    )
    def get_filter(entity_id):
        """
        Get all filters linked with an alarm.

        :param str entity_id: Entity ID of the alarm-filter

        :returns: a list of <AlarmFilter>
        """
        filters = am.alarm_filters.get_filter(entity_id)
        if filters is None:
            return gen_json_error({'description': 'nothing to return'},
                                  HTTP_ERROR)

        return gen_json([l.serialize() for l in filters])

    @ws.application.post(
        '/api/v2/alerts/filters'
    )
    def create_filter():
        """
        Create a new alarm filter.

        :returns: an <AlarmFilter>
        """
        # element is a full AlarmFilter (dict) to insert
        element = request.json

        if element is None:
            return gen_json_error(
                {'description': 'nothing to insert'}, HTTP_ERROR)

        new = am.alarm_filters.create_filter(element=element)
        new.save()

        return gen_json(new.serialize())

    @ws.application.put(
        '/api/v2/alerts/filters/<entity_id:id_filter>'
    )
    def update_filter(entity_id):
        """
        Update an existing alam filter.

        :param entity_id: Entity ID of the alarm-filter
        :type entity_id: str
        :returns: <AlarmFilter>
        :rtype: dict
        """
        dico = request.json

        if dico is None or not isinstance(dico, dict) or len(dico) <= 0:
            return gen_json_error(
                {'description': 'wrong update dict'}, HTTP_ERROR)

        af = am.alarm_filters.update_filter(filter_id=entity_id, values=dico)
        if not isinstance(af, AlarmFilter):
            return gen_json_error({'description': 'failed to update filter'},
                                  HTTP_ERROR)

        return gen_json(af.serialize())

    @ws.application.delete(
        '/api/v2/alerts/filters/<entity_id:id_filter>'
    )
    def delete_id(entity_id):
        """
        Delete a filter, based on his id.

        :param entity_id: Entity ID of the alarm-filter
        :type entity_id: str

        :rtype: dict
        """
        ws.logger.info('Delete alarm-filter : {}'.format(entity_id))

        return gen_json(am.alarm_filters.delete_filter(entity_id))

    @ws.application.delete(
        '/api/v2/alerts/<mfilter>'
    )
    def delete_filter(mfilter):
        """
        :param str mfilter: mongo filter
        :rtype: dict
        """
        return gen_json(ar.alarm_storage._backend.remove(json.loads(mfilter)))

    @ws.application.post(
        '/api/v2/alerts/done'
    )
    def done_action():
        """
        Trigger done action.

        For json payload, see doc/docs/fr/guide_developpeur/apis/v2/alerts.md

        :rtype: dict
        """
        dico = request.json

        if dico is None or not isinstance(dico, dict) or len(dico) <= 0:
            return gen_json_error(
                {'description': 'wrong done dict'}, HTTP_ERROR)

        author = dico.get(am.AUTHOR)
        event = forger(
            event_type=Check.EVENT_TYPE,
            author=author,
            connector=dico.get('connector'),
            connector_name=dico.get('connector_name'),
            component=dico.get('component'),
            output=dico.get('comment')
        )
        if dico.get('source_type', None) == 'resource':
            event['resource'] = dico['resource']
            event['source_type'] = 'resource'
        ws.logger.debug('Received done action: {}'.format(event))

        entity_id = am.context_manager.get_id(event)
        retour = am.execute_task(
            'alerts.useraction.done',
            event=event,
            author=author,
            entity_id=entity_id
        )
        return gen_json(retour)
Пример #13
0
class engine(Engine):
    etype = 'event_filter'

    def __init__(self, *args, **kargs):
        super(engine, self).__init__(*args, **kargs)

        self.mg_store = MongoStore.get_default()
        self.collection = MongoCollection(
            self.mg_store.get_collection("object"))
        self.name = kargs['name']
        self.drop_event_count = 0
        self.pass_event_count = 0
        self.__load_rules()

    def pre_run(self):
        self.beat()

    def a_override(self, event, action):
        """Override a field from event or add a new one if it does not have
        one.
        """

        afield = action.get('field', None)
        avalue = action.get('value', None)

        # This must be a hard check because value can be a boolean or a null
        # integer
        if afield is None or avalue is None:
            self.logger.error(
                "Malformed action ('field' and 'value' required): {}".format(
                    action))
            return False

        if afield not in event:
            self.logger.debug("Overriding: '{}' -> '{}'".format(
                afield, avalue))
            event[afield] = avalue
            return True

        # afield is in event
        if not isinstance(avalue, list):
            if isinstance(event[afield], list):
                self.logger.debug("Appending: '{}' to '{}'".format(
                    avalue, afield))
                event[afield].append(avalue)

            else:
                self.logger.debug("Overriding: '{}' -> '{}'".format(
                    afield, avalue))
                event[afield] = avalue

            return True

        else:
            # operation field is supported only for list values
            op = action.get('operation', 'append')

            if op == 'override':
                self.logger.debug("Overriding: '{}' -> '{}'".format(
                    afield, avalue))
                event[afield] = avalue
                return True

            elif op == 'append':
                self.logger.debug("Appending: '{}' to '{}'".format(
                    avalue, afield))

                if isinstance(event[afield], list):
                    event[afield] += avalue
                else:
                    event[afield] = [event[afield]] + avalue

                return True

            else:
                self.logger.error(
                    "Operation '{}' unsupported (action '{}')".format(
                        op, action))
                return False

    def a_remove(self, event, action):
        """Remove an event from a field in event or the whole field if no
        element is specified.
        """

        akey = action.get('key', None)
        aelement = action.get('element', None)
        del_met = action.get('met', 0)

        if akey:
            if aelement:
                if del_met:
                    for i, met in enumerate(event[akey]):
                        if met['name'] == aelement:
                            del event[akey][i]
                            break
                elif isinstance(event[akey], dict):
                    del event[akey][aelement]
                elif isinstance(event[akey], list):
                    del event[akey][event[akey].index(aelement)]

                self.logger.debug(u"    + {}: Removed: '{}' from '{}'".format(
                    event['rk'], aelement, akey))

            else:
                del event[akey]
                self.logger.debug(u"    + {}: Removed: '{}'".format(
                    event['rk'], akey))

            return True

        else:
            self.logger.error(
                u"Action malformed (needs 'key' and/or 'element'): {}".format(
                    action))
            return False

    def a_modify(self, event, action, name):
        """
        Args:
            event map of the event to be modified
            action map of type action
            _name of the rule
        Returns:
            ``None``
        """

        derogated = False
        atype = action.get('type')
        actionMap = {'override': self.a_override, 'remove': self.a_remove}

        if atype in actionMap:
            derogated = actionMap[atype](event, action)

        else:
            self.logger.warning(u"Unknown action '{}'".format(atype))

        # If the event was derogated, fill some informations
        if derogated:
            self.logger.debug(u"Event changed by rule '{}'".format(name))

        return None

    def a_drop(self, event, action, name):
        """ Drop the event.

        Args:
            event map of the event to be modified
            action map of type action
            _name of the rule
        Returns:
            ``None``
        """

        self.logger.debug(u"Event dropped by rule '{}'".format(name))
        self.drop_event_count += 1

        return DROP

    def a_pass(self, event, action, name):
        """Pass the event to the next queue.

        Args:
            event map of the event to be modified
            action map of type action
            _name of the rule
        Returns:
            ``None``
        """

        self.logger.debug(u"Event passed by rule '{}'".format(name))
        self.pass_event_count += 1

        return event

    def a_route(self, event, action, name):
        """
        Change the route to which an event will be sent
        Args:
            event: map of the event to be modified
            action: map of type action
            name: of the rule
        Returns:
            ``None``
        """

        if "route" in action:
            self.next_amqp_queues = [action["route"]]
            self.logger.debug(u"Event re-routed by rule '{}'".format(name))
        else:
            self.logger.error(
                u"Action malformed (needs 'route'): {}".format(action))

        return None

    def a_exec_job(self, event, action, name):
        records = self.collection.find({
            'crecord_type': 'job',
            '_id': action['job']
        })
        for record in records:
            job = copy.deepcopy(record)
            job['context'] = event
            try:
                self.work_amqp_publisher.direct_event(job, 'Engine_scheduler')
            except Exception as e:
                self.logger.exception("Unable to send job")
            time.sleep(1)
        return True

    def a_snooze(self, event, action, name):
        """
        Snooze event checks

        :param dict event: event to be snoozed
        :param dict action: action
        :param str name: name of the rule

        :returns: True if a snooze has been sent, False otherwise
        :rtype: boolean
        """
        if event.get('event_type') == 'snooze':
            return False
        # Only check events can trigger an auto-snooze
        if event.get('event_type') != 'check':
            return False

        # A check OK cannot trigger an auto-snooze
        if event.get('state') == 0:
            return False

        # Alerts manager caching
        if not hasattr(self, 'am'):
            self.am = Alerts(*Alerts.provide_default_basics())

        # Context manager caching
        if not hasattr(self, 'cm'):
            self.cm = ContextGraph(self.logger)

        entity_id = self.cm.get_id(event)

        current_alarm = self.am.get_current_alarm(entity_id)
        if current_alarm is None:
            snooze = {
                'connector': event.get('connector', ''),
                'connector_name': event.get('connector_name', ''),
                'source_type': event.get('source_type', ''),
                'component': event.get('component', ''),
                'event_type': 'snooze',
                'duration': action['duration'],
                'author': 'event_filter',
                'output': 'Auto snooze generated by rule "{}"'.format(name),
                'timestamp': int(time.time())
            }

            if event.get('resource', ''):
                snooze['resource'] = event['resource']

            try:
                self.work_amqp_publisher.direct_event(snooze,
                                                      'Engine_event_filter')
            except Exception as e:
                self.logger.exception("Unable to send snooze event")

            return True

        return False

    def a_baseline(self, event, actions, name):
        """a_baseline

        :param event:
        :param action: baseline conf in event filter
        :param name:
        """
        event['baseline_name'] = actions['baseline_name']
        event['check_frequency'] = actions['check_frequency']

        try:
            self.work_amqp_publisher.direct_event(event, 'Engine_baseline')
        except Exception as e:
            self.logger.exception("Unable to send baseline event")

    def apply_actions(self, event, actions):
        pass_event = False
        actionMap = {
            'drop': self.a_drop,
            'pass': self.a_pass,
            'override': self.a_modify,
            'remove': self.a_modify,
            'execjob': self.a_exec_job,
            'route': self.a_route,
            'snooze': self.a_snooze,
            'baseline': self.a_baseline
        }

        for name, action in actions:
            if action['type'] in actionMap:
                ret = actionMap[action['type'].lower()](event, action, name)
                if ret:
                    pass_event = True
            else:
                self.logger.warning(u"Unknown action '{}'".format(action))

        return pass_event

    def work(self, event, *xargs, **kwargs):

        rk = get_routingkey(event)
        default_action = self.configuration.get('default_action', 'pass')

        # list of supported actions

        rules = self.configuration.get('rules', [])
        to_apply = []

        self.logger.debug(u'event {}'.format(event))

        # When list configuration then check black and
        # white lists depending on json configuration
        for filterItem in rules:
            actions = filterItem.get('actions')
            name = filterItem.get('name', 'no_name')

            self.logger.debug(u'rule {}'.format(filterItem))
            self.logger.debug(u'filter is {}'.format(filterItem['mfilter']))
            # Try filter rules on current event
            if filterItem['mfilter'] and check(filterItem['mfilter'], event):
                self.logger.debug(u'Event: {}, filter matches'.format(
                    event.get('rk', event)))

                if 'pbehaviors' in filterItem:
                    pbehaviors = filterItem.get('pbehaviors', {})
                    list_in = pbehaviors.get('in', [])
                    list_out = pbehaviors.get('out', [])

                    if list_in or list_out:
                        pbm = singleton_per_scope(PBehaviorManager)
                        cm = singleton_per_scope(ContextGraph)
                        entity = cm.get_entity(event)
                        entity_id = cm.get_entity_id(entity)

                        result = pbm.check_pbehaviors(entity_id, list_in,
                                                      list_out)

                        if not result:
                            break

                for action in actions:
                    if action['type'].lower() == 'drop':
                        self.apply_actions(event, to_apply)
                        return self.a_drop(event, None, name)
                    to_apply.append((name, action))

                if filterItem.get('break', 0):
                    self.logger.debug(
                        u' + Filter {} broke the next filters processing'.
                        format(filterItem.get('name', 'filter')))
                    break

        if len(to_apply):
            if self.apply_actions(event, to_apply):
                self.logger.debug(u'Event before sent to next engine: %s' %
                                  event)
                event['rk'] = event['_id'] = get_routingkey(event)
                return event

        # No rules matched
        if default_action == 'drop':
            self.logger.debug("Event '%s' dropped by default action" % (rk))
            self.drop_event_count += 1
            return DROP

        self.logger.debug("Event '%s' passed by default action" % (rk))
        self.pass_event_count += 1

        self.logger.debug(u'Event before sent to next engine: %s' % event)
        event['rk'] = event['_id'] = get_routingkey(event)
        return event

    def __load_rules(self):

        tmp_rules = []
        records = self.collection.find({
            'crecord_type': 'filter',
            'enable': True
        })
        records.sort('priority', 1)

        for record in records:

            record_dump = copy.deepcopy(record)
            self.set_loaded(record_dump)

            try:
                record_dump["mfilter"] = loads(record_dump["mfilter"])
            except Exception:
                self.logger.info(u'Invalid mfilter {}, filter {}'.format(
                    record_dump['mfilter'],
                    record_dump['name'],
                ))

            self.logger.debug(u'Loading record_dump:')
            self.logger.debug(record_dump)
            tmp_rules.append(record_dump)

        self.configuration = {
            'rules': tmp_rules,
            'default_action': self.find_default_action()
        }

    def beat(self, *args, **kargs):
        """ Configuration reload for realtime ui changes handling """

        self.logger.debug(u'Reload configuration rules')

        self.__load_rules()

        self.logger.debug('Loaded {} rules'.format(
            len(self.configuration['rules'])))
        self.send_stat_event()

    def set_loaded(self, record):

        if 'run_once' in record and not record['run_once']:
            self.collection.update({"_id": record['_id']},
                                   {"$set": {
                                       'run_once': True
                                   }})
            self.logger.info('record {} has been run once'.format(
                record['_id']))

    def send_stat_event(self):
        """ Send AMQP Event for drop and pass metrics """

        message_dropped = '{} event dropped since {}'.format(
            self.drop_event_count, self.beat_interval)
        message_passed = '{} event passed since {}'.format(
            self.pass_event_count, self.beat_interval)
        event = forger(connector='Engine',
                       connector_name='engine',
                       event_type='check',
                       source_type='resource',
                       resource=self.amqp_queue + '_data',
                       state=0,
                       state_type=1,
                       output=message_dropped,
                       perf_data_array=[{
                           'metric': 'pass_event',
                           'value': self.pass_event_count,
                           'type': 'GAUGE'
                       }, {
                           'metric': 'drop_event',
                           'value': self.drop_event_count,
                           'type': 'GAUGE'
                       }])

        self.logger.debug(message_dropped)
        self.logger.debug(message_passed)
        try:
            self.beat_amqp_publisher.canopsis_event(event)
        except Exception as e:
            self.logger.exception("Unable to send stat event")
        self.drop_event_count = 0
        self.pass_event_count = 0

    def find_default_action(self):
        """Find the default action stored and returns it, else assume it
        default action is pass.
        """

        records = self.collection.find_one({'crecord_type': 'defaultrule'})
        if records:
            return records[0]["action"]

        self.logger.debug(
            "No default action found. Assuming default action is pass")
        return 'pass'
Пример #14
0
def exports(ws):

    ws.application.router.add_filter('id_filter', id_filter)

    context_manager = ContextGraph(ws.logger)
    am = Alerts(*Alerts.provide_default_basics())
    ar = AlertsReader(*AlertsReader.provide_default_basics())

    @route(
        ws.application.get,
        name='alerts/get-alarms',
        payload=[
            'tstart',
            'tstop',
            'opened',
            'resolved',
            'lookups',
            'filter',
            'search',
            'sort_key',
            'sort_dir',
            'skip',
            'limit',
            'with_steps',
            'natural_search',
            'active_columns',
            'hide_resources'
        ]
    )
    def get_alarms(
            tstart=None,
            tstop=None,
            opened=True,
            resolved=False,
            lookups=[],
            filter={},
            search='',
            sort_key='opened',
            sort_dir='DESC',
            skip=0,
            limit=None,
            with_steps=False,
            natural_search=False,
            active_columns=None,
            hide_resources=False
    ):
        """
        Return filtered, sorted and paginated alarms.

        :param tstart: Beginning timestamp of requested period
        :param tstop: End timestamp of requested period
        :type tstart: int or None
        :type tstop: int or None

        :param bool opened: If True, consider alarms that are currently opened
        :param bool resolved: If True, consider alarms that have been resolved

        :param list lookups: List of extra columns to compute for each
          returned alarm. Extra columns are "pbehaviors".

        :param dict filter: Mongo filter. Keys are UI column names.
        :param str search: Search expression in custom DSL

        :param str sort_key: Name of the column to sort
        :param str sort_dir: Either "ASC" or "DESC"

        :param int skip: Number of alarms to skip (pagination)
        :param int limit: Maximum number of alarms to return

        :param list active_columns: list of active columns on the brick
        listalarm .

        :param bool hide_resources: hide_resources if component has an alarm

        :returns: List of sorted alarms + pagination informations
        :rtype: dict
        """
        if isinstance(search, int):
            search = str(search)

        try:
            alarms = ar.get(
                tstart=tstart,
                tstop=tstop,
                opened=opened,
                resolved=resolved,
                lookups=lookups,
                filter_=filter,
                search=search.strip(),
                sort_key=sort_key,
                sort_dir=sort_dir,
                skip=skip,
                limit=limit,
                with_steps=with_steps,
                natural_search=natural_search,
                active_columns=active_columns,
                hide_resources=hide_resources
            )
        except OperationFailure as of_err:
            message = 'Operation failure on get-alarms: {}'.format(of_err)
            raise WebServiceError(message)

        alarms_ids = []
        for alarm in alarms['alarms']:
            tmp_id = alarm.get('d')
            if tmp_id:
                alarms_ids.append(tmp_id)
        entities = context_manager.get_entities_by_id(alarms_ids, with_links=True)
        entity_dict = {}
        for entity in entities:
            entity_dict[entity.get('_id')] = entity

        list_alarm = []
        for alarm in alarms['alarms']:
            now = int(time())
            alarm["v"]['duration'] = now - alarm.get('v', {}).get('creation_date', now)
            state_time = alarm.get('v', {}).get('state', {}).get('t', now)
            alarm["v"]['current_state_duration'] = now - state_time
            tmp_entity_id = alarm['d']

            if alarm['d'] in entity_dict:
                alarm['links'] = entity_dict[alarm['d']]['links']

                # TODO: 'infos' is already present in entity.
                # Remove this one if unused.
                if tmp_entity_id in entity_dict:
                    data = entity_dict[alarm['d']]['infos']
                    if alarm.get('infos'):
                        alarm['infos'].update(data)
                    else:
                        alarm['infos'] = data

            alarm = compat_go_crop_states(alarm)

            list_alarm.append(alarm)

        alarms['alarms'] = list_alarm

        return alarms

    @route(
        ws.application.get,
        name='alerts/search/validate',
        payload=['expression']
    )
    def validate_search(expression):
        """
        Tell if a search expression is valid from a grammatical propespective.

        :param str expression: Search expression

        :returns: True if valid, False otherwise
        :rtype: bool
        """

        try:
            ar.interpret_search(expression)

        except Exception:
            return False

        else:
            return True

    @route(
        ws.application.get,
        name='alerts/count',
        payload=['start', 'stop', 'limit', 'select'],
    )
    def count_by_period(
            start,
            stop,
            limit=100,
            select=None,
    ):
        """
        Count alarms that have been opened during (stop - start) period.

        :param start: Beginning timestamp of period
        :type start: int

        :param stop: End timestamp of period
        :type stop: int

        :param limit: Counts cannot exceed this value
        :type limit: int

        :param query: Custom mongodb filter for alarms
        :type query: dict

        :return: List in which each item contains a time interval and the
                 related count
        :rtype: list
        """

        return ar.count_alarms_by_period(
            start,
            stop,
            limit=limit,
            query=select,
        )

    @route(
        ws.application.get,
        name='alerts/get-current-alarm',
        payload=['entity_id'],
    )
    def get_current_alarm(entity_id):
        """
        Get current unresolved alarm for a entity.

        :param str entity_id: Entity ID of the alarm

        :returns: Alarm as dict if something is opened, else None
        """

        return am.get_current_alarm(entity_id)

    @ws.application.get(
        '/api/v2/alerts/filters/<entity_id:id_filter>'
    )
    def get_filter(entity_id):
        """
        Get all filters linked with an alarm.

        :param str entity_id: Entity ID of the alarm-filter

        :returns: a list of <AlarmFilter>
        """
        filters = am.alarm_filters.get_filter(entity_id)
        if filters is None:
            return gen_json_error({'description': 'nothing to return'},
                                  HTTP_ERROR)

        return gen_json([l.serialize() for l in filters])

    @ws.application.post(
        '/api/v2/alerts/filters'
    )
    def create_filter():
        """
        Create a new alarm filter.

        :returns: an <AlarmFilter>
        """
        # element is a full AlarmFilter (dict) to insert
        element = request.json

        if element is None:
            return gen_json_error(
                {'description': 'nothing to insert'}, HTTP_ERROR)

        new = am.alarm_filters.create_filter(element=element)
        new.save()

        return gen_json(new.serialize())

    @ws.application.put(
        '/api/v2/alerts/filters/<entity_id:id_filter>'
    )
    def update_filter(entity_id):
        """
        Update an existing alam filter.

        :param entity_id: Entity ID of the alarm-filter
        :type entity_id: str
        :returns: <AlarmFilter>
        :rtype: dict
        """
        dico = request.json

        if dico is None or not isinstance(dico, dict) or len(dico) <= 0:
            return gen_json_error(
                {'description': 'wrong update dict'}, HTTP_ERROR)

        af = am.alarm_filters.update_filter(filter_id=entity_id, values=dico)
        if not isinstance(af, AlarmFilter):
            return gen_json_error({'description': 'failed to update filter'},
                                  HTTP_ERROR)

        return gen_json(af.serialize())

    @ws.application.delete(
        '/api/v2/alerts/filters/<entity_id:id_filter>'
    )
    def delete_id(entity_id):
        """
        Delete a filter, based on his id.

        :param entity_id: Entity ID of the alarm-filter
        :type entity_id: str

        :rtype: dict
        """
        ws.logger.info('Delete alarm-filter : {}'.format(entity_id))

        return gen_json(am.alarm_filters.delete_filter(entity_id))

    @ws.application.delete(
        '/api/v2/alerts/<mfilter>'
    )
    def delete_filter(mfilter):
        """
        :param str mfilter: mongo filter
        :rtype: dict
        """
        return gen_json(ar.alarm_storage._backend.remove(json.loads(mfilter)))

    @ws.application.post(
        '/api/v2/alerts/done'
    )
    def done_action():
        """
        Trigger done action.

        For json payload, see doc/docs/fr/guide_developpeur/apis/v2/alerts.md

        :rtype: dict
        """
        dico = request.json

        if dico is None or not isinstance(dico, dict) or len(dico) <= 0:
            return gen_json_error(
                {'description': 'wrong done dict'}, HTTP_ERROR)

        author = dico.get(am.AUTHOR)
        event = forger(
            event_type=Check.EVENT_TYPE,
            author=author,
            connector=dico.get('connector'),
            connector_name=dico.get('connector_name'),
            component=dico.get('component'),
            output=dico.get('comment')
        )
        if dico.get('source_type', None) == 'resource':
            event['resource'] = dico['resource']
            event['source_type'] = 'resource'
        ws.logger.debug('Received done action: {}'.format(event))

        entity_id = am.context_manager.get_id(event)
        retour = am.execute_task(
            'alerts.useraction.done',
            event=event,
            author=author,
            entity_id=entity_id
        )
        return gen_json(retour)
Пример #15
0
class ComputeState(BaseTest):
    def setUp(self):
        super(ComputeState, self).setUp()
        pbehavior_storage = Middleware.get_middleware_by_uri(
            'storage-default-testpbehavior://')
        filter_storage = Middleware.get_middleware_by_uri(
            'storage-default-testalarmfilter://')
        config_storage = Middleware.get_middleware_by_uri(
            'storage-default-testconfig://')
        config_storage.put_element(element={
            '_id': 'test_config',
            'crecord_type': 'statusmanagement',
            'bagot_time': 3600,
            'bagot_freq': 10,
            'stealthy_time': 300,
            'restore_event': True,
            'auto_snooze': False,
            'snooze_default_time': 300,
        },
                                   _id='test_config')
        logger = Logger.get('test_pb', None, output_cls=OutputNull)

        config = Configuration.load(PBehaviorManager.CONF_PATH, Ini)

        self.pbm = PBehaviorManager(config=config,
                                    logger=logger,
                                    pb_storage=pbehavior_storage)
        self.pbm.context = self.context_graph_manager
        self.manager.pbehavior_manager = self.pbm

        conf = Configuration.load(Alerts.CONF_PATH, Ini)
        filter_ = {'crecord_type': 'statusmanagement'}
        config_data = EtherealData(collection=config_storage._backend,
                                   filter_=filter_)

        event_publisher = Mock(spec=StatEventPublisher)

        self.alert_manager = Alerts(config=conf,
                                    logger=logger,
                                    alerts_storage=self.alerts_storage,
                                    config_data=config_data,
                                    filter_storage=filter_storage,
                                    context_graph=self.context_graph_manager,
                                    watcher=self.manager,
                                    event_publisher=event_publisher)

        # Creating entity
        self.type_ = 'resource'
        self.name = 'morticia'
        entity = ContextGraph.create_entity_dict(id=self.name,
                                                 etype=self.type_,
                                                 name=self.name)
        self.context_graph_manager.create_entity(entity)

        # Creating coresponding alarm
        event = {
            'connector': self.type_,
            'connector_name': 'connector_name',
            'component': self.name,
            'output': 'tadaTaDA tic tic',
            'timestamp': 0
        }
        alarm = self.alert_manager.make_alarm(self.name, event)
        self.state = 2
        alarm = self.alert_manager.update_state(alarm, self.state, event)
        new_value = alarm[self.alert_manager.alerts_storage.VALUE]
        self.alert_manager.update_current_alarm(alarm, new_value)

    def tearDown(self):
        super(ComputeState, self).tearDown()
        self.pbm.pb_storage.remove_elements()

    def test_compute_state_issue427(self):
        # Aka: state desyncro
        watcher_id = 'addams'
        watcher = {
            '_id': watcher_id,
            'mfilter': '{"name": {"$in": ["morticia"]}}',
            'display_name': 'family'
        }
        self.assertTrue(self.manager.create_watcher(watcher))

        res = self.manager.get_watcher(watcher_id)
        self.assertEqual(res['state'], self.state)

        # Creating pbehavior on it
        now = datetime.utcnow()
        self.pbm.create(name='addam',
                        filter=loads('{"name": "morticia"}'),
                        author='addams',
                        tstart=timegm(now.timetuple()),
                        tstop=timegm((now + timedelta(seconds=2)).timetuple()),
                        rrule=None,
                        enabled=True)
        self.pbm.compute_pbehaviors_filters()

        res = self.manager.get_watcher(watcher_id)
        self.assertEqual(res['state'], self.state)

        self.manager.compute_watchers()

        res = self.manager.get_watcher(watcher_id)
        self.assertEqual(res['state'], 0)

        sleep(3)
        self.pbm.compute_pbehaviors_filters()
        self.manager.compute_watchers()

        res = self.manager.get_watcher(watcher_id)
        self.assertEqual(res['state'], self.state)
Пример #16
0
    def setUp(self):
        super(ComputeState, self).setUp()
        pbehavior_storage = Middleware.get_middleware_by_uri(
            'storage-default-testpbehavior://')
        filter_storage = Middleware.get_middleware_by_uri(
            'storage-default-testalarmfilter://')
        config_storage = Middleware.get_middleware_by_uri(
            'storage-default-testconfig://')
        config_storage.put_element(element={
            '_id': 'test_config',
            'crecord_type': 'statusmanagement',
            'bagot_time': 3600,
            'bagot_freq': 10,
            'stealthy_time': 300,
            'restore_event': True,
            'auto_snooze': False,
            'snooze_default_time': 300,
        },
                                   _id='test_config')
        logger = Logger.get('test_pb', None, output_cls=OutputNull)

        config = Configuration.load(PBehaviorManager.CONF_PATH, Ini)

        self.pbm = PBehaviorManager(config=config,
                                    logger=logger,
                                    pb_storage=pbehavior_storage)
        self.pbm.context = self.context_graph_manager
        self.manager.pbehavior_manager = self.pbm

        conf = Configuration.load(Alerts.CONF_PATH, Ini)
        filter_ = {'crecord_type': 'statusmanagement'}
        config_data = EtherealData(collection=config_storage._backend,
                                   filter_=filter_)

        event_publisher = Mock(spec=StatEventPublisher)

        self.alert_manager = Alerts(config=conf,
                                    logger=logger,
                                    alerts_storage=self.alerts_storage,
                                    config_data=config_data,
                                    filter_storage=filter_storage,
                                    context_graph=self.context_graph_manager,
                                    watcher=self.manager,
                                    event_publisher=event_publisher)

        # Creating entity
        self.type_ = 'resource'
        self.name = 'morticia'
        entity = ContextGraph.create_entity_dict(id=self.name,
                                                 etype=self.type_,
                                                 name=self.name)
        self.context_graph_manager.create_entity(entity)

        # Creating coresponding alarm
        event = {
            'connector': self.type_,
            'connector_name': 'connector_name',
            'component': self.name,
            'output': 'tadaTaDA tic tic',
            'timestamp': 0
        }
        alarm = self.alert_manager.make_alarm(self.name, event)
        self.state = 2
        alarm = self.alert_manager.update_state(alarm, self.state, event)
        new_value = alarm[self.alert_manager.alerts_storage.VALUE]
        self.alert_manager.update_current_alarm(alarm, new_value)
Пример #17
0
    def setUp(self):
        super(ComputeState, self).setUp()
        pbehavior_storage = Middleware.get_middleware_by_uri(
            'storage-default-testpbehavior://'
        )
        filter_storage = Middleware.get_middleware_by_uri(
            'storage-default-testalarmfilter://'
        )
        config_storage = Middleware.get_middleware_by_uri(
            'storage-default-testconfig://'
        )
        config_storage.put_element(
            element={
                '_id': 'test_config',
                'crecord_type': 'statusmanagement',
                'bagot_time': 3600,
                'bagot_freq': 10,
                'stealthy_time': 300,
                'restore_event': True,
                'auto_snooze': False,
                'snooze_default_time': 300,
            },
            _id='test_config'
        )
        logger = Logger.get('test_pb', None, output_cls=OutputNull)

        config = Configuration.load(PBehaviorManager.CONF_PATH, Ini)

        self.pbm = PBehaviorManager(config=config,
                                    logger=logger,
                                    pb_storage=pbehavior_storage)
        self.pbm.context = self.context_graph_manager
        self.manager.pbehavior_manager = self.pbm

        conf = Configuration.load(Alerts.CONF_PATH, Ini)
        filter_ = {'crecord_type': 'statusmanagement'}
        config_data = EtherealData(collection=config_storage._backend,
                                   filter_=filter_)

        event_publisher = Mock(spec=StatEventPublisher)

        self.alert_manager = Alerts(config=conf,
                                    logger=logger,
                                    alerts_storage=self.alerts_storage,
                                    config_data=config_data,
                                    filter_storage=filter_storage,
                                    context_graph=self.context_graph_manager,
                                    watcher=self.manager,
                                    event_publisher=event_publisher)

        # Creating entity
        self.type_ = 'resource'
        self.name = 'morticia'
        entity = ContextGraph.create_entity_dict(
            id=self.name,
            etype=self.type_,
            name=self.name
        )
        self.context_graph_manager.create_entity(entity)

        # Creating coresponding alarm
        event = {
            'connector': self.type_,
            'connector_name': 'connector_name',
            'component': self.name,
            'output': 'tadaTaDA tic tic',
            'timestamp': 0
        }
        alarm = self.alert_manager.make_alarm(self.name, event)
        self.state = 2
        alarm = self.alert_manager.update_state(alarm, self.state, event)
        new_value = alarm[self.alert_manager.alerts_storage.VALUE]
        self.alert_manager.update_current_alarm(alarm, new_value)