def supitemgroup(self, supitemgroup, partial, noCache): """ Auto-compléteur pour les noms des groupes d'éléments supervisés. @param supitemgroup: Motif qui doit apparaître dans le nom du groupe d'éléments supervisés. @type supitemgroup: C{unicode} @return: Un dictionnaire dont la clé 'results' contient la liste des noms de groupes d'élements supervisés correspondant au motif donné et auxquels l'utilisateur a accès. @rtype: C{dict} """ supitemgroup = sql_escape_like(supitemgroup) user = get_current_user() if not user: return dict(results=[]) if partial: supitemgroup += "%" supitemgroups = DBSession.query(SupItemGroup.name).distinct().filter(SupItemGroup.name.ilike(supitemgroup)) if not config.is_manager.is_met(request.environ): user_groups = [ug[0] for ug in user.supitemgroups() if ug[1]] supitemgroups = supitemgroups.filter(SupItemGroup.idgroup.in_(user_groups)) supitemgroups = supitemgroups.all() return dict(results=[s.name for s in supitemgroups])
def get_service(idservice, service_type, idhost=None): """ Retourne un service à partir de son ID ou de son nom. Si le service est un service de bas niveau (C{tables.LowLevelService}), il faut aussi fournir un identifiant d'hôte (ID ou nom). @param idservice: l'identifiant du service à récupérer, ou son nom @type idservice: C{int} ou C{str} @param service_type: le type de service à récupérer @type service_type: C{str}: C{lls} ou C{hls} @param idhost: l'identifiant de l'hôte associé au service, ou son nom @type idhost: C{int} ou C{str} """ try: idservice = int(idservice) except ValueError: # on a reçu un nom de service if service_type == "lls": if idhost is None: raise HTTPNotFound("Can't find the host, you must use " "the numeric service ID") host = get_host(idhost) service = tables.LowLevelService.by_host_service_name(host.name, idservice) elif service_type == "hls": service = tables.HighLevelService.by_service_name(idservice) else: service = DBSession.query(tables.Service).get(idservice) if service is None: raise HTTPNotFound("Can't find the service: %s" % idservice) # ACLs user = get_current_user() if not user: raise HTTPForbidden("You must be logged in") if not service.is_allowed_for(user): raise HTTPForbidden("Access to this service is forbidden") return service
def plugin_json(self, idcorrevent, plugin_name, *arg, **krgv): """ Permet de récupérer la valeur d'un plugin associée à un CorrEvent donné via JSON. """ # Vérification de l'existence du plugin plugins = dict(config['columns_plugins']) if plugin_name not in plugins: raise HTTPNotFound(_("No such plugin '%s'") % plugin_name) # Récupération de la liste des évènements corrélés events = DBSession.query(CorrEvent.idcorrevent) # Filtrage des évènements en fonction des permissions de # l'utilisateur (s'il n'appartient pas au groupe 'managers') if not config.is_manager.is_met(request.environ): user = get_current_user() events = events.join( (Event, Event.idevent == CorrEvent.idcause), ).outerjoin( (LowLevelService, LowLevelService.idservice == Event.idsupitem), ).join( (SUPITEM_GROUP_TABLE, or_( SUPITEM_GROUP_TABLE.c.idsupitem == \ LowLevelService.idhost, SUPITEM_GROUP_TABLE.c.idsupitem == \ Event.idsupitem, ) ), ).join( (GroupHierarchy, GroupHierarchy.idchild == SUPITEM_GROUP_TABLE.c.idgroup), ).join( (DataPermission, DataPermission.idgroup == GroupHierarchy.idparent), ).join( (USER_GROUP_TABLE, USER_GROUP_TABLE.c.idgroup == DataPermission.idusergroup), ).filter(USER_GROUP_TABLE.c.username == user.user_name) # Filtrage des évènements en fonction # de l'identifiant passé en paramètre events = events.filter(CorrEvent.idcorrevent == idcorrevent).count() # Pas d'événement ou permission refusée. On ne distingue pas # les 2 cas afin d'éviter la divulgation d'informations. if events == 0: raise HTTPNotFound(_('No such incident or insufficient ' 'permissions')) # L'évènement existe bien, et l'utilisateur dispose # des permissions appropriées. On fait alors appel au # plugin pour récupérer les informations à retourner. return plugins[plugin_name].get_json_data(idcorrevent, *arg, **krgv)
def event(self, idevent, page): """ Affichage de l'historique d'un événement brut. Pour accéder à cette page, l'utilisateur doit être authentifié. @param idevent: identifiant de l'événement brut souhaité. @type idevent: C{int} @param page: numéro de la page à afficher. @type page: C{int} Cette méthode permet de satisfaire l'exigence VIGILO_EXIG_VIGILO_BAC_0080. """ # Auto-supervision self.get_failures() user = get_current_user() events = VigiboardRequest(user, False) events.add_table( Event, events.items.c.hostname.label('hostname'), events.items.c.servicename.label('servicename'), ) events.add_join((EVENTSAGGREGATE_TABLE, \ EVENTSAGGREGATE_TABLE.c.idevent == Event.idevent)) events.add_join((CorrEvent, CorrEvent.idcorrevent == \ EVENTSAGGREGATE_TABLE.c.idcorrevent)) events.add_join((events.items, Event.idsupitem == events.items.c.idsupitem)) events.add_filter(Event.idevent == idevent) if events.num_rows() != 1: flash(_('No such event or access denied'), 'error') redirect('/') events.format_events(0, 1) events.generate_tmpl_context() history = events.format_history() # Pagination des résultats items_per_page = int(session.get('items_per_page', config['vigiboard_items_per_page'])) page = paginate.Page(history, page=page, items_per_page=items_per_page) event = events.req[0] return dict( idevent = idevent, hostname = event.hostname, servicename = event.servicename, plugins_data = {}, page = page, search_form = create_search_form, search = {}, fixed_search = {}, )
def create_or_modify( self, states, host, service=None, # start=time.time(), # end=time.time(), comment=None, idsilence=None): """ Ajoute une règle de mise en silence d'un hôte/service, ou en modifie une déjà existante. @param states: (optionnel) Liste des états concernés par la règle. @type states: C{list} of C{unicode} @param host: Nom de l'hôte sur lequel porte la règle. @type host: C{unicode} @param service: (optionnel) Nom du service sur lequel porte la règle. @type service: C{unicode} # @param start: Début de la mise en silence planifiée. # @type start: C{str} # @param end: Fin de la mise en silence planifiée. # @type end: C{str} @param comment: (optionnel) Commentaire accompagnant la règle. @type comment: C{unicode} @param idsilence: (optionnel) Identifiant de la règle dans le cas d'une mise à jour. @type idsilence: C{int} """ # TODO: Faire ce traitement dans le schéma de validation if not states: msg = _('No state specified for the silence rule.') self.handle_error_message(msg) states = list(states) # On récupère le nom et l'IP de l'utilisateur. user = get_current_user() user_name = user.user_name user_ip = request.remote_addr # On récupère l'identifiant de l'item (hôte # ou service) concerné par la mise en silence. idsupitem = SupItem.get_supitem(host, service) if idsupitem: try: supitem = DBSession.query(SupItem ).filter(SupItem.idsupitem == idsupitem).one() except InvalidRequestError, e: msg = _('An exception has been raised while ' \ 'querying the database: %s') % str(e) self.handle_error_message(msg)
def service(self, service, host, partial, noCache): """ Auto-compléteur pour les noms des services d'un hôte. @param host: Nom d'hôte (optionnel) sur lequel s'applique l'autocomplétion. @type host: C{unicode} @param service: Motif qui doit apparaître dans le nom de service. @type service: C{unicode} @note: Les caractères '?' et '*' peuvent être utilisés dans le paramètre L{service} pour remplacer un caractère quelconque ou une chaîne de caractères, respectivement. Ex: 'ho?t*' permet de récupérer 'host', 'honte' et 'hostile', mais pas 'hote' ou 'hopital'. @return: Un dictionnaire dont la clé 'results' contient la liste des noms de services configurés sur L{host} (ou sur n'importe quel hôte si L{host} vaut None), correspondant au motif donné et auxquels l'utilisateur a accès. @rtype: C{dict} """ service = sql_escape_like(service) user = get_current_user() if not user: return dict(results=[]) if partial: service += "%" hostgroup = SUPITEM_GROUP_TABLE.alias() servicegroup = SUPITEM_GROUP_TABLE.alias() services = ( DBSession.query(LowLevelService.servicename) .distinct() .outerjoin( (Host, Host.idhost == LowLevelService.idhost), (hostgroup, hostgroup.c.idsupitem == Host.idhost), (servicegroup, servicegroup.c.idsupitem == LowLevelService.idservice), ) .filter(LowLevelService.servicename.ilike(service)) .order_by(LowLevelService.servicename) ) if not config.is_manager.is_met(request.environ): user_groups = [ug[0] for ug in user.supitemgroups() if ug[1]] services = services.filter( or_(hostgroup.c.idgroup.in_(user_groups), servicegroup.c.idgroup.in_(user_groups)) ) if host: services = services.filter(Host.name == host) services = services.all() return dict(results=[s.servicename for s in services])
def _get_allowed_groups(self): """ @return: liste des ID des groupes autorisés pour l'utilisateur courant @rtype: liste de C{int} """ user = get_current_user() #user = tables.User.by_user_name(u"editor") # debug if not user: raise HTTPForbidden("You must be logged in") allowed_groups = None if self.type == "map": allowed_groups = user.mapgroups(only_id=True) elif self.type == "supitem": allowed_groups = [ g[0] for g in user.supitemgroups() ] return allowed_groups
def get_root_groups(self): """ Retourne tous les groupes racines (c'est à dire n'ayant aucun parent) d'hôtes auquel l'utilisateur a accès. @return: Un dictionnaire contenant la liste de ces groupes. @rtype : C{dict} of C{list} of C{dict} of C{mixed} """ # On récupère tous les groupes qui ont un parent. children = DBSession.query( SupItemGroup, ).distinct( ).join( (GroupHierarchy, GroupHierarchy.idchild == SupItemGroup.idgroup) ).filter(GroupHierarchy.hops > 0) # Ensuite on les exclut de la liste des groupes, # pour ne garder que ceux qui sont au sommet de # l'arbre et qui constituent nos "root groups". root_groups = DBSession.query( SupItemGroup, ).except_(children ).order_by(SupItemGroup.name) # On filtre ces groupes racines afin de ne # retourner que ceux auquels l'utilisateur a accès user = get_current_user() if not config.is_manager.is_met(request.environ): root_groups = root_groups.join( (GroupHierarchy, GroupHierarchy.idparent == SupItemGroup.idgroup), (DataPermission, DataPermission.idgroup == GroupHierarchy.idchild), (USER_GROUP_TABLE, USER_GROUP_TABLE.c.idgroup == \ DataPermission.idusergroup), ).filter(USER_GROUP_TABLE.c.username == user.user_name) groups = [] for group in root_groups.all(): groups.append({ 'id' : group.idgroup, 'name' : group.name, 'type' : "group", }) return dict(groups=groups, items=[])
def check_map_access(m): """ Vérifie que l'utilisateur courant a bien accès à la carte donnée en argument @param m: carte à tester @type m: C{tables.Map} """ user = get_current_user() # user = tables.User.by_user_name(u"editor") # debug if not user: raise HTTPForbidden("You must be logged in") allowed_mapgroups = user.mapgroups(only_id=True, only_direct=True) for mapgroup in m.groups: if mapgroup.idgroup in allowed_mapgroups: return True raise HTTPForbidden("Access denied to map %s" % m.idmap)
def host(self, host, partial, noCache): """ Auto-compléteur pour les noms d'hôtes. @param host: Motif qui doit apparaître dans le nom de l'hôte. @type host: C{unicode} @note: Les caractères '?' et '*' peuvent être utilisés dans le paramètre L{host} pour remplacer un caractère quelconque ou une chaîne de caractères, respectivement. Ex: 'ho?t*' permet de récupérer 'host', 'honte' et 'hostile', mais pas 'hote' ou 'hopital'. @return: Un dictionnaire dont la clé 'results' contient la liste des noms d'hôtes correspondant au motif donné en entrée et auxquels l'utilisateur a accès. @rtype: C{dict} """ host = sql_escape_like(host) user = get_current_user() if not user: return dict(results=[]) if partial: host += "%" hostgroup = SUPITEM_GROUP_TABLE.alias() servicegroup = SUPITEM_GROUP_TABLE.alias() hostnames = ( DBSession.query(Host.name) .distinct() .outerjoin( (hostgroup, hostgroup.c.idsupitem == Host.idhost), (LowLevelService, LowLevelService.idhost == Host.idhost), (servicegroup, servicegroup.c.idsupitem == LowLevelService.idservice), ) .filter(Host.name.ilike(host)) .order_by(Host.name) ) if not config.is_manager.is_met(request.environ): user_groups = [ug[0] for ug in user.supitemgroups() if ug[1]] hostnames = hostnames.filter( or_(hostgroup.c.idgroup.in_(user_groups), servicegroup.c.idgroup.in_(user_groups)) ) hostnames = hostnames.all() return dict(results=[h.name for h in hostnames])
def get_all(self): # pylint:disable-msg=C0111,R0201 user = get_current_user() #user = tables.User.by_user_name(u"editor") # debug if not user: raise HTTPForbidden("You must be logged in") mapgroups = user.mapgroups(only_id=False, only_direct=True) result = [] for mapgroup in mapgroups: for m in mapgroup.maps: if m.idmap in [mr["id"] for mr in result]: continue # Déjà ajouté result.append({ "id": m.idmap, "href": tg.url("/api/v%s/maps/%s" % (self.apiver, m.idmap)), "title": m.title, }) return dict(maps=result)
def graph(self, graphname, host, partial, noCache): """ Auto-compléteur pour les noms des graphes. @param graphname: Motif qui doit apparaître dans le nom du graphe. @type graphname: C{unicode} @param host: Nom de l'hôte auquel le graphe doit être rattaché. @type host: C{unicode} @return: Un dictionnaire dont la clé 'results' contient la liste des noms des graphes portant sur L{host}, correspondant au motif donné et auxquels l'utilisateur a accès. @rtype: C{dict} """ graphname = sql_escape_like(graphname) user = get_current_user() if not user: return dict(results=[]) if partial: graphname += "%" graphs = ( DBSession.query(Graph.name) .distinct() .join( (GRAPH_PERFDATASOURCE_TABLE, GRAPH_PERFDATASOURCE_TABLE.c.idgraph == Graph.idgraph), (PerfDataSource, PerfDataSource.idperfdatasource == GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource), (Host, Host.idhost == PerfDataSource.idhost), ) .filter(Graph.name.ilike(graphname)) .filter(Host.name == host) .order_by(Graph.name) ) if not config.is_manager.is_met(request.environ): user_groups = [ug[0] for ug in user.supitemgroups() if ug[1]] graphs = graphs.join((SUPITEM_GROUP_TABLE, SUPITEM_GROUP_TABLE.c.idsupitem == Host.idhost)).filter( SUPITEM_GROUP_TABLE.c.idgroup.in_(user_groups) ) graphs = graphs.all() return dict(results=[g.name for g in graphs])
def get_one(self, idgraph): # pylint:disable-msg=C0111,R0201 graph = DBSession.query(Graph).get(idgraph) if not graph: raise HTTPNotFound("Can't find graph %s" % idgraph) # ACLs user = get_current_user() # user = tables.User.by_user_name(u"editor") # debug for pds in graph.perfdatasources: if not pds.host.is_allowed_for(user): raise HTTPForbidden("Access denied to graphs on host %s" % pds.host.name) result = { "id": graph.idgraph, "href": tg.url("/api/v%s/graphs/%s" % (self.apiver, graph.idgraph)), "name": graph.name, "template": graph.template, "vlabel": graph.vlabel, } groups = [] for group in graph.groups: groups.append( { "id": group.idgroup, "name": group.name, "href": tg.url("/api/v%s/graphgroups/%s" % (self.apiver, group.idgroup)), } ) result["groups"] = groups datasources = [] for pds in graph.perfdatasources: datasources.append( { "id": pds.idperfdatasource, "name": pds.name, "href": tg.url( "/api/v%s/host/%s/perfdatasources/%s" % (self.apiver, pds.idhost, pds.idperfdatasource) ), } ) result["perfdatasources"] = datasources return dict(graph=result)
def searchHost(self, query): """ Affiche les résultats de la recherche par nom d'hôte. La requête de recherche (C{query}) correspond à un préfixe qui sera recherché dans le nom d'hôte. Ce préfixe peut contenir les caractères '*' et '?' qui agissent comme des "jokers". @keyword query: Prefixe de recherche sur les noms d'hôtes @type query: C{unicode} """ if not query: redirect("searchHostForm") return query = sql_escape_like(query.strip()) user = get_current_user() if user is None: return dict(items=[]) # Récupère les hôtes auxquels l'utilisateur a réellement accès. hosts = DBSession.query( Host.name, ).distinct( ).join( (SUPITEM_GROUP_TABLE, SUPITEM_GROUP_TABLE.c.idsupitem == \ Host.idhost), ).filter(Host.name.like(query + u'%') ).order_by(Host.name.asc(),) # Les managers ont accès à tout. # Les autres ont un accès restreint. if not config.is_manager.is_met(request.environ): supitemgroups = [sig[0] for sig in user.supitemgroups() if sig[1]] hosts = hosts.join( (GroupHierarchy, GroupHierarchy.idchild == \ SUPITEM_GROUP_TABLE.c.idgroup) ).filter(GroupHierarchy.idparent.in_(supitemgroups)) return dict(hosts=[h.name for h in hosts])
def hls(self, service, partial, noCache): """ Auto-compléteur pour les noms des services de haut niveau. @param service: Motif qui doit apparaître dans le nom de service. @type service: C{unicode} @note: Les caractères '?' et '*' peuvent être utilisés dans le paramètre L{service} pour remplacer un caractère quelconque ou une chaîne de caractères, respectivement. Ex: 'ho?t*' permet de récupérer 'host', 'honte' et 'hostile', mais pas 'hote' ou 'hopital'. @return: Un dictionnaire dont la clé 'results' contient la liste des noms des services de haut niveau correspondant au motif donné et auxquels l'utilisateur a accès. @rtype: C{dict} """ service = sql_escape_like(service) user = get_current_user() if not user: return dict(results=[]) if partial: service += "%" services = ( DBSession.query(HighLevelService.servicename) .distinct() .filter(HighLevelService.servicename.ilike(service)) .order_by(HighLevelService.servicename) ) # if not config.is_manager.is_met(request.environ): # user_groups = [ug[0] for ug in user.supitemgroups() if ug[1]] # services = services.join( # (SUPITEM_GROUP_TABLE, SUPITEM_GROUP_TABLE.c.idsupitem == \ # HighLevelService.idservice), # ).filter(SUPITEM_GROUP_TABLE.c.idgroup.in_(user_groups)) services = services.all() return dict(results=[s.servicename for s in services])
def perfdatasource(self, ds, host, partial, noCache): """ Auto-compléteur pour les noms des indicateurs de performance. @param ds: Motif qui doit apparaître dans le nom de l'indicateur. @type ds: C{unicode} @param host: Nom de l'hôte auquel l'indicateur doit être rattaché. @type host: C{unicode} @return: Un dictionnaire dont la clé 'results' contient la liste des noms des indicateurs de supervision sur L{host} correspondant au motif donné et auxquels l'utilisateur a accès. @rtype: C{dict} """ ds = sql_escape_like(ds) user = get_current_user() if not user: return dict(results=[]) if partial: ds += "%" perfdatasources = ( DBSession.query(PerfDataSource.name) .distinct() .join((Host, Host.idhost == PerfDataSource.idhost)) .filter(PerfDataSource.name.ilike(ds)) .filter(Host.name == host) .order_by(PerfDataSource.name) ) if not config.is_manager.is_met(request.environ): user_groups = [ug[0] for ug in user.supitemgroups() if ug[1]] perfdatasources = perfdatasources.join( (SUPITEM_GROUP_TABLE, SUPITEM_GROUP_TABLE.c.idsupitem == Host.idhost) ).filter(SUPITEM_GROUP_TABLE.c.idgroup.in_(user_groups)) perfdatasources = perfdatasources.all() return dict(results=[ds.name for ds in perfdatasources])
def get_host(idhost): """ Retourne un hôte (C{tables.Host}) à partir de son ID ou de son nom @param idhost: l'identifiant de l'hôte @type idhost: C{int} ou C{str} """ try: idhost = int(idhost) except ValueError: host = tables.Host.by_host_name(idhost) else: host = DBSession.query(tables.Host).get(idhost) if host is None: raise HTTPNotFound("Can't find the host: %s" % idhost) # ACLs user = get_current_user() # user = tables.User.by_user_name(u"editor") # debug if not user: raise HTTPForbidden("You must be logged in") if not host.is_allowed_for(user): raise HTTPForbidden("Access to this host is forbidden") return host
def get_all_services(model_class): """ Retourne tous les services auxquels l'utilisateur à accès, suivant le type demandé en argument. @param model_class: la classe du modèle correspondante au type de service demandé @type model_class: sous-classe de C{tables.Service} """ user = get_current_user() # user = tables.User.by_user_name(u"editor") # debug if not user: raise HTTPForbidden("You must be logged in") servicegroup = tables.secondary_tables.SUPITEM_GROUP_TABLE.alias() services = ( DBSession.query(model_class) .distinct() .outerjoin((servicegroup, servicegroup.c.idsupitem == model_class.idservice)) ) # ACLs if not tg.config.is_manager.is_met(tg.request.environ): user_groups = [ug[0] for ug in user.supitemgroups() if ug[1]] services = services.filter(servicegroup.c.idgroup.in_(user_groups)) return services.all()
def get_all_hosts(): """ Retourne tous les hôtes (C{tables.Host}) auxquels l'utilisateur à accès """ user = get_current_user() # user = tables.User.by_user_name(u"editor") # debug if not user: raise HTTPForbidden("You must be logged in") hostgroup = tables.secondary_tables.SUPITEM_GROUP_TABLE.alias() servicegroup = tables.secondary_tables.SUPITEM_GROUP_TABLE.alias() hosts = ( DBSession.query(tables.Host) .distinct() .outerjoin( (hostgroup, hostgroup.c.idsupitem == tables.Host.idhost), (tables.LowLevelService, tables.LowLevelService.idhost == tables.Host.idhost), (servicegroup, servicegroup.c.idsupitem == tables.LowLevelService.idservice), ) ) # ACLs if not tg.config.is_manager.is_met(tg.request.environ): user_groups = [ug[0] for ug in user.supitemgroups() if ug[1]] hosts = hosts.filter(or_(hostgroup.c.idgroup.in_(user_groups), servicegroup.c.idgroup.in_(user_groups))) return hosts.all()
def graphtree(self, host_id=None, parent_id=None, offset=0, noCache=None): """ Affiche un étage de l'arbre de sélection des graphes et groupes de graphes. @param parent_id: identifiant du groupe de graphes parent @type parent_id: C{int} or None """ # Si l'identifiant de l'hôte n'est pas spécifié, on # retourne un dictionnaire contenant deux listes vides if host_id is None: return dict(groups = [], graphs=[]) # On vérifie les permissions sur l'hôte # TODO: Utiliser un schéma de validation host_id = int(host_id) host = DBSession.query(Host ).filter(Host.idhost == host_id ).first() if host is None: return dict(groups = [], graphs=[]) user = get_current_user() if not host.is_allowed_for(user): return dict(groups = [], graphs=[]) # On récupère la liste des groupes de graphes associés à l'hôte host_graph_groups = DBSession.query( GraphGroup ).distinct( ).join( (GRAPH_GROUP_TABLE, \ GRAPH_GROUP_TABLE.c.idgroup == GraphGroup.idgroup), (Graph, Graph.idgraph == GRAPH_GROUP_TABLE.c.idgraph), (GRAPH_PERFDATASOURCE_TABLE, \ GRAPH_PERFDATASOURCE_TABLE.c.idgraph == Graph.idgraph), (PerfDataSource, PerfDataSource.idperfdatasource == \ GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource), (SUPITEM_GROUP_TABLE, \ SUPITEM_GROUP_TABLE.c.idsupitem == PerfDataSource.idhost), ).filter(PerfDataSource.idhost == host_id ).order_by(GraphGroup.name.asc() ).all() # Si l'identifiant du groupe parent n'est pas spécifié, # on récupère la liste des groupes de graphes racines. if parent_id is None: graph_groups = GraphGroup.get_top_groups() # Sinon on récupère la liste des graphes dont le # groupe passé en paramètre est le parent direct else: # TODO: Utiliser un schéma de validation parent_id = int(parent_id) graph_groups = DBSession.query( GraphGroup ).join( (GroupHierarchy, GroupHierarchy.idchild == \ GraphGroup.idgroup), ).filter(GroupHierarchy.hops == 1 ).filter(GroupHierarchy.idparent == parent_id ).order_by(GraphGroup.name.asc() ).all() # On réalise l'intersection des deux listes groups = [] for gg in graph_groups: if gg in host_graph_groups: groups.append({ 'id' : gg.idgroup, 'name' : gg.name, 'type' : "group", }) # On récupère la liste des graphes appartenant au # groupe dont l'identifiant est passé en paramètre graphs = [] if parent_id: db_graphs = DBSession.query( Graph.idgraph, Graph.name, ).distinct( ).join( (GRAPH_GROUP_TABLE, GRAPH_GROUP_TABLE.c.idgraph == Graph.idgraph), (GRAPH_PERFDATASOURCE_TABLE, GRAPH_PERFDATASOURCE_TABLE.c.idgraph == Graph.idgraph), (PerfDataSource, PerfDataSource.idperfdatasource == \ GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource), ).filter(GRAPH_GROUP_TABLE.c.idgroup == parent_id ).filter(PerfDataSource.idhost == host_id ).order_by(Graph.name.asc()) for graph in db_graphs.all(): graphs.append({ 'id' : graph.idgraph, 'name' : graph.name, 'type' : "item", }) return dict(groups=groups, items=graphs)
def hosttree(self, parent_id=None, onlytype="", offset=0, noCache=None): """ Affiche un étage de l'arbre de sélection des hôtes et groupes d'hôtes. @param parent_id: identifiant du groupe d'hôte parent @type parent_id: C{int} or None """ # Si l'identifiant du groupe parent n'est pas # spécifié, on retourne la liste des groupes racines, # fournie par la méthode get_root_hosts_groups. if parent_id is None: return self.get_root_host_groups() # TODO: Utiliser un schéma de validation parent_id = int(parent_id) offset = int(offset) # On vérifie si le groupe parent fait partie des # groupes auxquel l'utilisateur a accès, et on # retourne une liste vide dans le cas contraire is_manager = config.is_manager.is_met(request.environ) if not is_manager: direct_access = False user = get_current_user() # On calcule la distance de ce groupe par rapport aux groupes # sur lesquels l'utilisateur a explicitement les permissions. # # La distance est définie ainsi : # 0 : l'utilisateur a des droits explicites sur ce groupe. # > 0 : l'utilisateur a accès implicitement au groupe. # < 0 : l'utilisateur n'a pas d'accès (il peut juste parcourir # ce groupe) # # Il faut 2 étapes pour trouver la distance. La 1ère essaye # de trouver une distance >= 0, la 2ème une distance <= 0. # Distance positive. distance = DBSession.query( functions.max(GroupHierarchy.hops) ).join( (Group, Group.idgroup == GroupHierarchy.idparent), (DataPermission, DataPermission.idgroup == Group.idgroup), (UserGroup, UserGroup.idgroup == DataPermission.idusergroup), (USER_GROUP_TABLE, USER_GROUP_TABLE.c.idgroup == \ UserGroup.idgroup), ).filter(USER_GROUP_TABLE.c.username == user.user_name ).filter(Group.grouptype == u'supitemgroup' ).filter(GroupHierarchy.idchild == parent_id ).scalar() if distance is None: # Distance négative. distance = DBSession.query( functions.max(GroupHierarchy.hops) ).join( (Group, Group.idgroup == GroupHierarchy.idchild), (DataPermission, DataPermission.idgroup == Group.idgroup), (UserGroup, UserGroup.idgroup == DataPermission.idusergroup), (USER_GROUP_TABLE, USER_GROUP_TABLE.c.idgroup == \ UserGroup.idgroup), ).filter(USER_GROUP_TABLE.c.username == user.user_name ).filter(Group.grouptype == u'supitemgroup' ).filter(GroupHierarchy.idparent == parent_id ).scalar() if distance is not None: distance = -distance if distance is None: # Pas d'accès à ce groupe. return dict(groups = [], items = []) direct_access = distance >= 0 limit = int(config.get("max_menu_entries", 20)) result = {"groups": [], "items": []} if not onlytype or onlytype == "group": # On récupère la liste des groupes dont # l'identifiant du parent est passé en paramètre gh1 = aliased(GroupHierarchy, name='gh1') gh2 = aliased(GroupHierarchy, name='gh2') db_groups = DBSession.query( SupItemGroup ).options(lazyload('_path_obj') ).distinct( ).join( (gh1, gh1.idchild == SupItemGroup.idgroup), ).filter(gh1.hops == 1 ).filter(gh1.idparent == parent_id ).order_by(SupItemGroup.name.asc()) if not is_manager and not direct_access: # On ne doit afficher que les fils du groupe <parent_id> # tels que l'utilisateur a accès explicitement à l'un # des fils de l'un de ces groupes. db_groups = db_groups.join( (gh2, gh2.idparent == gh1.idchild), (DataPermission, DataPermission.idgroup == gh2.idchild), (UserGroup, UserGroup.idgroup == DataPermission.idusergroup), (USER_GROUP_TABLE, USER_GROUP_TABLE.c.idgroup == UserGroup.idgroup), ).filter(USER_GROUP_TABLE.c.username == user.user_name) num_children_left = db_groups.count() - offset if offset: result["continued_from"] = offset result["continued_type"] = "group" all_groups = db_groups.limit(limit).offset(offset).all() for group in all_groups: result["groups"].append({ 'id' : group.idgroup, 'name' : group.name, 'type' : "group", }) if num_children_left > limit: result["groups"].append({ 'name': _("Next %(limit)s") % {"limit": limit}, 'offset': offset + limit, 'parent_id': parent_id, 'type': 'continued', 'for_type': 'group', }) # On récupère la liste des hôtes appartenant au # groupe dont l'identifiant est passé en paramètre if ((not onlytype or onlytype == "item") and (is_manager or direct_access)): db_hosts = DBSession.query( Host.idhost, Host.name, ).join( (SUPITEM_GROUP_TABLE, SUPITEM_GROUP_TABLE.c.idsupitem == Host.idhost ), ).filter(SUPITEM_GROUP_TABLE.c.idgroup == parent_id ).order_by(Host.name.asc()) num_children_left = db_hosts.count() - offset if offset: result["continued_from"] = offset result["continued_type"] = "item" all_hosts = db_hosts.limit(limit).offset(offset).all() for host in all_hosts: result["items"].append({ 'id' : host.idhost, 'name' : host.name, 'type' : "item", }) if num_children_left > limit: result["items"].append({ 'name': _("Next %(limit)s") % {"limit": limit}, 'offset': offset + limit, 'parent_id': parent_id, 'type': 'continued', 'for_type': 'item', }) return result
def fullHostPage(self, host, start=None, duration=86400): """ Affichage de l'ensemble des graphes associes a un hote * d apres les donnees RRD * avec une date-heure de debut * pour une plage de temps @param host : hôte @type host : C{str} @param start : date-heure de debut des donnees @type start : C{str} @param duration : plage de temps des données. Parametre optionnel, initialisé a 86400 = plage de 1 jour. @type duration : C{str} @return: page avec les images des graphes et boutons de deplacement dans le temps @rtype: page html """ if start is None: start = int(time.time()) - int(duration) else: start = int(start) duration = int(duration) user = get_current_user() if user is None: return dict(host=host, start=start, duration=duration, presets=self.presets, graphs=[]) # Vérification des permissions de l'utilisateur sur l'hôte. if not config.is_manager.is_met(request.environ): # Récupération des groupes auxquels l'utilisateur a accès. supitemgroups = [sig[0] for sig in user.supitemgroups() if sig[1]] # On vérifie que l'hôte en question existe bel et bien. host_obj = Host.by_host_name(host) if not host_obj: message = _('No such host "%s"') % host LOGGER.warning(message) raise http_exc.HTTPNotFound(message) # Récupération des groupes dont l'hôte fait partie hostgroups = [g.idgroup for g in host_obj.groups] # Si aucun des groupes de l'hôte ne fait partie des groupes # auxquels l'utilisateur a accès, on affiche une erreur 403. if len(set(hostgroups).intersection(set(supitemgroups))) < 1: message = _('Access denied to host "%s"') % host LOGGER.warning(message) raise http_exc.HTTPForbidden(message) # Récupération de la liste des noms des graphes associés à l'hôte. graphs = DBSession.query( Graph.name ).distinct( ).join( (GRAPH_PERFDATASOURCE_TABLE, GRAPH_PERFDATASOURCE_TABLE.c.idgraph == Graph.idgraph), (PerfDataSource, PerfDataSource.idperfdatasource == GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource), (Host, Host.idhost == PerfDataSource.idhost), ).filter(Host.name == host) graphs = graphs.all() return dict(host=host, start=start, duration=duration, presets=self.presets, graphs=graphs)
def searchHostAndGraph(self, search_form_host, search_form_graph): """ Determination des couples (hote-graphe) repondant aux criteres de recherche sur hote et/ou graphe. Un critere peut correspondre a un intitule complet hote ou graphe ou a un extrait. @return: couples hote-graphe @rtype: document json (sous forme de dict) """ limit = 100 user = get_current_user() ids = [] labels = [] if user is None: return dict(items=[]) # On a un nom d'indicateur, mais pas de nom d'hôte, # on considère que l'utilisateur veut tous les indicateurs # correspondant au motif, quel que soit l'hôte. if search_form_graph: if not search_form_host: search_form_host = u'*' search_form_host = sql_escape_like(search_form_host) search_form_graph = sql_escape_like(search_form_graph) items = DBSession.query( Host.idhost.label('idhost'), Host.name.label('hostname'), Graph.idgraph.label('idgraph'), Graph.name.label('graphname'), ).distinct().join( (PerfDataSource, PerfDataSource.idhost == Host.idhost), (GRAPH_PERFDATASOURCE_TABLE, \ GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource == \ PerfDataSource.idperfdatasource), (Graph, Graph.idgraph == \ GRAPH_PERFDATASOURCE_TABLE.c.idgraph), (SUPITEM_GROUP_TABLE, SUPITEM_GROUP_TABLE.c.idsupitem == \ Host.idhost), ).filter(Host.name.ilike(search_form_host) ).filter(Graph.name.ilike(search_form_graph) ).order_by( Host.name.asc(), Graph.name.asc(), ) # On a ni hôte, ni indicateur. On renvoie une liste vide. # Si l'utilisateur voulait vraiment quelque chose, # il n'avait qu'à le demander. elif not search_form_host: return [] # Sinon, on a juste un motif pour un hôte. # On renvoie la liste des hôtes correspondant. else: search_form_host = sql_escape_like(search_form_host) items = DBSession.query( Host.idhost.label('idhost'), Host.name.label('hostname'), ).distinct().join( (SUPITEM_GROUP_TABLE, SUPITEM_GROUP_TABLE.c.idsupitem == \ Host.idhost), ).filter(Host.name.ilike(search_form_host) ).order_by(Host.name.asc()) # Les managers ont accès à tout. # Les autres ont un accès restreint. if not config.is_manager.is_met(request.environ): supitemgroups = [sig[0] for sig in user.supitemgroups() if sig[1]] # pylint: disable-msg=E1103 items = items.join( (GroupHierarchy, GroupHierarchy.idchild == \ SUPITEM_GROUP_TABLE.c.idgroup) ).filter(GroupHierarchy.idparent.in_(supitemgroups)) items = items.limit(limit + 1).all() # pylint: disable-msg=E1103 more_results = len(items) > limit if not search_form_graph: for i in xrange(min(limit, len(items))): ids.append((items[i].idhost, None)) labels.append((items[i].hostname, None)) else: for i in xrange(min(limit, len(items))): ids.append((items[i].idhost, items[i].idgraph)) labels.append((items[i].hostname, items[i].graphname)) return dict(labels=labels, ids=ids, more=more_results)
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, )
def get_groups(self, parent_id=None, onlytype="", offset=0, noCache=None): """ Affiche un étage de l'arbre de sélection des hôtes et groupes d'hôtes. @param parent_id: identifiant du groupe d'hôte parent @type parent_id: C{int} or None """ # Si l'identifiant du groupe parent n'est pas # spécifié, on retourne la liste des groupes # racines, fournie par la méthode get_root_groups. if parent_id is None: return self.get_root_groups() # TODO: Utiliser un schéma de validation parent_id = int(parent_id) offset = int(offset) # On récupère la liste des groupes de supitems dont # l'identifiant du parent est passé en paramètre. supitem_groups = DBSession.query( SupItemGroup.idgroup, SupItemGroup.name, ).join( (GroupHierarchy, GroupHierarchy.idchild == SupItemGroup.idgroup), ).filter(GroupHierarchy.idparent == parent_id ).filter(GroupHierarchy.hops == 1 ).order_by(SupItemGroup.name) # Si l'utilisateur n'appartient pas au groupe 'managers', # on filtre les résultats en fonction de ses permissions. if not config.is_manager.is_met(request.environ): user = get_current_user() GroupHierarchy_aliased = aliased(GroupHierarchy, name='GroupHierarchy_aliased') supitem_groups = supitem_groups.join( (GroupHierarchy_aliased, or_( GroupHierarchy_aliased.idchild == SupItemGroup.idgroup, GroupHierarchy_aliased.idparent == SupItemGroup.idgroup )), (DataPermission, or_( DataPermission.idgroup == \ GroupHierarchy_aliased.idparent, DataPermission.idgroup == \ GroupHierarchy_aliased.idchild, )), (USER_GROUP_TABLE, USER_GROUP_TABLE.c.idgroup == \ DataPermission.idusergroup), ).filter(USER_GROUP_TABLE.c.username == user.user_name) limit = int(config.get("max_menu_entries", 20)) result = {"groups": [], "items": []} num_children_left = supitem_groups.distinct().count() - offset if offset: result["continued_from"] = offset result["continued_type"] = "group" all_grs = supitem_groups.distinct().limit(limit).offset(offset).all() for group in all_grs: result["groups"].append({ 'id' : group.idgroup, 'name' : group.name, 'type' : "group", }) if num_children_left > limit: result["groups"].append({ 'name': _("Next %(limit)s") % {"limit": limit}, 'offset': offset + limit, 'parent_id': parent_id, 'type': 'continued', 'for_type': 'group', }) return result
# On s'assure que toutes les règles ont bien été trouvées dans la # base, faute de quoi on lève une erreur et on arrête le traitement if len(silences) != len(id): missing_ids = [ i for i in id if i not in [s.idsilence for s in silences]] if len(missing_ids) > 1: msg = _('Error: the following silence rules do not exist:' \ ' %s.') % ", ".join('#' + str(i) for i in missing_ids) else: msg = _('Error: silence rule #%s does not exist.' ) % ", ".join(str(i) for i in missing_ids) self.handle_error_message(msg) # On s'assure que l'utilisateur dispose bien des permissions nécessaires # pour supprimer chacune des règles user = get_current_user() for s in silences: if not s.supitem.is_allowed_for(user): msg = _("Silence rule #%s does not exist.") % s.idsilence self.handle_error_message(msg) # On supprime les règles dans la BDD. try: for silence in silences: DBSession.delete(silence) DBSession.flush() except InvalidRequestError, e: msg = _('An exception has been raised while ' \ 'deleting the silence rules: %s') % str(e) self.handle_error_message(msg)
def update(self, id, last_modification, trouble_ticket, ack): """ Mise à jour d'un événement suivant les arguments passés. Cela peut être un changement de ticket ou un changement de statut. @param id: Le ou les identifiants des événements à traiter @param last_modification: La date de la dernière modification dont l'utilisateur est au courant. @param trouble_ticket: Nouveau numéro du ticket associé. @param ack: Nouvel état d'acquittement des événements sélectionnés. Cette méthode permet de satisfaire les exigences suivantes : - VIGILO_EXIG_VIGILO_BAC_0020, - VIGILO_EXIG_VIGILO_BAC_0060, - VIGILO_EXIG_VIGILO_BAC_0110. """ # On vérifie que des identifiants ont bien été transmis via # le formulaire, et on informe l'utilisateur le cas échéant. if id is None: flash(_('No event has been selected'), 'warning') raise redirect(request.environ.get('HTTP_REFERER', '/')) # On récupère la liste de tous les identifiants des événements # à mettre à jour. ids = [ int(i) for i in id.strip(',').split(',') ] user = get_current_user() events = VigiboardRequest(user) events.add_table( CorrEvent, Event, events.items.c.hostname, events.items.c.servicename, ) events.add_join((Event, CorrEvent.idcause == Event.idevent)) events.add_join((events.items, Event.idsupitem == events.items.c.idsupitem)) events.add_filter(CorrEvent.idcorrevent.in_(ids)) events.generate_request() idevents = [event[0].idcause for event in events.req] # Si des changements sont survenus depuis que la # page est affichée, on en informe l'utilisateur. last_modification = datetime.fromtimestamp(last_modification) cur_last_modification = get_last_modification_timestamp(idevents, None) if cur_last_modification and last_modification < cur_last_modification: flash(_('Changes have occurred since the page was last displayed, ' 'your changes HAVE NOT been saved.'), 'warning') raise redirect(request.environ.get('HTTP_REFERER', '/')) # Vérification que au moins un des identifiants existe et est éditable if not events.num_rows(): flash(_('No access to this event'), 'error') redirect('/') if ack == u'Forced': condition = Any( config.is_manager, has_permission('vigiboard-admin'), msg=l_("You don't have administrative access " "to VigiBoard")) try: condition.check_authorization(request.environ) except NotAuthorizedError, e: reason = unicode(e) flash(reason, 'error') raise redirect(request.environ.get('HTTP_REFERER', '/'))
def item(self, page, host, service, sort=None, order=None): """ Affichage de l'historique de l'ensemble des événements corrélés jamais ouverts sur l'hôte / service demandé. Pour accéder à cette page, l'utilisateur doit être authentifié. @param page: Numéro de la page à afficher. @type: C{int} @param host: Nom de l'hôte souhaité. @type: C{str} @param service: Nom du service souhaité @type: C{str} @param sort: Colonne de tri @type: C{str} or C{None} @param order: Ordre du tri (asc ou desc) @type: C{str} or C{None} Cette méthode permet de satisfaire l'exigence VIGILO_EXIG_VIGILO_BAC_0080. """ # Auto-supervision self.get_failures() idsupitem = SupItem.get_supitem(host, service) if not idsupitem: flash(_('No such host/service'), 'error') redirect('/') user = get_current_user() aggregates = VigiboardRequest(user, False, sort=sort, order=order) aggregates.add_table( CorrEvent, aggregates.items.c.hostname, aggregates.items.c.servicename, ) aggregates.add_join((Event, CorrEvent.idcause == Event.idevent)) aggregates.add_join((aggregates.items, Event.idsupitem == aggregates.items.c.idsupitem)) aggregates.add_filter(aggregates.items.c.idsupitem == idsupitem) # Pagination des résultats aggregates.generate_request() items_per_page = int(session.get('items_per_page', config['vigiboard_items_per_page'])) page = paginate.Page(aggregates.req, page=page, items_per_page=items_per_page) # Vérification qu'il y a au moins 1 événement qui correspond if not page.item_count: flash(_('No access to this host/service or no event yet'), 'error') redirect('/') # Ajout des formulaires et préparation # des données pour ces formulaires. ids_events = [event[0].idcause for event in page.items] tmpl_context.last_modification = \ mktime(get_last_modification_timestamp(ids_events).timetuple()) tmpl_context.edit_event_form = EditEventForm("edit_event_form", submit_text=_('Apply'), action=url('/update')) plugins_data = {} for plugin in dict(config['columns_plugins']): plugins_data[plugin] = {} return dict( hostname = host, servicename = service, plugins_data = plugins_data, page = page, sort = sort, order = order, event_edit_status_options = edit_event_status_options, search_form = create_search_form, search = {}, fixed_search = {}, )
def masked_events(self, idcorrevent, page): """ Affichage de la liste des événements bruts masqués d'un événement corrélé (événements agrégés dans l'événement corrélé). @param page: numéro de la page à afficher. @type page: C{int} @param idcorrevent: identifiant de l'événement corrélé souhaité. @type idcorrevent: C{int} """ # Auto-supervision self.get_failures() user = get_current_user() # Récupère la liste des événements masqués de l'événement # corrélé donné par idcorrevent. events = VigiboardRequest(user, False) events.add_table( Event, events.items.c.hostname, events.items.c.servicename, ) events.add_join((EVENTSAGGREGATE_TABLE, \ EVENTSAGGREGATE_TABLE.c.idevent == Event.idevent)) events.add_join((CorrEvent, CorrEvent.idcorrevent == \ EVENTSAGGREGATE_TABLE.c.idcorrevent)) events.add_join((events.items, Event.idsupitem == events.items.c.idsupitem)) events.add_filter(Event.idevent != CorrEvent.idcause) events.add_filter(CorrEvent.idcorrevent == idcorrevent) # Récupère l'instance de SupItem associé à la cause de # l'événement corrélé. Cette instance est utilisé pour # obtenir le nom d'hôte/service auquel la cause est # rattachée (afin de fournir un contexte à l'utilisateur). hostname = None servicename = None cause_supitem = DBSession.query( SupItem, ).join( (Event, Event.idsupitem == SupItem.idsupitem), (CorrEvent, Event.idevent == CorrEvent.idcause), ).filter(CorrEvent.idcorrevent == idcorrevent ).one() if isinstance(cause_supitem, LowLevelService): hostname = cause_supitem.host.name servicename = cause_supitem.servicename elif isinstance(cause_supitem, Host): hostname = cause_supitem.name # Pagination des résultats events.generate_request() items_per_page = int(session.get('items_per_page', config['vigiboard_items_per_page'])) page = paginate.Page(events.req, page=page, items_per_page=items_per_page) # Vérification que l'événement existe if not page.item_count: flash(_('No masked event or access denied'), 'error') redirect('/') return dict( idcorrevent = idcorrevent, hostname = hostname, servicename = servicename, plugins_data = {}, page = page, search_form = create_search_form, search = {}, fixed_search = {}, )
def index(self, page, sort=None, order=None, **search): """ Page d'accueil de Vigiboard. Elle affiche, suivant la page demandée (page 1 par defaut), la liste des événements, rangés par ordre de prise en compte, puis de sévérité. Pour accéder à cette page, l'utilisateur doit être authentifié. @param page: Numéro de la page souhaitée, commence à 1 @type page: C{int} @param sort: Colonne de tri @type sort: C{str} or C{None} @param order: Ordre du tri (asc ou desc) @type order: C{str} or C{None} @param search: Dictionnaire contenant les critères de recherche. @type search: C{dict} Cette méthode permet de satisfaire les exigences suivantes : - VIGILO_EXIG_VIGILO_BAC_0040, - VIGILO_EXIG_VIGILO_BAC_0070, - VIGILO_EXIG_VIGILO_BAC_0100, """ # Auto-supervision self.get_failures() user = get_current_user() aggregates = VigiboardRequest(user, search=search, sort=sort, order=order) aggregates.add_table( CorrEvent, aggregates.items.c.hostname, aggregates.items.c.servicename ) aggregates.add_join((Event, CorrEvent.idcause == Event.idevent)) aggregates.add_contains_eager(CorrEvent.cause) aggregates.add_group_by(Event) aggregates.add_join((aggregates.items, Event.idsupitem == aggregates.items.c.idsupitem)) aggregates.add_order_by(asc(aggregates.items.c.hostname)) # Certains arguments sont réservés dans routes.util.url_for(). # On effectue les substitutions adéquates. # Par exemple: "host" devient "host_". reserved = ('host', 'anchor', 'protocol', 'qualified') for column in search.copy(): if column in reserved: search[column + '_'] = search[column] del search[column] # On ne garde que les champs effectivement renseignés. for column in search.copy(): if not search[column]: del search[column] # On sérialise les champs de type dict. def serialize_dict(dct, key): if isinstance(dct[key], dict): for subkey in dct[key]: serialize_dict(dct[key], subkey) dct['%s.%s' % (key, subkey)] = dct[key][subkey] del dct[key] elif isinstance(dct[key], datetime): dct[key] = dct[key].strftime(dateformat.get_date_format()) fixed_search = search.copy() for column in fixed_search.copy(): serialize_dict(fixed_search, column) # Pagination des résultats aggregates.generate_request() items_per_page = int(session.get('items_per_page', config['vigiboard_items_per_page'])) page = paginate.Page(aggregates.req, page=page, items_per_page=items_per_page) # Récupération des données des plugins plugins_data = {} plugins = dict(config['columns_plugins']) ids_events = [event[0].idcause for event in page.items] ids_correvents = [event[0].idcorrevent for event in page.items] for plugin in plugins: plugin_data = plugins[plugin].get_bulk_data(ids_correvents) if plugin_data: plugins_data[plugin] = plugin_data else: plugins_data[plugin] = {} # Ajout des formulaires et préparation # des données pour ces formulaires. tmpl_context.last_modification = \ mktime(get_last_modification_timestamp(ids_events).timetuple()) tmpl_context.edit_event_form = EditEventForm("edit_event_form", submit_text=_('Apply'), action=url('/update')) if request.response_type == 'text/csv': # Sans les 2 en-têtes suivants qui désactivent la mise en cache, # Internet Explorer refuse de télécharger le fichier CSV (cf. #961). response.headers['Pragma'] = 'public' # Nécessaire pour IE. response.headers['Cache-Control'] = 'max-age=0' # Nécessaire pour IE. response.headers["Content-Type"] = "text/csv" response.headers['Content-Disposition'] = \ 'attachment;filename="alerts.csv"' return export_csv.export(page, plugins_data) return dict( hostname = None, servicename = None, plugins_data = plugins_data, page = page, sort = sort, order = order, event_edit_status_options = edit_event_status_options, search_form = create_search_form, search = search, fixed_search = fixed_search, )