Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

vigiboard / vigiboard / tests / functional / test_silence.py @ 011743be

History | View | Annotate | Download (20.5 KB)

1
# -*- coding: utf-8 -*-
2
# vim:set expandtab tabstop=4 shiftwidth=4:
3
# Copyright (C) 2006-2020 CS GROUP - France
4
# License: GNU GPL v2 <http://www.gnu.org/licenses/gpl-2.0.html>
5

    
6
"""
7
Test des vues liées aux règles de mise en silence
8
"""
9

    
10
from __future__ import absolute_import
11

    
12
from nose.tools import assert_true, assert_equal
13

    
14
import urllib
15
import transaction
16

    
17
from vigilo.models.demo import functions
18
from vigilo.models.session import DBSession
19
from vigilo.models.tables import Silence, SupItem
20

    
21
from vigiboard.tests import TestController
22
from tg import config
23

    
24
import logging
25
logging.basicConfig()
26

    
27
def populate_DB():
28
    """ Peuple la base de données en vue des tests. """
29

    
30
    # On crée quatre hôtes de test.
31
    host1 = functions.add_host(u'host1')
32
    host2 = functions.add_host(u'host2')
33
    host3 = functions.add_host(u'host3')
34
    host4 = functions.add_host(u'host4')
35
    DBSession.flush()
36

    
37
    # On ajoute un service sur chaque hôte.
38
    service1 = functions.add_lowlevelservice(
39
                        host2, u'service1')
40
    service2 = functions.add_lowlevelservice(
41
                        host1, u'service2')
42
    service3 = functions.add_lowlevelservice(
43
                        host3, u'service3')
44
    functions.add_lowlevelservice(
45
                        host4, u'service4')
46
    DBSession.flush()
47

    
48
    # On crée un groupe de supitems et on y ajoute 'host1' et 'host4' en vue des
49
    # tests portant sur les permissions
50
    group1 = functions.add_supitemgroup(u'group1')
51
    DBSession.add(group1)
52
    functions.add_host2group(u'host1', u'group1')
53
    functions.add_host2group(u'host4', u'group1')
54
    DBSession.flush()
55

    
56
    # On ajoute 2 utilisateurs.
57
    functions.add_user(u'no_rights', u'no@righ.ts',
58
                       u'no_rights', u'no_rights',
59
                       u'no_rights')
60
    functions.add_user(u'limited_rights', u'limited@righ.ts',
61
                       u'limited_rights', u'limited_rights',
62
                       u'limited_rights')
63
    functions.add_usergroup_permission(u'limited_rights', u'vigiboard-silence')
64
    functions.add_supitemgrouppermission(u'group1', u'limited_rights')
65
    DBSession.flush()
66

    
67
    # On ajoute 4 règles de mise en silence.
68
    functions.add_silence(
69
        states=[u'UNKNOWN'], host=host1, service=None, user=u'manager',
70
        comment=u'foo', date=u'2000-01-01 00:00:00')
71
    functions.add_silence(
72
        states=[u'DOWN'], host=host1, service=service2,
73
        user=u'unrestricted', comment=u'bar', date=u'2000-01-02 00:00:00')
74
    functions.add_silence(
75
        states=[u'WARNING', 'CRITICAL'], host=host2, service=service1, user=u'unrestricted',
76
        comment=u'baz', date=u'2000-01-03 00:00:00')
77
    functions.add_silence(
78
        states=[u'DOWN'], host=host3, service=None,
79
        user=u'manager', comment=u'qux', date=u'2000-01-04 00:00:00')
80
    DBSession.flush()
81

    
82
    transaction.commit()
83

    
84
class TestSilence(TestController):
85
    """
86
    Test de l'inhibition des alarmes dans VigiBoard.
87
    """
88
    def setUp(self):
89
        super(TestSilence, self).setUp()
90
        populate_DB()
91

    
92
    def test_default_order(self):
93
        """ Tri par défaut des règles de mise en silence """
