Beispiel #1
0
    def __init__(self, user, mask_closed_events=True, search=None, sort=None, order=None):
        """
        Initialisation de l'objet qui effectue les requêtes de VigiBoard
        sur la base de données.
        Cet objet est responsable de la vérification des droits de
        l'utilisateur sur les données manipulées.

        @param user: Nom de l'utilisateur cherchant à afficher les événements.
        @type  user: C{str}
        @param mask_closed_events: Booléen indiquant si l'on souhaite masquer les
            événements fermés ou non.
        @type  mask_closed_events: C{boolean}
        @param search: Dictionnaire contenant les critères de recherche.
        @type  search: C{dict}
        @param sort: Colonne de tri; vide en l'absence de tri.
        @type  sort: C{unicode}
        @param order: Ordre du tri ("asc" ou "desc"); vide en l'absence de tri.
        @type  order: C{unicode}

        """

        # Permet s'appliquer des filtres de recherche aux sous-requêtes.
        self.subqueries = []
        self.generaterq = False

        # Éléments à retourner (SELECT ...)
        self.table = []

        # Tables sur lesquelles porte la récupération (JOIN)
        self.join = []

        # Options à ajouter la requête
        self.option = []

        # Tables sur lesquelles porte la récupération (OUTER JOIN)
        self.outerjoin = []

        # Critères de filtrage (WHERE)
        self.filter = []

        # Regroupements (GROUP BY)
        # PostgreSQL est pointilleux sur les colonnes qui apparaissent
        # dans la clause GROUP BY. Si une colonne apparaît dans ORDER BY,
        # elle doit systématiquement apparaître AUSSI dans GROUP BY.
        self.groupby = [
            StateName.order,
            Event.timestamp,
            CorrEvent.ack,
            CorrEvent.priority,
            StateName.statename,
        ]

        self.req = DBSession
        self.plugin = []
        self.events = []

        # Si l'utilisateur est privilégié, il a accès
        # à tous les hôtes/services sans restriction.
        if config.is_manager.is_met(request.environ):
            # Sélection de tous les services de la BDD.
            lls_query = DBSession.query(
                LowLevelService.idservice.label("idsupitem"),
                LowLevelService.servicename.label("servicename"),
                Host.name.label("hostname"),
            ).join(
                (Host, Host.idhost == LowLevelService.idhost),
            ).distinct()

            # Sélection de tous les hôtes de la BDD.
            host_query = DBSession.query(
                Host.idhost.label("idsupitem"),
                expr_null().label("servicename"),
                Host.name.label("hostname"),
            ).distinct()

            # Application des filtres des plugins si nécessaire.
            if search is not None:
                # On tire ici partie du fait que les listes sont passées
                # par référence dans les fonctions.
                subqueries = [lls_query, host_query]
                for _plugin, instance in config.get('columns_plugins', []):
                    instance.handle_search_fields(
                        self, search, INNER, subqueries)
                lls_query = subqueries[0]
                host_query = subqueries[1]

            # Union des deux sélections précédentes
            self.items = union_all(
                lls_query,
                host_query,
                correlate=False
            ).alias()

        # Sinon, on ne récupère que les hôtes/services auquel il a accès.
        else:
            items = DBSession.query(
                UserSupItem.idsupitem,
                UserSupItem.servicename,
                UserSupItem.hostname,
            ).filter(
                UserSupItem.username == user.user_name
            ).distinct()

            # Application des filtres des plugins si nécessaire.
            if search is not None:
                # On tire ici partie du fait que les listes sont passées
                # par référence dans les fonctions.
                subqueries = [items]
                for _plugin, instance in config.get('columns_plugins', []):
                    instance.handle_search_fields(
                        self, search, INNER, subqueries)
                items = subqueries[0]

            # Permet d'avoir le même format que pour l'autre requête.
            self.items = items.subquery()

        # Tris (ORDER BY)
        # Permet de répondre aux exigences suivantes :
        # - VIGILO_EXIG_VIGILO_BAC_0050
        # - VIGILO_EXIG_VIGILO_BAC_0060
        self.orderby = []
        if sort:
            for _plugin, instance in config.get('columns_plugins', []):
                criterion = instance.get_sort_criterion(self, sort)
                if criterion is not None:
                    if order == 'asc':
                        self.orderby.append(asc(criterion))
                    else:
                        self.orderby.append(desc(criterion))

        # Permet de définir le sens de tri pour la priorité.
        if config['vigiboard_priority_order'] == 'asc':
            priority_order = asc(CorrEvent.priority)
        else:
            priority_order = desc(CorrEvent.priority)

        self.orderby.extend([
            asc(CorrEvent.ack),                             # État acquittement
            asc(StateName.statename.in_([u'OK', u'UP'])),   # Vert / Pas vert
            priority_order,                                 # Priorité ITIL
        ])

        if asbool(config.get('state_first', True)):
            self.orderby.extend([
                desc(StateName.order),                      # Etat courant
                desc(Event.timestamp),                      # Timestamp
            ])
        else:
            self.orderby.extend([
                desc(Event.timestamp),                      # Timestamp
                desc(StateName.order),                      # Etat courant
            ])

        if search is not None:
            # 2nde passe pour les filtres : self.items est désormais défini.
            for _plugin, instance in config.get('columns_plugins', []):
                instance.handle_search_fields(self, search, ITEMS, subqueries)

        if mask_closed_events:
            self.filter.append(
                # On masque les événements avec l'état OK
                # et traités (ack == CorrEvent.ACK_CLOSED).
                not_(and_(
                    StateName.statename.in_([u'OK', u'UP']),
                    CorrEvent.ack == CorrEvent.ACK_CLOSED
                ))
            )
