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)
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