94

    
95
        # 1. On essaye d'afficher la table des règles de mise en silence pour
96
        # l'utilisateur 'no_rights' et on s'assure qu'on reçoit bien une erreur
97
        # 403
98
        environ = {'REMOTE_USER': 'no_rights'}
99
        response = self.app.get('/silence', extra_environ=environ, status=403)
100

    
101
        # 2. On affiche la table des règles de mise en silence avec l'utilisateur
102
        # 'limited_rights'
103
        environ = {'REMOTE_USER': 'limited_rights'}
104
        response = self.app.get('/silence', extra_environ=environ)
105

    
106
        # Il doit y avoir 2 lignes de résultats
107
        # - la 1ère concerne 'service2' sur 'host1' ;
108
        # - la 2ème concerne 'host1' ;
109
        hostnames = response.lxml.xpath(
110
            '//table/tbody/tr/' \
111
            'td[@class="hostname"]/text()')
112
        assert_equal(hostnames, ['host1', 'host1'])
113
        servicenames = response.lxml.xpath(
114
            '//table/tbody/tr/' \
115
            'td[@class="servicename"]/text()')
116
        assert_equal(servicenames, ['service2'])
117

    
118
        # 3. On affiche la table des règles de mise en silence avec l'utilisateur
119
        # 'manager'
120
        environ = {'REMOTE_USER': 'manager'}
121
        response = self.app.get('/silence', extra_environ=environ)
122

    
123
        # Il doit y avoir 4 lignes de résultats
124
        # - la 1ère concerne 'host3'.
125
        # - la 2ème concerne 'service1' sur 'host2' ;
126
        # - la 3ème concerne 'service2' sur 'host1' ;
127
        # - la 4ème concerne 'host1' ;
128
        hostnames = response.lxml.xpath(
129
            '//table/tbody/tr/' \
130
            'td[@class="hostname"]/text()')
131
        assert_equal(hostnames, ['host3', 'host2', 'host1', 'host1'])
132
        servicenames = response.lxml.xpath(
133
            '//table/tbody/tr/' \
134
            'td[@class="servicename"]/text()')
135
        assert_equal(servicenames, ['service1', 'service2'])
136

    
137
    def test_ascending_order(self):
138
        """ Tri des règles de mise en silence dans l'ordre croissant """
139

    
140
        # 1. On essaye d'afficher la table des règles de mise en silence triée sur
141
        # le nom d'hôte par ordre croissant avec l'utilisateur 'no_rights' et on
142
        # s'assure qu'on reçoit bien une erreur 403
143
        environ = {'REMOTE_USER': 'no_rights'}
144
        response = self.app.get('/silence?sort=hostname&order=asc',
145
            extra_environ=environ, status=403)
146

    
147
        # 2. On affiche la table des règles de mise en silence triée sur le nom
148
        # d'hôte par ordre croissant avec l'utilisateur 'limited_rights'
149
        environ = {'REMOTE_USER': 'limited_rights'}
150
        response = self.app.get(
151
            '/silence?sort=hostname&order=asc', extra_environ=environ)
152

    
153
        # Il doit y avoir 2 lignes de résultats
154
        # - la 1ère concerne 'host1' ;
155
        # - la 2ème concerne 'service2' sur 'host1'.
156
        hostnames = response.lxml.xpath(
157
            '//table/tbody/tr/' \
158
            'td[@class="hostname"]/text()')
159
        assert_equal(hostnames, ['host1', 'host1'])
160
        servicenames = response.lxml.xpath(
161
            '//table/tbody/tr/' \
162
            'td[@class="servicename"]/text()')
163
        assert_equal(servicenames, ['service2'])
164

    
165
        # 3. On affiche la table des règles de mise en silence triée sur le nom
166
        # d'hôte par ordre croissant avec l'utilisateur 'manager'
167
        environ = {'REMOTE_USER': 'manager'}
168
        response = self.app.get(
169
            '/silence?sort=hostname&order=asc', extra_environ=environ)