Beispiel #2
0
    def get_json_data(self, idcorrevent, *args, **kwargs):
        """
        Renvoie les éléments pour l'affichage de la fenêtre de dialogue
        contenant des détails sur un événement corrélé.

        @param idcorrevent: identifiant de l'événement corrélé.
        @type idcorrevent: C{int}
        """

        # Obtention de données sur l'événement et sur son historique
        host_query = DBSession.query(
            Host.idhost.label("idsupitem"),
            Host.idhost.label("idhost"),
            Host.name.label("host"),
            expr_null().label("service"),
        )
        lls_query = DBSession.query(
            LowLevelService.idservice.label("idsupitem"),
            Host.idhost.label("idhost"),
            Host.name.label("host"),
            LowLevelService.servicename.label("service"),
        ).join(
            (Host, Host.idhost == LowLevelService.idhost),
        )
        supitems = union_all(lls_query, host_query, correlate=False).alias()
        event = DBSession.query(
            CorrEvent.idcorrevent,
            CorrEvent.idcause,
            supitems.c.idhost,
            supitems.c.host,
            supitems.c.service,
            Event.message,
            Event.initial_state,
            Event.current_state,
            Event.peak_state
        ).join(
            (Event, Event.idevent == CorrEvent.idcause),
            (supitems, supitems.c.idsupitem == Event.idsupitem),
        ).filter(CorrEvent.idcorrevent == idcorrevent
        ).first()

        # On détermine les cartes auxquelles cet utilisateur a accès.
        user_maps = []
        max_maps = int(config['max_maps'])
        is_manager = config.is_manager.is_met(request.environ)
        if max_maps != 0 and (is_manager or
            has_permission('vigimap-access').is_met(request.environ)):
            items = DBSession.query(
                    Map.idmap,
                    Map.title,
                    func.lower(Map.title),
                ).distinct(
                ).join(
                    (MAP_GROUP_TABLE, MAP_GROUP_TABLE.c.idmap == Map.idmap),
                    (MapGroup, MapGroup.idgroup == MAP_GROUP_TABLE.c.idgroup),
                    (MapNodeHost, MapNodeHost.idmap == Map.idmap),
                ).order_by(func.lower(Map.title).asc()
                ).filter(MapNodeHost.idhost == event.idhost)

            if not is_manager:
                mapgroups = get_current_user().mapgroups(only_direct=True)
                # pylint: disable-msg=E1103
                items = items.filter(MapGroup.idgroup.in_(mapgroups))

            # La valeur -1 supprime la limite.
            if max_maps > 0:
                # On limite au nombre maximum de cartes demandés + 1.
                # Un message sera affiché s'il y a effectivement plus
                # de cartes que la limite configurée.
                items = items.limit(max_maps + 1)

            user_maps = [(m.idmap, m.title) for m in items.all()]

        context = {
            'idcorrevent': idcorrevent,
            'host': event.host,
            'service': event.service,
            'message': event.message,
            'maps': user_maps,
            'current_state': StateName.value_to_statename(event.current_state),
            'initial_state': StateName.value_to_statename(event.initial_state),
            'peak_state': StateName.value_to_statename(event.peak_state),
        }

        eventdetails = {}
        for edname, edlink in enumerate(config['vigiboard_links.eventdetails']):
            # Évite que les gardes ne se polluent entre elles.
            local_ctx = context.copy()

            # Les liens peuvent être conditionnés à l'aide
            # d'une expression ou d'un callable qui agira
            # comme un prédicat de test.
            if 'only_if' in edlink:
                if callable(edlink['only_if']):
                    display_link = edlink['only_if'](local_ctx)
                else:
                    display_link = edlink['only_if']
                if not display_link:
                    continue

            if callable(edlink['uri']):
                uri = edlink['uri'](local_ctx)
            else:
                uri = edlink['uri'] % local_ctx

            eventdetails[unicode(edname)] = {
                'url': url(uri),
                'target': edlink.get('target', '_blank')
            }

        return dict(
                current_state = StateName.value_to_statename(
                                    event.current_state),
                initial_state = StateName.value_to_statename(
                                    event.initial_state),
                peak_state = StateName.value_to_statename(
                                    event.peak_state),
                idcorrevent = idcorrevent,
                host = event.host,
                service = event.service,
                eventdetails = eventdetails,
                maps = user_maps,
                idcause = event.idcause,
            )