Example #1
0
def handle_ticket(info_dictionary):
    """
    Met à jour l'historique d'un évènement corrélé dans la base de
    données après la réception d'un message sur le bus indiquant
    la modification du ticket d'incident qui lui est associé.

    @param info_dictionary: Dictionnaire contenant les
    informations extraites du message reçu par le rule dispatcher.
    @type info_dictionary: C{dictionary}

    Cette fonction permet de satisfaire l'exigence VIGILO_EXIG_VIGILO_BAC_0120
    """
    LOGGER.debug(_(u'handle_ticket: Trouble ticket message received. '
                 'Timestamp = %(timestamp)r. Impacted HLS = %(hls)r. '
                 'Ticket id = %(ticket_id)r. acknowledgement_status = '
                 '%(ack_status)r. Message = %(message)r.'),
                 {
                    'timestamp': info_dictionary["timestamp"],
                    'hls': info_dictionary["impacted_HLS"],
                    'ticket_id': info_dictionary["ticket_id"],
                    'ack_status': info_dictionary["acknowledgement_status"],
                    'message': info_dictionary["message"],
                 })

    # On cherche dans la BDD l'évènement
    # corrélé associé à ce ticket d'incident.
    try:
        correvent = DBSession.query(
                    CorrEvent
                ).filter(
                    CorrEvent.trouble_ticket == info_dictionary["ticket_id"]
                ).one()
    except NoResultFound:
        # Si aucun évènement n'est trouvé on loggue une erreur.
        LOGGER.error(_(u'handle_ticket: No matching trouble ticket found : %r'),
                       info_dictionary["ticket_id"])
        return

    except MultipleResultsFound:
        # Si plusieurs évènements sont trouvés on loggue une erreur.
        LOGGER.error(_(u'handle_ticket: Several events seem to be associated '
                       'with this ticket : %r'), info_dictionary["ticket_id"])
        return
    LOGGER.debug(_(u'handle_ticket: The event %(event_id)r is '
                   'associated with the given ticket (%(ticket_id)r)'), {
                        'event_id': correvent.idcorrevent,
                        'ticket_id': info_dictionary["ticket_id"],
                    })

    # Mise à jour de l'historique de l'évènement corrélé :
    history = EventHistory()
    history.type_action = u'Ticket change notification'
    history.idevent = correvent.idcorrevent
    history.value = info_dictionary['ticket_id']
    history.text = '%r;%r;%r' % (info_dictionary['acknowledgement_status'],
                                 info_dictionary['message'],
                                 info_dictionary['impacted_HLS'])
    history.timestamp = info_dictionary['timestamp']
    history.username = None

    try:
        DBSession.add(history)
        DBSession.flush()

    except (IntegrityError, InvalidRequestError):
        LOGGER.exception(_(u'handle_ticket: Got exception while updating '
                            'event %r history'), correvent.idcorrevent)

    else:
        LOGGER.debug(_(u'handle_ticket: Event %r history updated '
                        'successfully.'), correvent.idcorrevent)
