Beispiel #1
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 = {}

    for key, value in event.items():
Beispiel #2
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)
Beispiel #3
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 = {}

    for key, value in event.items():
        try:
Beispiel #4
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)
Beispiel #5
0
def exports(ws):
    alr = AlertsReader(*AlertsReader.provide_default_basics())
    manager = ContextGraph(ws.logger)

    DEFAULT_ACTIVE_COLUMNS = ["name", "type"]

    @route(ws.application.get)
    def context(_type, names=None, context=None, extended=None):
        if names:
            names = [n.strip() for n in names.split(',')]
        """
        result = manager.get(
            _type=_type, names=names, context=context, extended=extended)
        """
        # this is a test before adapter refactoring
        result = manager.get_entities_by_id(names)
        return result

    @route(ws.application.get, name='context/ids')
    @route(ws.application.post,
           payload=['ids', 'limit', 'start', 'sort', 'with_count'],
           name='context/ids')
    def context_by_id(ids=None, limit=0, start=0, sort=None, with_count=False):
        """
        result = manager.get(
            ids=ids,
            limit=limit,
            skip=start,
            sort=sort,
            with_count=with_count
        )
        """
        result = manager.get_entities_by_id(ids)

        return result

    @route(ws.application.post,
           payload=[
               'limit', 'start', 'sort', '_filter', 'search', 'active_columns'
           ])
    def context(context=None,
                _filter=None,
                search='',
                extended=False,
                limit=0,
                start=0,
                sort=None,
                active_columns=None):
        query = {}
        if _filter is not None:
            query.update(_filter)

        final_filter = {'$and': [query]}
        # try grammar search
        try:
            _, bnf_search_filter = alr.interpret_search(search)
        except ValueError as e:
            ws.logger.exception(e)
            bnf_search_filter = None

        if request.json:
            active_columns = request.json.get('active_columns', [])
        if not active_columns:
            active_columns = DEFAULT_ACTIVE_COLUMNS

        if bnf_search_filter is not None:
            final_filter['$and'].append(bnf_search_filter)
        else:
            escaped_search = re.escape(str(search).decode('utf-8'))
            column_filter = {'$or': []}
            for column in active_columns:
                column_filter['$or'].append({
                    column: {
                        '$regex': u'.*{}.*'.format(escaped_search),
                        '$options': 'i'
                    }
                })
            final_filter['$and'].append(column_filter)
        data, count = manager.get_entities(query=final_filter,
                                           limit=limit,
                                           start=start,
                                           sort=sort,
                                           with_count=True)

        return data, count

    @route(ws.application.put,
           payload=['_type', 'entity', 'context', 'extended_id'])
    def context(_type, entity, context=None, extended_id=None):
        """
        manager.put(
            _type=_type,
            entity=entity,
            context=context,
            extended_id=extended_id
        )
        """
        manager.update_entity(entity=entity)
        return entity

    @route(ws.application.delete,
           payload=['context', 'ids', '_type', 'extended'])
    def context(ids=None, _type=None, context=None, extended=False):
        """
        manager.remove(
            ids=ids,
            _type=_type,
            context=context,
            extended=extended
        )"""
        manager.delete_entity(ids)
Beispiel #6
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)