170

    
171
        # Il doit y avoir 4 lignes de résultats
172
        # - la 1ère concerne 'host1' ;
173
        # - la 2ème concerne 'service2' sur 'host1' ;
174
        # - la 3ème concerne 'service1' sur 'host2' ;
175
        # - la 4ème concerne 'host3'.
176
        hostnames = response.lxml.xpath(
177
            '//table/tbody/tr/' \
178
            'td[@class="hostname"]/text()')
179
        assert_equal(hostnames, ['host1', 'host1', 'host2', 'host3'])
180
        servicenames = response.lxml.xpath(
181
            '//table/tbody/tr/' \
182
            'td[@class="servicename"]/text()')
183
        assert_equal(servicenames, ['service2', 'service1'])
184

    
185
    def test_descending_order(self):
186
        """ Tri des règles de mise en silence dans l'ordre décroissant """
187

    
188
        # 1. On essaye d'afficher la table des règles de mise en silence triée
189
        # sur le nom de service par ordre décroissant avec l'utilisateur
190
        # 'no_rights' et on s'assure qu'on reçoit bien une erreur 403
191
        environ = {'REMOTE_USER': 'no_rights'}
192
        response = self.app.get('/silence?sort=hostname&order=asc',
193
            extra_environ=environ, status=403)
194

    
195
        # 2. On affiche la table des règles de mise en silence triée sur le nom
196
        # de service par ordre décroissant avec l'utilisateur 'limited_rights'
197
        environ = {'REMOTE_USER': 'limited_rights'}
198
        response = self.app.get(
199
            '/silence?sort=servicename&order=desc', extra_environ=environ)
200

    
201
        # Il doit y avoir 2 lignes de résultats
202
        # - la 1ère concerne 'service2' sur 'host1' ;
203
        # - la 2ème concerne 'host1' ;
204
        hostnames = response.lxml.xpath(
205
            '//table/tbody/tr/' \
206
            'td[@class="hostname"]/text()')
207
        assert_equal(hostnames, ['host1', 'host1'])
208
        servicenames = response.lxml.xpath(
209
            '//table/tbody/tr/' \
210
            'td[@class="servicename"]/text()')
211
        assert_equal(servicenames, ['service2'])
212

    
213
        # 3. On affiche la table des règles de mise en silence triée sur le nom
214
        # de service par ordre décroissant avec l'utilisateur 'manager'
215
        environ = {'REMOTE_USER': 'manager'}
216
        response = self.app.get(
217
            '/silence?sort=servicename&order=desc', extra_environ=environ)
218

    
219
        # Il doit y avoir 4 lignes de résultats
220
        # - la 1ère concerne 'service2' sur 'host1' ;
221
        # - la 2ème concerne 'service1' sur 'host2' ;
222
        # - la 3ème concerne 'host1' ;
223
        # - la 4ème concerne 'host3'.
224
        hostnames = response.lxml.xpath(
225
            '//table/tbody/tr/' \
226
            'td[@class="hostname"]/text()')
227
        assert_equal(hostnames, ['host1', 'host2', 'host1', 'host3'])
228
        servicenames = response.lxml.xpath(
229
            '//table/tbody/tr/' \
230
            'td[@class="servicename"]/text()')
231
        assert_equal(servicenames, ['service2', 'service1'])
232

    
233
    def test_rule_creation(self):
234
        """ Ajout d'une règle de mise en silence """
235

    
236
        # 1. On essaye d'ajouter une règle de mise en silence sur 'service3'
237
        # avec l'utilisateur 'no_rights' et on s'assure qu'on reçoit bien une
238
        # erreur 403
239
        environ = {'REMOTE_USER': 'no_rights'}
240
        url = '/silence/create_or_modify?' + urllib.urlencode({
241
                'states':  'CRITICAL',
242
                'host':    'host3',
243
                'service': 'service3',
244
                'comment': 'commentaire accentué'
245
            })