Example #2
0
def insert_event(info_dictionary):
    """
    Insère un événement dans la BDD.
    Retourne l'identifiant de cet événement.

    @param info_dictionary: Dictionnaire contenant les informations
    extraites du message d'alerte reçu par le rule dispatcher.
    @type info_dictionary: C{dict}
    @return: L'identifiant de l'événement dans la BDD.
    @rtype: C{int}
    """

    # S'il s'agit d'un événement concernant un HLS.
    if not info_dictionary["host"]:
        LOGGER.error(_('Received request to add an event on HLS "%s"'),
                            info_dictionary["service"])
        return None

    if not info_dictionary['idsupitem']:
        LOGGER.error(_('Got a reference to a non configured item '
                       '(%(host)r, %(service)r), skipping event'), {
                            "host": info_dictionary["host"],
                            "service": info_dictionary["service"],
                        })
        return None

    # On recherche un éventuel évènement brut concernant cet item.
    # L'événement doit être associé à un événement corrélé ouvert
    # ou bien ne pas être à rattaché à un événement corrélé du tout.
    cause_event = aliased(Event)
    current_event = aliased(Event)
    # On privilégie les événements bruts associés à un événement corrélé.
    order_clause = (CorrEvent.idcorrevent != None)
    event = DBSession.query(
                current_event,
                order_clause,   # Doit être présent dans le SELECT
                                # pour satisfaire PostgreSQL.
            ).outerjoin(
                (EVENTSAGGREGATE_TABLE, EVENTSAGGREGATE_TABLE.c.idevent ==
                    current_event.idevent),
                (CorrEvent, CorrEvent.idcorrevent ==
                    EVENTSAGGREGATE_TABLE.c.idcorrevent),
                (cause_event, cause_event.idevent == CorrEvent.idcause),
            ).filter(current_event.idsupitem == info_dictionary['idsupitem']
            ).filter(
                or_(
                    # Soit l'événement brut n'est pas
                    # rattaché à un événement corrélé.
                    CorrEvent.idcorrevent == None,

                    # Soit l'événement corrélé auquel
                    # il est rattaché est toujours ouvert.
                    not_(
                        and_(
                            cause_event.current_state.in_([
                                StateName.statename_to_value(u'OK'),
                                StateName.statename_to_value(u'UP')
                            ]),
                            CorrEvent.ack == CorrEvent.ACK_CLOSED
                        )
                    )
                )
            ).order_by(order_clause.desc()
            ).distinct().limit(2).all()

    # Si aucun événement correpondant à cet item ne figure dans la base
    if not event:
        # Si l'état de cette alerte est 'OK', on l'ignore
        if info_dictionary["state"] == "OK" or \
            info_dictionary["state"] == "UP":
            LOGGER.info(_('Ignoring request to create a new event '
                            'with state "%s" (nothing alarming here)'),
                            info_dictionary['state'])
            raise NoProblemException(info_dictionary.copy())
        # Sinon, il s'agit d'un nouvel incident, on le prépare.
        event = Event()
        event.idsupitem = info_dictionary['idsupitem']
        LOGGER.debug(_('Creating new event'))

    # Si plusieurs événements ont été trouvés
    else:
        if len(event) > 1:
            LOGGER.warning(_('Multiple raw events found, '
                             'using the first one available.'))
        # On sélectionne le premier Event parmi la liste
        # des tuples (Event, CorrEvent.idcorrevent != None).
        event = event[0][0]
        LOGGER.debug(_('Updating event %r'), event.idevent)

    # Nouvel état.
    new_state_value = StateName.statename_to_value(info_dictionary['state'])
    is_new_event = event.idevent is None

    # S'agit-il d'un événement important ?
    # Un événement est important s'il s'agit d'un nouvel événement
    # ou si un champ autre que le timestamp ou le message a changé.
    info_dictionary['important'] = is_new_event or \
                                    event.current_state != new_state_value or \
                                    event.message != info_dictionary['message']


    # Mise à jour de l'évènement.
    event.timestamp = info_dictionary['timestamp']
    event.current_state = new_state_value
    event.message = info_dictionary['message']

    # Sauvegarde de l'évènement.
    DBSession.add(event)

    # Les événements importants donnent lieu à l'ajout
    # d'une entrée dans l'historique.
    if info_dictionary['important']:
        history = EventHistory()

        history.type_action = is_new_event and \
                                u'New occurrence' or \
                                u'Nagios update state'

        try:
            history.state = \
                StateName.statename_to_value(info_dictionary['state'])
        except KeyError:
            # Si le nom d'état n'est pas reconnu, on ne fait rien.
            pass

        history.value = info_dictionary['state']
        history.text = info_dictionary['message']
        history.timestamp = info_dictionary['timestamp']
        history.username = None
        history.event = event
        DBSession.add(history)

    DBSession.flush()
    return event.idevent