def cb(_result): self.assertEqual(DBSession.query(tables.Event).count(), 0, "L'événement ne doit pas avoir été inséré") self.assertEqual(DBSession.query(tables.EventHistory).count(), 0, "L'événement ne doit pas avoir d'historique") self.assertEqual(self.rd._do_correl.call_count, 0, "La correlation ne doit pas avoir été lancée")
def by_host_and_source_name(cls, host, sourcename): """ Renvoie une source de données concernant un service donné en fonction de son nom. @param cls: Classe à utiliser pour la récupération de la source. @type cls: C{type} @param host: Instance de L{Host} ou identifiant de l'hôte sur lequel porte la source de données. @type host: C{int} ou L{Host} @param sourcename: Nom de la source de données à récupérer. @type sourcename: C{unicode} @return: La source de données de performances dont le nom est C{sourcename} et qui porte sur le service C{service}. @rtype: L{PerfDataSource} """ if isinstance(host, (int, long)): return DBSession.query(cls ).filter(cls.idhost == host ).filter(cls.name == sourcename ).first() return DBSession.query(cls ).filter(cls.idhost == host.idhost ).filter(cls.name == sourcename ).first()
def test_purge_zero_days(self): """Purge des événements sans limite d'âge.""" # On veut fermer les événements corrélés qui sont dans l'état OK, # quelque soit la date à laquelle ils ont été créés. options = Options(days=0, size=None) clean_vigiboard(LOGGER, options, None) # Les 2 entrées d'historique pour un HLS # doivent avoir été supprimées. self.assertEquals(0, DBSession.query(tables.HLSHistory).count()) # On s'assure que le CorrEvent et l'événement sur localhost2 # âgés de 2j ont bien été supprimés. supitem = tables.Host.by_host_name(u'localhost2') event = DBSession.query(tables.Event).filter( tables.Event.idsupitem == supitem.idsupitem).first() self.assertEquals(None, event) # sans Event, pas de CorrEvent possible. # Les autres doivent toujours être dans l'état "fermé". others = DBSession.query(tables.CorrEvent).all() self.assertNotEquals(0, len(others)) for other in others: # Contourne le problème du support incomplet des contraintes # référentielles de type ON DELETE CASCADE dans SQLite. if other.cause is None: continue self.assertEquals( other.ack, tables.CorrEvent.ACK_NONE, "L'événement corrélé sur %s devrait être 'nouveau'" % other.cause.supitem )
def impacted_hls(self, *args): """ Renvoie une requête portant sur les services de haut niveau impactés. @param args: Liste d'éléments à récupérer dans la requête. @type args: Une C{DeclarativeBase} ou une liste de C{Column}s. @return: Une C{Query} portant sur les éléments demandés. @rtype: C{sqlalchemy.orm.query.Query} """ from vigilo.models.tables import HighLevelService, \ ImpactedHLS, ImpactedPath if not args: args = [HighLevelService] imp_hls1 = aliased(ImpactedHLS) imp_hls2 = aliased(ImpactedHLS) subquery = DBSession.query( functions.max(imp_hls1.distance).label('distance'), imp_hls1.idpath ).join( (ImpactedPath, ImpactedPath.idpath == imp_hls1.idpath) ).filter(ImpactedPath.idsupitem == self.idsupitem ).group_by(imp_hls1.idpath).subquery() services_query = DBSession.query(*args).distinct( ).join( (imp_hls2, HighLevelService.idservice == imp_hls2.idhls), (subquery, subquery.c.idpath == imp_hls2.idpath), ).filter(imp_hls2.distance == subquery.c.distance) return services_query
def test_migration(self): """Teste la migration (partielle/totale) du modèle.""" # Recherche des scripts de migration dans le dossier des tests. module = u'vigilo.models.test.testdata' scripts = get_migration_scripts(module) expected_scripts = { 1: '001_Initial_version', 2: '002_Dummy', 3: '003_Dummy', } self.assertEquals(scripts, expected_scripts) # On simule l'installation d'un nouveau modèle. DBSession.add(tables.Version( name=module, version=1, )) DBSession.flush() # On vérifie qu'une migration jusqu'à un point fixe fonctionne. migrate_model(DBSession.bind, module, scripts, 2) version = DBSession.query(tables.Version).filter( tables.Version.name == module).one() self.assertEquals(version.version, 2) # On annule la migration et on teste cette fois une migration # jusqu'à la dernière version disponible. version.version = 1 DBSession.flush() migrate_model(DBSession.bind, module, scripts) version = DBSession.query(tables.Version).filter( tables.Version.name == module).one() self.assertEquals(version.version, 3)
def test_select_graph_without_a_host(self): """ Résultats de la recherche sur un graphe sans préciser d'hôte """ # Récupération de l'hôte 'host1' dans la base de données host1 = DBSession.query(Host).filter( Host.name == u'host1 éà').first() # Récupération du graphe 'graph1' dans la base de données graph1 = DBSession.query(Graph).filter( Graph.name == u'graph1 éà').first() # Récupération des résultats obtenus après une recherche sur # un graphe sans préciser d'hôte par l'utilisateur 'manager'. response = self.app.post( '/rpc/searchHostAndGraph?search_form_graph=%s' % urllib2.quote(graph1.name.encode('utf-8'), ''), {}, extra_environ={'REMOTE_USER': '******'} ) json = response.json # On s'assure que la liste retournée est conforme à celle attendue self.assertEqual( json, { 'labels': [[host1.name, graph1.name]], 'ids': [[host1.idhost, graph1.idgraph]], 'more': False, } )
def test_close_limited_up(self): """Fermeture événements état UP avec limite de durée.""" # On veut fermer les événements corrélés qui sont dans l'état UP, # ayant au moins 1j d'âge. options = Options(state_up=True, state_ok=False, days=1) res = close_green(LOGGER, options) self.assertTrue(res) # pas d'erreur. # On s'assure que le CorrEvent associé à l'état UP # âgé de 2j a bien été clos. supitem = tables.Host.by_host_name(u'localhost2') event = DBSession.query(tables.Event).filter( tables.Event.idsupitem == supitem.idsupitem).one() correvent = DBSession.query(tables.CorrEvent).filter( tables.CorrEvent.idcause == event.idevent).one() self.assertEquals(correvent.ack, tables.CorrEvent.ACK_CLOSED) # Les autres doivent toujours être dans l'état "nouveau". others = DBSession.query(tables.CorrEvent).filter( tables.CorrEvent.idcorrevent != correvent.idcorrevent).all() self.assertNotEquals(0, len(others)) for other in others: self.assertEquals(other.ack, tables.CorrEvent.ACK_NONE, "L'événement corrélé sur %s devrait être 'nouveau'" % other.cause.supitem )
def test_add_multiple_batch(self): """Ajout permission sur plusieurs groupes en mode batch.""" for (incode, outcode) in commands._permissions.iteritems(): print "Test permission %s" % incode options = NamespaceStub( permission=incode, object_type=self._type, usergroup=self._usergroup.group_name.encode('utf-8'), object_group=self._group1.name.encode('utf-8'), batch=True, update=False, commit=False, # la base de test est en mémoire, # en la committant, on perdrait tout. ) res = commands.cmd_add(options) self.assertEquals(res, 0) # 2 permissions doivent avoir été ajoutées. dataperms = DBSession.query(tables.DataPermission).all() self.assertEquals(2, len(dataperms)) idgroups = [self._group1.idgroup, self._group2.idgroup] for dataperm in dataperms: self.assertTrue(dataperm.idgroup in idgroups) idgroups.remove(dataperm.idgroup) self.assertEquals(dataperm.idusergroup, self._usergroup.idgroup) self.assertEquals(dataperm.access, outcode) # Suppression des permissions pour le test # du type de permission suivant. for dataperm in dataperms: DBSession.delete(dataperm) DBSession.flush() dataperm = DBSession.query(tables.DataPermission).first() self.assertEquals(dataperm, None)
def test_get_graph_groups_when_not_allowed(self): """ Récupération des groupes de graphes sans les bons droits """ # Récupération de l'hôte 'host1' dans la base de données host1 = DBSession.query(Host).filter( Host.name == u'host1 éà').first() # Récupération de l'hôte 'host3' dans la base de données host3 = DBSession.query(Host).filter( Host.name == u'host3 éà').first() # Récupération des groupes de graphes de l'hôte # host1 accessibles à l'utilisateur 'user' response = self.app.post( '/rpc/graphtree?host_id=%s' % (host1.idhost, ), { }, extra_environ={'REMOTE_USER': '******'}) json = response.json # On s'assure que la liste de groupes # de graphes retournée est vide self.assertEqual( json, { 'graphs': [], 'groups': [] } ) # Récupération des groupes de graphes de l'hôte # host3 accessibles à l'utilisateur 'user' response = self.app.post( '/rpc/graphtree?host_id=%s' % (host3.idhost, ), { }, extra_environ={'REMOTE_USER': '******'}) json = response.json # On s'assure que la liste de groupes # de graphes retournée est vide self.assertEqual( json, { 'graphs': [], 'groups': [] } ) # Récupération des groupes de graphes de l'hôte # host1 accessibles à l'utilisateur 'visitor' response = self.app.post( '/rpc/graphtree?host_id=%s' % (host1.idhost, ), { }, extra_environ={'REMOTE_USER': '******'}) json = response.json # On s'assure que la liste de groupes # de graphes retournée est vide self.assertEqual( json, { 'graphs': [], 'groups': [] } )
def test_add_single(self): """Ajout de permission sur un seul groupe.""" for (incode, outcode) in commands._permissions.iteritems(): print "Test permission %s" % incode options = NamespaceStub( permission=incode, object_type=self._type, usergroup=self._usergroup.group_name.encode('utf-8'), object_group=self._group1.path.encode('utf-8'), batch=False, update=False, commit=False, # la base de test est en mémoire, # en la committant, on perdrait tout. ) res = commands.cmd_add(options) self.assertEquals(res, 0) # Une seule permission doit exister en base de données. # Elle doit porter sur le groupe 1 définis par le test # et avoir le bon type d'accès. dataperm = DBSession.query(tables.DataPermission).one() self.assertEquals(dataperm.idgroup, self._group1.idgroup) self.assertEquals(dataperm.idusergroup, self._usergroup.idgroup) self.assertEquals(dataperm.access, outcode) # Suppression de la permission pour le test # du type de permission suivant. DBSession.delete(dataperm) DBSession.flush() dataperm = DBSession.query(tables.DataPermission).first() self.assertEquals(dataperm, None)
def test_insert_old_state(self): """Abandon de l'insertion d'un état ancien""" self.make_dependencies() ts_old = 1239104006 ts_recent = 1239104042 ts_recent_dt = datetime.fromtimestamp(ts_recent) idsupitem = SupItem.get_supitem("server.example.com", "Load") # Insertion de l'état récent state = DBSession.query(State).get(idsupitem) state.timestamp = ts_recent_dt # Création d'un message d'événement portant sur un SBN. info_dictionary = { "type": "event", "timestamp": datetime.fromtimestamp(ts_old), "host": "server.example.com", "service": "Load", "state": "WARNING", "message": "WARNING: Load average is above 4 (4.5)", } info_dictionary['idsupitem'] = SupItem.get_supitem( info_dictionary['host'], info_dictionary['service'] ) # Insertion de l'ancien événement dans la BDD result = insert_state(info_dictionary) self.assertTrue(isinstance(result, OldStateReceived)) supitem = DBSession.query(SupItem).get(idsupitem) self.assertEqual(supitem.state.timestamp, ts_recent_dt)
def test_parent(self): """Affectation d'un parent à un groupe.""" # Au début, nous n'avons pas de parent. assert_equal(self.obj.has_parent(), False) # On obtient un parent. parent = self.klass(name=u"aparent", parent=None) DBSession.add(parent) self.obj.parent = parent DBSession.query(GroupHierarchy ).filter(GroupHierarchy.parent == parent ).filter(GroupHierarchy.child == self.obj ).filter(GroupHierarchy.hops == 1 ).one() assert_equal(self.obj.parent, parent) assert_equal(self.obj.has_parent(), True) # Notre parent est modifié. anotherparent = self.klass(name=u"anotherparent", parent=None) DBSession.add(anotherparent) self.obj.parent = anotherparent DBSession.query(GroupHierarchy ).filter(GroupHierarchy.parent == anotherparent ).filter(GroupHierarchy.child == self.obj ).filter(GroupHierarchy.hops == 1 ).one() assert_equal(self.obj.parent, anotherparent) assert_equal(self.obj.has_parent(), True) # Suppression du parent. self.obj.parent = None assert_equal(self.obj.parent, None) assert_equal(self.obj.has_parent(), False)
def test_rule_creation(self): """ Ajout d'une règle de mise en silence """ # 1. On essaye d'ajouter une règle de mise en silence sur 'service3' # avec l'utilisateur 'no_rights' et on s'assure qu'on reçoit bien une # erreur 403 environ = {"REMOTE_USER": "******"} url = "/silence/create_or_modify?" + urllib.urlencode( {"states": "CRITICAL", "host": "host3", "service": "service3", "comment": "commentaire accentué"} ) self.app.get(url, extra_environ=environ, status=403) # 2. On essaye d'ajouter une règle de mise en silence sur 'service3' # avec l'utilisateur 'limited_rights' et on s'assure qu'on est bien # redirigé sur un message d'erreur environ = {"REMOTE_USER": "******"} url = "/silence/create_or_modify?" + urllib.urlencode( {"states": "CRITICAL", "host": "host3", "service": "service3", "comment": "commentaire accentué"} ) response = self.app.get(url, extra_environ=environ, status=302) response = response.follow(status=200, extra_environ=environ) assert_true(len(response.lxml.xpath('//div[@id="flash"]/div[@class="error"]'))) # 3. On ajoute une règle de mise en silence sur 'service4' avec # l'utilisateur 'limited_rights' environ = {"REMOTE_USER": "******"} url = "/silence/create_or_modify?" + urllib.urlencode( {"states": "CRITICAL", "host": "host4", "service": "service4", "comment": "commentaire accentué"} ) self.app.get(url, extra_environ=environ) # On recherche dans la base toutes les règles concernant 'service4' supitem_id = SupItem.get_supitem("host4", "service4") silences = DBSession.query(Silence).filter(Silence.idsupitem == supitem_id).all() # On s'assure qu'il n'y en a qu'une, et on vérifie ses propriétés assert_equal(len(silences), 1) assert_equal([s.statename for s in silences[0].states], ["CRITICAL"]) assert_equal(silences[0].comment, u"commentaire accentué") assert_equal(silences[0].author, u"limited_rights") # 4. On ajoute une règle de mise en silence sur 'service3' avec # l'utilisateur 'manager' environ = {"REMOTE_USER": "******"} url = "/silence/create_or_modify?" + urllib.urlencode( {"states": "CRITICAL", "host": "host3", "service": "service3", "comment": "commentaire accentué"} ) self.app.get(url, extra_environ=environ) # On recherche dans la base toutes les règles concernant 'service3' supitem_id = SupItem.get_supitem("host3", "service3") silences = DBSession.query(Silence).filter(Silence.idsupitem == supitem_id).all() # On s'assure qu'il n'y en a qu'une, et on vérifie ses propriétés assert_equal(len(silences), 1) assert_equal([s.statename for s in silences[0].states], ["CRITICAL"]) assert_equal(silences[0].comment, u"commentaire accentué") assert_equal(silences[0].author, u"manager")
def supitemgroups(self, access=None): """ Renvoie la liste des identifiants des groupes d'éléments supervisés auxquels l'utilisateur a accès. @param access: La liste des types d'accès qui autoriseront l'utilisateur à voir les groupes. Si elle vaut C{None}, aucune vérification n'est faite sur le type d'accès. @param access: C{basestring} or C{list} of C{basestring} @return: Liste des identifiants des groupes d'éléments supervisés auxquels l'utilisateur a accès. @rtype: C{list} of Ctuple{} of C{int}, C{bool} """ result = {} if hasattr(access, '__iter__'): access = set([ unicode(a) for a in access ]) elif access is not None: access = set([unicode(access)]) # L'accès en écriture donne implicitement un accès en lecture. if access is not None and u'r' in access: access.add(u'w') # Groupes d'éléments supervisés auxquels # l'utilisateur a directement accès. direct = DBSession.query(SupItemGroup.idgroup).distinct( ).join( (GroupHierarchy, GroupHierarchy.idchild == SupItemGroup.idgroup), (DataPermission, DataPermission.idgroup == GroupHierarchy.idparent), (UserGroup, UserGroup.idgroup == DataPermission.idusergroup), (USER_GROUP_TABLE, USER_GROUP_TABLE.c.idgroup == UserGroup.idgroup), ).filter(USER_GROUP_TABLE.c.username == self.user_name) if access is not None: direct = direct.filter(DataPermission.access.in_(access)) direct = direct.all() direct_ids = [sig.idgroup for sig in direct] # Groupes d'éléments supervisés auxquels l'utilisateur a accès # indirectement (droit de passage, mais pas de droit de lecture). indirect = DBSession.query(SupItemGroup.idgroup).distinct( ).join( (GroupHierarchy, GroupHierarchy.idparent == \ SupItemGroup.idgroup), ).filter(GroupHierarchy.idchild.in_(direct_ids) ).filter(GroupHierarchy.hops > 0 ).all() for sig in indirect: result[sig.idgroup] = (sig.idgroup, False) for sig in direct: result[sig.idgroup] = (sig.idgroup, True) return result.values()
def test_creation_loop(self): """ Ajout des boucles dans la hiérarchie lors de la création d'un groupe. """ DBSession.query(GroupHierarchy ).filter(GroupHierarchy.idparent == self.obj.idgroup ).filter(GroupHierarchy.idchild == self.obj.idgroup ).filter(GroupHierarchy.hops == 0 ).one()
def test_update_while_data_have_changed(self): """Màj d'un évènement corrélé modifié entre temps.""" # On peuple la BDD avec 2 hôtes, 2 services de bas niveau, # et un groupe d'hôtes et de services associés à ces items. (_hosts, services) = populate_DB() # On ajoute 2 évènements corrélés causés par ces hôtes timestamp = datetime.now() correvent1_id = add_correvent_caused_by(services[0], timestamp) add_correvent_caused_by(services[1], timestamp) # Date de modification du premier évènement corrélé later_date = datetime.now() # Date du chargement de la page date = mktime(later_date.timetuple()) - 42 # On ajoute une entrée dans l'historique de l'évènement brut # causant le premier évènement corrélé, portant pour timestamp # une date postérieure à celle du chargement de la page. correvent1 = DBSession.query( CorrEvent.idcause ).filter(CorrEvent.idcorrevent == correvent1_id).one() DBSession.add(EventHistory( type_action = u'Nagios update state', idevent = correvent1.idcause, timestamp = later_date)) DBSession.flush() transaction.commit() # L'utilisateur utilisé pour se connecter à Vigiboard est 'access'. environ = {'REMOTE_USER': '******'} # On s'attend à ce que le statut de la requête soit 302, et # à ce qu'un message d'erreur avise l'utilisateur que des # changements sont intervenus depuis le chargement de la page. response = self.app.post( '/update', { "id" : str(correvent1_id), "last_modification" : date, "trouble_ticket" : "", "ack" : u'Acknowledged', }, status = 302, extra_environ = environ) response = response.follow(status=200, extra_environ = environ) assert_true(response.lxml.xpath( '//div[@id="flash"]/div[@class="warning"]')) # On s'assure que le statut de l'évènement corrélé # n'a pas été modifié dans la base de données. status = DBSession.query( CorrEvent.ack ).filter(CorrEvent.idcorrevent == correvent1_id ).scalar() assert_equal(status, CorrEvent.ACK_NONE)
def test_change_dependencies_nothing(self): grouploader = GroupLoader() grouploader.load_dir(self.datadir) before = DBSession.query(SupItemGroup).count() # On doit créer un 2ème loader pour forcer le rechargement # des instances depuis la base de données. grouploader = GroupLoader() grouploader.load_dir(self.datadir) after = DBSession.query(SupItemGroup).count() self.assertEquals(after, before)
def do_get_dependencies(self): """ On surcharge la méthode de ModelTest car elle insère déjà des noms d'états. On veut éviter toute interférence dans les tests. """ # On supprime les StateName insérés par défaut. DBSession.query(StateName).delete() DBSession.flush() return {}
def test_insert_lls_event(self): """Insertion d'un évènement brut concernant un SBN""" self.make_dependencies() # Création d'un message d'événement portant sur un SBN. info_dictionary = { "type": "event", "timestamp": datetime.fromtimestamp(1239104006), "host": "server.example.com", "service": "Load", "state": u"WARNING", "message": u"WARNING: Load average is above 4 (4.5)", } info_dictionary['idsupitem'] = SupItem.get_supitem( info_dictionary['host'], info_dictionary['service'] ) # Insertion de l'événement dans la BDD idevent = insert_event(info_dictionary) assert idevent is not None event = DBSession.query(Event).one() # Vérification des informations de l'événement dans la BDD. self.assertEquals(LowLevelService, type(event.supitem)) self.assertEquals(1239104006, time.mktime(event.timestamp.timetuple())) self.assertEquals(u'server.example.com', event.supitem.host.name) self.assertEquals(u'Load', event.supitem.servicename) self.assertEquals(u'WARNING', StateName.value_to_statename(event.current_state)) self.assertEquals(u'WARNING', StateName.value_to_statename(event.initial_state)) self.assertEquals(u'WARNING', StateName.value_to_statename(event.peak_state)) self.assertEquals(u'WARNING: Load average is above 4 (4.5)', event.message) # Insertion de l'état dans la BDD state = DBSession.query(State).get(info_dictionary['idsupitem']) # le timestamp par défaut est plus récent et insert_state refusera la # mise à jour state.timestamp = info_dictionary['timestamp'] insert_state(info_dictionary) # Vérification des informations de l'état dans la BDD. self.assertEquals(LowLevelService, type(state.supitem)) self.assertEquals(1239104006, time.mktime(state.timestamp.timetuple())) self.assertEquals('server.example.com', state.supitem.host.name) self.assertEquals('Load', state.supitem.servicename) self.assertEquals('WARNING', StateName.value_to_statename(state.state)) self.assertEquals('WARNING: Load average is above 4 (4.5)', state.message)
def test_nonexisting_predecessor(self): """Agrégation topologique : agrégat inexistant.""" ctx = self.context_factory(42) event1 = functions.add_event(self.hosts[1], 'DOWN', u'foo') event2 = functions.add_event(self.hosts[2], 'UNREACHABLE', u'foo') ctx.set('predecessors_aggregates', [1]) res = yield self.corrbuilder._aggregate_topologically( ctx, None, event2.idevent, self.hosts[2].idhost) self.assertEquals(False, res) self.assertEquals(0, DBSession.query(tables.CorrEvent).count()) self.assertEquals(2, DBSession.query(tables.Event).count())
def prevalidate_hosts(self): hosts_db = DBSession.query(tables.Host).count() if hosts_db != self._stats["nbHosts"]: self.addError("DBLoader", "hosts", _("The number of host entries in the database does not match " "the number of hosts in the configuration. " "Database: %(db)d, configuration: %(conf)d") % {"db": hosts_db, "conf": self._stats["nbHosts"]}) hosts_db = set([h.name for h in DBSession.query(tables.Host).all()]) hosts_conf = set([ unicode(h) for h in conf.hostsConf.keys() ]) LOGGER.debug("Hosts: difference between conf and DB: %s", " ".join(hosts_db ^ hosts_conf))
def test_change_dependencies_remove(self): """Gestion des changements: fichier supprimé""" grouploader = GroupLoader() grouploader.load_dir(self.datadir) df.add_supitemgroup("to_be_removed") before = DBSession.query(SupItemGroup).count() # On doit créer un 2ème loader pour forcer le rechargement # des instances depuis la base de données. grouploader = GroupLoader() grouploader.load_dir(self.datadir) grouploader.cleanup() after = DBSession.query(SupItemGroup).count() self.assertEquals(after, before - 1)
def remove_children(self): """ Supprime la relation de descendance entre ce groupe et tous ses descendants. """ children_ids = DBSession.query( GroupHierarchy.idchild ).filter(GroupHierarchy.idparent == self.idgroup ).filter(GroupHierarchy.hops > 0).all() children_ids = [c.idchild for c in children_ids] DBSession.query(Group).filter(Group.idgroup.in_(children_ids)).delete( synchronize_session='fetch') DBSession.flush()
def test_predecessor_and_no_aggregate(self): """Agrégation topologique : prédécesseur et pas d'agrégat.""" ctx = self.context_factory(42) event1 = functions.add_event(self.hosts[1], 'DOWN', u'foo') event2 = functions.add_event(self.hosts[2], 'UNREACHABLE', u'foo') aggr1 = functions.add_correvent([event1]) ctx.set('predecessors_aggregates', [aggr1.idcorrevent]) ctx.set('successors_aggregates', []) res = yield self.corrbuilder._aggregate_topologically( ctx, None, event2.idevent, self.hosts[2].idhost) self.assertEquals(True, res) self.assertEquals(1, DBSession.query(tables.CorrEvent).count()) self.assertEquals(2, DBSession.query(tables.Event).count())
def test_insert_host_event(self): """Insertion d'un évènement brut concernant un hôte""" self.make_dependencies() # Création d'un message d'événement portant sur un hôte. info_dictionary = { "type": "event", "timestamp": datetime.fromtimestamp(1239104006), "host": "server.example.com", "state": u"DOWN", "message": u"DOWN: No ping response", } info_dictionary['idsupitem'] = SupItem.get_supitem( info_dictionary['host'], None, ) # Insertion de l'événement dans la BDD idevent = insert_event(info_dictionary) assert idevent is not None event = DBSession.query(Event).one() # Vérification des informations de l'événement dans la BDD. self.assertEquals(Host, type(event.supitem)) self.assertEquals(1239104006, time.mktime(event.timestamp.timetuple())) self.assertEquals(u'server.example.com', event.supitem.name) self.assertEquals(u'DOWN', StateName.value_to_statename(event.current_state)) self.assertEquals(u'DOWN', StateName.value_to_statename(event.initial_state)) self.assertEquals(u'DOWN', StateName.value_to_statename(event.peak_state)) self.assertEquals(u'DOWN: No ping response', event.message) # Insertion de l'état dans la BDD state = DBSession.query(State).get(info_dictionary['idsupitem']) # le timestamp par défaut est plus récent et insert_state refusera la # mise à jour state.timestamp = info_dictionary['timestamp'] insert_state(info_dictionary) # Vérification des informations de l'état dans la BDD. self.assertEquals(Host, type(state.supitem)) self.assertEquals(1239104006, time.mktime(state.timestamp.timetuple())) self.assertEquals('server.example.com', state.supitem.name) self.assertEquals('DOWN', StateName.value_to_statename(state.state)) self.assertEquals('DOWN: No ping response', state.message)
def _insert_dep(self): """Insertion de l'événement corrélé de test.""" print "Insertion evenement correle" timestamp = datetime.now() supitem = DBSession.query(self.supitem_class).one() if isinstance(supitem, Host): event = functions.add_event(supitem, u'DOWN', u'', timestamp) else: # Sinon, il s'agit d'un LowLevelService. event = functions.add_event(supitem, u'CRITICAL', u'', timestamp) functions.add_correvent([event], timestamp=timestamp) DBSession.flush() transaction.commit() correvent = DBSession.query(CorrEvent.idcorrevent).one() return correvent.idcorrevent
def __set_parent(self, group): """ Positionne un groupe en tant que parent du groupe courant. Cette méthode ne peut gérer qu'un unique parent, elle ne convient donc pas pour les L{SupItemGroup}. @param group: Nouveau parent du groupe courant. @type group: L{Group} @note: Si un groupe était déjà marqué comme parent du groupe courant, alors cette association est rompue et une nouvelle hiérarchie de groupe est construite pour le nouveau parent. """ # On récupère tous nos enfants, petits-enfants, etc.. children = DBSession.query(GroupHierarchy).filter( GroupHierarchy.parent == self).all() if not children: loop = GroupHierarchy(parent=self, child=self, hops=0) DBSession.add(loop) DBSession.flush() children = [loop] # Supprime tous les liens de parenté du groupe courant # et de ses enfants (sans limite de profondeur) vers nos # parents (sans limite de profondeur). for c in children: DBSession.query(GroupHierarchy ).filter(GroupHierarchy.idchild == c.idchild ).filter(GroupHierarchy.hops > c.hops ).delete(synchronize_session='fetch') # Si un groupe doit devenir le nouveau parent. if group: # Récupère les parents, grands-parents, etc. de notre parent. parents = DBSession.query(GroupHierarchy ).filter(GroupHierarchy.child == group ).all() for p in parents: # Nos enfants [et petits ...] et nous-même héritons de # l'arborescence de nos parents [et grands ...] à une # distance augmentée de 1. for c in children: GroupHierarchy.get_or_create( idparent=p.idparent, idchild=c.idchild, hops=p.hops + c.hops + 1, ) DBSession.flush()
def get_one(self, idmap): # pylint:disable-msg=C0111,R0201 m = DBSession.query(Map).get(idmap) if m is None: raise HTTPNotFound("Can't find map %s" % idmap) check_map_access(m) baseurl = tg.url("/api/v%s/maps/%s" % (self.apiver, m.idmap)) result = {"id": m.idmap, "title": m.title, "mtime": m.mtime.isoformat(), "generated": m.generated, "background": { "color": m.background_color, "image": m.background_image, "position": m.background_position, "repeat": m.background_repeat, }, "href": baseurl, } # groups result["groups_href"] = baseurl+"/groups/" groups = [] for group in m.groups: groups.append({ "id": group.idgroup, "name": group.name, "href": tg.url("/api/v%s/mapgroups/%s" % (self.apiver, group.idgroup)), }) result["groups"] = groups # nodes result["nodes_href"] = baseurl+"/nodes/" nodes = [] for node in m.nodes: nodes.append({ "id": node.idmapnode, "href": "%s/nodes/%s" % (baseurl, node.idmapnode) }) result["nodes"] = nodes # links result["links_href"] = baseurl+"/links/" links = [] for link in DBSession.query(MapLink).filter_by( idmap=idmap).all(): links.append({ "id": link.idmaplink, "href": "%s/links/%s" % (baseurl, link.idmaplink) }) result["links"] = links return dict(map=result)
def test_change_dependencies_add(self): grouploader = GroupLoader() grouploader.load_dir(self.datadir) print DBSession.query(SupItemGroup).all() first_group = DBSession.query(SupItemGroup).first() assert first_group is not None DBSession.delete(first_group) DBSession.flush() before = DBSession.query(SupItemGroup).count() # On doit créer un 2ème loader pour forcer le rechargement # des instances depuis la base de données. grouploader = GroupLoader() grouploader.load_dir(self.datadir) after = DBSession.query(SupItemGroup).count() self.assertEquals(after, before + 1)
def test_host_mapnode(self): """Suppression des mapnodes d'un host supprimé (#57)""" # Mettre localhost sur une carte h = fct.add_host(u"localhost") testmap = fct.add_map(u"Test map") fct.add_node_host(h, "localhost", testmap) DBSession.flush() DBSession.delete(h) DBSession.flush() # On vérifie que la suppression de l'hôte a bien supprimé ses # représentations cartographiques mn_count = DBSession.query(tables.MapNode).count() self.assertEquals(mn_count, 0) mnh_count = DBSession.query(tables.MapNodeHost).count() self.assertEquals(mnh_count, 0)