246
        self.app.get(url, extra_environ=environ, status=403)
247

    
248
        # 2. On essaye d'ajouter une règle de mise en silence sur 'service3'
249
        # avec l'utilisateur 'limited_rights' et on s'assure qu'on est bien
250
        # redirigé sur un message d'erreur
251
        environ = {'REMOTE_USER': 'limited_rights'}
252
        url = '/silence/create_or_modify?' + urllib.urlencode({
253
                'states':  'CRITICAL',
254
                'host':    'host3',
255
                'service': 'service3',
256
                'comment': 'commentaire accentué'
257
            })
258
        response = self.app.get(url, extra_environ=environ, status=302)
259
        response = response.follow(status = 200, extra_environ = environ)
260
        assert_true(len(response.lxml.xpath(
261
            '//div[@id="flash"]/div[@class="error"]')))
262

    
263
        # 3. On ajoute une règle de mise en silence sur 'service4' avec
264
        # l'utilisateur 'limited_rights'
265
        environ = {'REMOTE_USER': 'limited_rights'}
266
        url = '/silence/create_or_modify?' + urllib.urlencode({
267
                'states':  'CRITICAL',
268
                'host':    'host4',
269
                'service': 'service4',
270
                'comment': 'commentaire accentué'
271
            })
272
        self.app.get(url, extra_environ=environ)
273

    
274
        # On recherche dans la base toutes les règles concernant 'service4'
275
        supitem_id = SupItem.get_supitem('host4', 'service4')
276
        silences = DBSession.query(Silence
277
            ).filter(Silence.idsupitem == supitem_id
278
            ).all()
279

    
280
        # On s'assure qu'il n'y en a qu'une, et on vérifie ses propriétés
281
        assert_equal(len(silences), 1)
282
        assert_equal([s.statename for s in silences[0].states], ['CRITICAL'])
283
        assert_equal(silences[0].comment, u'commentaire accentué')
284
        assert_equal(silences[0].author, u'limited_rights')
285

    
286
        # 4. On ajoute une règle de mise en silence sur 'service3' avec
287
        # l'utilisateur 'manager'
288
        environ = {'REMOTE_USER': 'manager'}
289
        url = '/silence/create_or_modify?' + urllib.urlencode({
290
                'states':  'CRITICAL',
291
                'host':    'host3',
292
                'service': 'service3',
293
                'comment': 'commentaire accentué'
294
            })
295
        self.app.get(url, extra_environ=environ)
296

    
297
        # On recherche dans la base toutes les règles concernant 'service3'
298
        supitem_id = SupItem.get_supitem('host3', 'service3')
299
        silences = DBSession.query(Silence
300
            ).filter(Silence.idsupitem == supitem_id
301
            ).all()
302

    
303
        # On s'assure qu'il n'y en a qu'une, et on vérifie ses propriétés
304
        assert_equal(len(silences), 1)
305
        assert_equal([s.statename for s in silences[0].states], ['CRITICAL'])
306
        assert_equal(silences[0].comment, u'commentaire accentué')
307
        assert_equal(silences[0].author, u'manager')
308

    
309
    def test_rule_update(self):
310
        """ Mise à jour d'une règle de mise en silence """
311

    
312
        # On recherche dans la base l'id de la règle concernant 'service1'
313
        service1_id = SupItem.get_supitem('host2', 'service1')
314
        service1_silence_id = DBSession.query(Silence
315
            ).filter(Silence.idsupitem == service1_id
316
            ).one().idsilence
317
        # On recherche dans la base l'id de la règle concernant 'service2'
318
        service2_id = SupItem.get_supitem('host1', 'service2')
319
        service2_silence_id = DBSession.query(Silence
320
            ).filter(Silence.idsupitem == service2_id
321
            ).one().idsilence
322

    
323
        # 1. On essaye de mettre à jour la règle de mise en silence sur
324
        # 'service1' avec l'utilisateur 'no_rights' et on s'assure qu'on reçoit
325
        # bien une erreur 403
