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