326
        environ = {'REMOTE_USER': 'no_rights'}
327
        url = '/silence/create_or_modify?' + urllib.urlencode({
328
                'idsilence':  service1_silence_id,
329
                'states':  'CRITICAL',
330
                'host':    'host1',
331
                'service': 'service2',
332
                'comment': 'commentaire accentué'
333
            }) + '&' + urllib.urlencode({'states':  'WARNING'})
334
        self.app.get(url, extra_environ=environ, status=403)
335

    
336
        # 2. On essaye de mettre à jour la règle de mise en silence sur
337
        # 'service1' avec l'utilisateur 'limited_rights' et on s'assure qu'on
338
        # est bien redirigé sur un message d'erreur
339
        environ = {'REMOTE_USER': 'limited_rights'}
340
        url = '/silence/create_or_modify?' + urllib.urlencode({
341
                'idsilence':  service1_silence_id,
342
                'states':  'CRITICAL',
343
                'host':    'host2',
344
                'service': 'service1',
345
                'comment': 'commentaire accentué'
346
            }) + '&' + urllib.urlencode({'states':  'WARNING'})
347
        response = self.app.get(url, extra_environ=environ, status=302)
348
        response = response.follow(status = 200, extra_environ = environ)
349
        assert_true(len(response.lxml.xpath(
350
            '//div[@id="flash"]/div[@class="error"]')))
351

    
352
        # 3. On met à jour la règle de mise en silence sur 'service2' avec
353
        # l'utilisateur 'limited_rights'
354
        environ = {'REMOTE_USER': 'limited_rights'}
355
        url = '/silence/create_or_modify?' + urllib.urlencode({
356
                'idsilence':  service2_silence_id,
357
                'states':  'CRITICAL',
358
                'host':    'host1',
359
                'service': 'service2',
360
                'comment': 'commentaire accentué'
361
            }) + '&' + urllib.urlencode({'states':  'WARNING'})
362
        self.app.get(url, extra_environ=environ)
363

    
364
        # On recherche dans la base toutes les règles concernant 'service2'
365
        silences = DBSession.query(Silence
366
            ).filter(Silence.idsupitem == service2_id
367
            ).all()
368

    
369
        # On s'assure qu'il n'y en a qu'une, et on vérifie ses propriétés
370
        assert_equal(len(silences), 1)
371
        assert_equal(silences[0].idsilence, service2_silence_id)
372
        assert_equal(list(set([s.statename for s in silences[0].states]) -
373
            set([u'CRITICAL', u'WARNING'])), [])
374
        assert_equal(silences[0].comment, u'commentaire accentué')
375
        assert_equal(silences[0].author, u'limited_rights')
376

    
377
        # 4. On met à jour la règle de mise en silence sur 'service1' avec
378
        # l'utilisateur 'manager'
379
        environ = {'REMOTE_USER': 'manager'}
380
        url = '/silence/create_or_modify?' + urllib.urlencode({
381
                'idsilence':  service1_silence_id,
382
                'states':  'CRITICAL',
383
                'host':    'host2',
384
                'service': 'service1',
385
                'comment': 'commentaire accentué'
386
            }) + '&' + urllib.urlencode({'states':  'WARNING'})
387
        self.app.get(url, extra_environ=environ)
388

    
389
        # On recherche dans la base toutes les règles concernant 'service1'
390
        silences = DBSession.query(Silence
391
            ).filter(Silence.idsupitem == service1_id
392
            ).all()
393

    
394
        # On s'assure qu'il n'y en a qu'une, et on vérifie ses propriétés
395
        assert_equal(len(silences), 1)
396
        assert_equal(silences[0].idsilence, service1_silence_id)
397
        assert_equal(list(set([s.statename for s in silences[0].states]) -
398
            set([u'CRITICAL', u'WARNING'])), [])
399
        assert_equal(silences[0].comment, u'commentaire accentué')
400
        assert_equal(silences[0].author, u'manager')
401

    
402
    def test_rule_deletion(self):
403
        """ Suppression d'une règle de mise en silence """
404

    
405
        # On recherche dans la base l'id de la règle concernant 'service1'
406
        service1_id = SupItem.get_supitem('host2', 'service1')
407
        service1_silence_id = DBSession.query(Silence
408
            ).filter(Silence.idsupitem == service1_id
409
            ).one().idsilence
410
        # On recherche dans la base l'id de la règle concernant 'service2'
411
        service2_id = SupItem.get_supitem('host1', 'service2')
412
        service2_silence_id = DBSession.query(Silence
413
            ).filter(Silence.idsupitem == service2_id
414
            ).one().idsilence
415

    
416
        # On essaye de supprimer la règle de mise en silence portant sur
417
        # 'service1' avec l'utilisateur 'no_rights' et on s'assure qu'on reçoit
418
        # bien une erreur 403
419
        environ = {'REMOTE_USER': 'no_rights'}
420
        url = '/silence/delete?id=%s' % service1_silence_id
421
        response = self.app.get(url, extra_environ=environ, status=403)
422

    
423
        # On essaye de supprimer la règle de mise en silence portant sur
424
        # 'service1' avec l'utilisateur 'limited_rights' et on s'assure qu'on
425
        # est bien redirigé sur un message d'erreur
426
        environ = {'REMOTE_USER': 'limited_rights'}
427
        url = '/silence/delete?id=%s' % service1_silence_id
428
        response = self.app.get(url, extra_environ=environ, status=302)
429
        response = response.follow(status = 200, extra_environ = environ)
430
        assert_true(len(response.lxml.xpath(
431
            '//div[@id="flash"]/div[@class="error"]')))
432

    
433
        # On supprime la règle de mise en silence portant sur 'service2' avec
434
        # l'utilisateur 'limited_rights'
435
        environ = {'REMOTE_USER': 'limited_rights'}
436
        url = '/silence/delete?id=%s' % service2_silence_id
437
        response = self.app.get(url, extra_environ=environ)
438
        # On s'assure qu'elle n'existe plus en base
439
        silences = DBSession.query(Silence
440
            ).filter(Silence.idsupitem == service2_silence_id
441
        ).all()
442
        assert_equal(len(silences), 0)
443

    
444
        # On supprime la règle de mise en silence portant sur 'service1' avec
445
        # l'utilisateur 'manager'
446
        environ = {'REMOTE_USER': 'manager'}
447
        url = '/silence/delete?id=%s' % service1_silence_id
448
        response = self.app.get(url, extra_environ=environ)
449
        # On s'assure qu'elle n'existe plus en base
450
        silences = DBSession.query(Silence
451
            ).filter(Silence.idsupitem == service1_id
452
        ).all()
453
        assert_equal(len(silences), 0)
454

    
455
class TestSilencePagination(TestController):
456
    """
457
    Test de la pagination de la table des règles d'inhibition dans VigiBoard.
458
    """
459
    application_under_test = 'pagination'
460

    
461
    def setUp(self):
462
        super(TestSilencePagination, self).setUp()
463
        populate_DB()
464

    
465
    def test_pagination(self):
466
        """ Pagination des règles de mise en silence """
467

    
468
        # On affiche la seconde page de la table des règles de mise en silence
469
        environ = {'REMOTE_USER': 'manager'}
470
        response = self.app.get('/silence?page=2', extra_environ=environ)
471

    
472
        # Il ne doit y avoir qu'une seule ligne de
473
        # résultats concernant "service2" sur "host1"
474
        hostnames = response.lxml.xpath(
475
            '//table/tbody/tr/' \
476
            'td[@class="hostname"]/text()')
477
        assert_equal(hostnames, ['host2'])
478
        servicenames = response.lxml.xpath(
479
            '//table/tbody/tr/' \
480
            'td[@class="servicename"]/text()')
481
        assert_equal(servicenames, ['service1'])
482

    
483