Project

General

Profile

Revision ee3ae8c8

IDee3ae8c8af17e3c5a2ccf13231c071ca30fc26ae
Parent 6f56e540
Child 10848680

Added by Francois POIROTTE over 14 years ago

Corrections en tous genres dans Vigiboard.

- Mise à jour des contrôleurs pour tenir compte de la disparition de l'attribut "active" et l'ajout des variantes de "severity" (initial, current, peak).
- VigiboardRequest : utilisation de variables static pour les noms des différents niveaux de sévérité (évite une duplication dans le RootController).
- Ajout d'informations supplémentaires lors de l'historisation d'une modification.
- Correction d'un bug dans le décompte du nombre de pages à afficher.
XXX Utiliser le module "Paginate" pour la pagination, plutôt que de le recoder nous-même...

git-svn-id: https://vigilo-dev.si.c-s.fr/svn@896 b22e2e97-25c9-44ff-b637-2e5ceca36478

View differences:

development.ini
23 23
use = egg:vigiboard
24 24

  
25 25
; Nombre d'évènements par page.
26
vigiboard_item_per_page = 15
26
vigiboard_items_per_page = 15
27 27

  
28 28
; URL vers laquelle le logo de Vigilo redirige.
29 29
vigiboard_links.logo = /
vigiboard/controllers/error.py
2 2
"""Error controller"""
3 3

  
4 4
from tg import request, expose
5
from pylons.i18n import ugettext as _
5 6

  
6 7
__all__ = ['ErrorController']
7 8

  
......
22 23
    def document(self, *args, **kwargs):
23 24
        """Render the error document"""
24 25
        resp = request.environ.get('pylons.original_response')
25
        default_message = ("<p>We're sorry but we weren't able to process "
26
                           " this request.</p>")
26
        default_message = ("<p>" + _("We're sorry but we weren't " +
27
                           "able to process this request.") + "</p>")
27 28
        values = dict(prefix=request.environ.get('SCRIPT_NAME', ''),
28
                      code=request.params.get('code', resp.status_int),
29
                      code=int(request.params.get('code', resp.status_int)),
29 30
                      message=request.params.get('message', default_message))
30 31
        return values
vigiboard/controllers/root.py
8 8
from pylons.i18n import ugettext as _
9 9
from pylons.controllers.util import abort
10 10
from sqlalchemy import asc
11
from datetime import datetime
12
import math
13

  
11 14
from vigiboard.model import DBSession
12 15
from vigiboard.model import Event, EventHistory, EventsAggregate, \
13 16
                            Host, HostGroup, \
......
105 108

  
106 109
        # Calcul des éléments à afficher et du nombre de pages possibles
107 110
        total_rows = aggregates.num_rows()
108
        item_per_page = int(config['vigiboard_item_per_page'])
111
        items_per_page = int(config['vigiboard_items_per_page'])
109 112

  
110
        if total_rows <= item_per_page * (page-1):
113
        if total_rows <= items_per_page * (page-1):
111 114
            page = 1
112
        id_first_row = item_per_page * (page-1)
113
        id_last_row = min(id_first_row + item_per_page, total_rows)
115
        id_first_row = items_per_page * (page-1)
116
        id_last_row = min(id_first_row + items_per_page, total_rows)
114 117

  
115 118
        aggregates.format_events(id_first_row, id_last_row)
116 119
        aggregates.generate_tmpl_context()
120
        nb_pages = int(math.ceil(total_rows / (items_per_page + 0.0)))
117 121

  
118 122
        return dict(
119 123
               events = aggregates.events,
......
122 126
                   'id_last_row': id_last_row,
123 127
                   'total_rows': total_rows,
124 128
               },
125
               pages = range(1, (total_rows / item_per_page) + 2),
129
               pages = range(1, nb_pages + 1),
126 130
               page = page,
127 131
               event_edit_status_options = edit_event_status_options,
128 132
               history = [],
......
151 155
        user = User.by_user_name(username)
152 156

  
153 157
        event = DBSession.query(
154
                        EventsAggregate.severity,
158
                        EventsAggregate.initial_severity,
159
                        EventsAggregate.current_severity,
160
                        EventsAggregate.peak_severity,
155 161
                        Event.hostname,
156 162
                        Event.servicename,
157
                        Event.idevent
163
                        Event.idevent,
158 164
                 ).join(
159 165
                    (Event, EventsAggregate.idcause == Event.idevent),
160 166
                    (HostGroup, Event.hostname == HostGroup.hostname),
161 167
                 ).filter(HostGroup.groupname.in_(user.groups)
162
                 ).filter(EventsAggregate.idaggregate == idaggregate).one()
168
                 ).filter(EventsAggregate.idaggregate == idaggregate
169
                 ).one()
163 170

  
164
        initial_state = DBSession.query(
171
        history = DBSession.query(
165 172
                    EventHistory,
166 173
                 ).filter(EventHistory.idevent == event.idevent
167 174
                 ).order_by(asc(EventHistory.timestamp)
168
                 ).order_by(asc(EventHistory.type_action))
169

  
170
        if initial_state.count() > 0 :
171
            for i in initial_state:
172
                if i.value != '' and i.value is not None:
173
                    initial_state = i.value
174
                    break
175
        else :
176
            initial_state = 0
175
                 ).order_by(asc(EventHistory.type_action)).all()
177 176

  
178
        severity = (
179
                _('None'), _('OK'), _('Suppressed'), _('Initial'),
180
                _('Maintenance'), _('Minor'), _('Major'), _('Critical')
181
            )
182
        if event.severity is None:
183
            current_state = _('Unknown')
184
        else:
185
            current_state = severity[event.severity]
177
        current_severity = VigiboardRequest.get_severity(event.current_severity)
178
        initial_severity = VigiboardRequest.get_severity(event.initial_severity)
179
        peak_severity = VigiboardRequest.get_severity(event.peak_severity)
186 180

  
187 181
        eventdetails = {}
188 182
        for edname, edlink in \
......
195 189
                    }
196 190

  
197 191
        return dict(
198
                initial_state = severity[int(initial_state)],
199
                current_state = current_state,
192
                initial_state = VigiboardRequest.severity[initial_severity],
193
                current_state = VigiboardRequest.severity[current_severity],
194
                peak_state = VigiboardRequest.severity[peak_severity],
200 195
                idaggregate = idaggregate,
201 196
                host = event.hostname,
202 197
                service = event.servicename,
......
273 268
        # Vérification qu'il y a au moins 1 évènement qui correspond
274 269
        if events.num_rows() == 0 :
275 270
            redirect('/')
276
       
271

  
277 272
        events.format_events(0, events.num_rows())
278 273
        events.format_history()
279
        events.generate_tmpl_context() 
274
        events.generate_tmpl_context()
275

  
280 276
        return dict(
281 277
                    events = events.events,
282 278
                    rows_info = {
......
345 341
                event = req[0]
346 342

  
347 343
            if krgv['trouble_ticket'] != '' :
348
                event.trouble_ticket = krgv['trouble_ticket']
349 344
                history = EventHistory(
350 345
                        type_action="Ticket change",
351 346
                        idevent=event.idcause,
352
                        value='',
353
                        text='',
347
                        value=krgv['trouble_ticket'],
348
                        text=_("Changed trouble ticket from '%s' to '%s'") % (
349
                            event.trouble_ticket, krgv['trouble_ticket']
350
                        ),
354 351
                        username=username,
352
                        timestamp=datetime.now(),
355 353
                    )
356 354
                DBSession.add(history)   
355
                event.trouble_ticket = krgv['trouble_ticket']
357 356

  
358 357
            if krgv['status'] != 'NoChange' :
359
                event.status = krgv['status']
360 358
                history = EventHistory(
361 359
                        type_action="Acknowlegement change state",
362 360
                        idevent=event.idcause,
363
                        value='',
364
                        text='',
361
                        value=krgv['status'],
362
                        text=_("Changed acknowledgement status from '%s' to '%s'") % (
363
                            event.status, krgv['status']
364
                        ),
365 365
                        username=username,
366
                        timestamp=datetime.now(),
366 367
                    )
367 368
                DBSession.add(history)
369
                event.status = krgv['status']
368 370

  
369 371
        DBSession.flush()       
370 372
        flash(_('Updated successfully'))
vigiboard/controllers/vigiboard_plugin/shn.py
57 57
        idaggregate = krgv['idaggregate']
58 58
        aggregate = DBSession.query(EventsAggregate) \
59 59
                .filter(EventsAggregate.idaggregate == idaggregate).one()
60
        shns = aggregate.highlevel
60
        shns = aggregate.high_level_services
61 61

  
62 62
        return dict(shns=[shn.servicename for shn in shns]) 
63 63

  
vigiboard/controllers/vigiboardrequest.py
13 13
from pylons.i18n import ugettext as _
14 14

  
15 15
class VigiboardRequest():
16
    
16
    class_ack = {
17
        'Acknowledged': 'Ack',
18
        'None': '',
19
        'AAClosed': 'Ack'
20
    }
21

  
22
    severity = (
23
        _('OK'),            # 0
24
        _('Suppressed'),
25
        _('Initial'),
26
        _('Maintenance'),
27
        _('Minor'),
28
        _('Major'),
29
        _('Critical'),      # 6
30
    )
31

  
32
    bouton_severity = (
33
        'OK', 'Minor', 'Minor',
34
        'Minor', 'Minor', 'Major',
35
        'Critical',
36
    )
37

  
38
    @classmethod
39
    def get_severity(cls, severity):
40
        if not severity:
41
            severity = 0
42
        return int(severity)
43

  
44

  
17 45
    """
18 46
    Classe gérant la génération de la requête finale,
19 47
    le préformatage des évènements et celui des historiques
......
29 57
        """
30 58

  
31 59
        self.user_groups = user.groups
32

  
33
        self.bouton_severity = (
34
                'Minor', 'Minor', 'Minor', 'Minor',
35
                'Minor', 'Minor', 'Major', 'Critical'
36
            )
37

  
38
        self.class_severity = (
39
                'None', 'None', 'None', 'None',
40
                'None', 'Minor', 'Major', 'Critical'
41
            )
42

  
43
        self.severity = (
44
                _('None'),          # 0
45
                _('OK'),
46
                _('Suppressed'),
47
                _('Initial'),
48
                _('Maintenance'),
49
                _('Minor'),
50
                _('Major'),
51
                _('Critical'),      # 7
52
            )
53

  
54
        self.class_ack = {
55
                'Acknowledged': 'Ack',
56
                'None': '',
57
                'AAClosed': 'Ack'
58
            }
59

  
60 60
        self.generaterq = False
61 61

  
62 62
        self.table = [
......
77 77
        self.filter = [
78 78
                HostGroup.groupname.in_(self.user_groups),
79 79
                ServiceGroup.groupname.in_(self.user_groups),
80
                not_(and_(Event.active == False,
80

  
81
                # On masque les évènements marqués comme OK
82
                # (current_severity == 0) et déjà traités
83
                # (status == 'AAClosed').
84
                not_(and_(EventsAggregate.current_severity == 0,
81 85
                    EventsAggregate.status == u'AAClosed')),
82
                EventsAggregate.timestamp_active != None#,
83
                #not_(Event.timestamp_active.like('0000-00-00 00:00:00'))
86
                EventsAggregate.timestamp_active != None,
84 87
            ]
85 88

  
86 89
        self.orderby = [
87
                desc(EventsAggregate.status),
88
                desc(Event.active),
89
                desc(EventsAggregate.severity),
90
                desc(EventsAggregate.status),   # None, Acknowledged, AAClosed
91
                desc(EventsAggregate.current_severity), # Code pour Minor, etc.
90 92
                asc(Event.hostname),
91 93
                desc(Event.timestamp),
92 94
            ]
......
94 96
        self.groupby = [
95 97
                EventsAggregate.idaggregate,
96 98
                EventsAggregate,
97
                Event.active,
98 99
                Event.hostname,
99 100
                Event.timestamp,
100 101
            ]
......
106 107
        self.req = DBSession
107 108
        self.context_fct = []
108 109

  
109
    def get_bouton_severity(self, severity):
110
        if severity is None:
111
            return 'Unknown'
112
        return self.bouton_severity[severity]
113

  
114 110
    def add_plugin(self, *argv):
115 111

  
116 112
        """
......
291 287
        @return: Dictionnaire représentant la classe à appliquer
292 288
        """
293 289

  
294
        if event.cause.active and event.status == 'AAClosed':
290
        if event.status == 'AAClosed':
295 291
            return { 'src': url('/images/crossed.png') }
296 292
        elif event.status == 'Acknowledged' :
297 293
            return { 'src': url('/images/checked.png') }
......
328 324
                [_('Output'), {'style':'text-align:left'}]
329 325
                ]
330 326
        lst_title.extend([[plug.name, plug.style] for plug in self.plugin])
331
        lst_title.extend([['['+_('TT')+']', {'title': _('Trouble Ticket')}],
327
        lst_title.extend([['[' + _('TT') + ']', {'title': _('Trouble Ticket')}],
332 328
                            ['', {}]])
333 329
        events = [lst_title]
334 330
        i = 0
......
355 351
            #   Une liste (une case par plugin) de ce que le plugin souhaite
356 352
            #       afficher en fonction de l'évènement
357 353

  
358
            if event.cause.active:
359
                events.append([
360
                        event,
361
                        {'class': class_tr[i % 2]},
362
                        {'class': self.get_bouton_severity(event.severity) + \
363
                            self.class_ack[event.status]},
364
                        {'class': self.get_bouton_severity(event.severity) + \
365
                            self.class_ack[event.status]},
366
                        {'src': '/images/%s2.png' % \
367
                            self.get_bouton_severity(event.severity).upper()},
368
                        self.format_events_img_status(event),
369
                        [[j.__show__(event), j.style] for j in self.plugin]
370
                    ])
354
            current_severity = self.get_severity(event.current_severity)
355
            initial_severity = self.get_severity(event.initial_severity)
371 356

  
372
            else:
373
                events.append([
374
                        event,
375
                        {'class': class_tr[i % 2]},
376
                        {'class': self.get_bouton_severity(event.severity) + \
377
                            self.class_ack[event.status] },
378
                        {'class': 'Cleared' + self.class_ack[event.status]},
379
                        {'src': '/images/%s2.png' % \
380
                            self.get_bouton_severity(event.severity).upper()},
381
                        self.format_events_img_status(event),
382
                        [[j.__show__(event), j.style] for j in self.plugin]
383
                    ])
357
            events.append([
358
                    event,
359
                    {'class': class_tr[i % 2]},
360
                    {'class': self.bouton_severity[initial_severity] + \
361
                        self.class_ack[event.status]},
362
                    {'class': self.bouton_severity[current_severity] + \
363
                        self.class_ack[event.status]},
364
                    {'src': '/images/%s2.png' % \
365
                        self.bouton_severity[current_severity].upper()},
366
                    self.format_events_img_status(event),
367
                    [[j.__show__(event), j.style] for j in self.plugin]
368
                ])
384 369
            i += 1
385 370

  
386 371
        # On sauvegarde la liste précédemment créée puis on remplit
......
397 382
        de l'affichage pour un historique donné.
398 383
        """
399 384

  
400
        history = DBSession.query(EventHistory
385
        history = DBSession.query(
386
                    EventHistory,
401 387
                ).filter(EventHistory.idevent.in_(self.idevents)
402 388
                ).order_by(desc(EventHistory.timestamp)
403 389
                ).order_by(desc(EventHistory.idhistory))
......
406 392
            for i in self.idevents:
407 393
                self.hist[i] = []
408 394
            return
395

  
409 396
        hists = {}
410 397
        i = 0
411 398
        class_tr = ['odd', 'even']
412
        hist_tmp = []
413
        last_idevent = history[0].idevent
414
        for hist in history :
415
            
416
            if last_idevent != hist.idevent:
417
                hists[last_idevent] = hist_tmp
418
                last_idevent = hist.idevent
419
                hist_tmp = []
399

  
400
        for hist in history:
401
            if not hist.idevent in hists:
402
                hists[hist.idevent] = []
420 403

  
421 404
            # La liste pour l'historique actuel comporte dans l'ordre :
422 405
            #   Le moment où il a été généré
423 406
            #   Qui l'a généré
424 407
            #   Le type d'action qui a été appliqué
425
            #   La sévérité de l'action si besoin est
408
            #   La valeur de l'action
426 409
            #   Le détail de l'action
427
            #   La classe à appliquer à la ligne (permet d'alterner
428
            #       les couleurs)
429
            #   La classe de la sévérité s'il y a
430

  
431
            if hist.value :
432
                hist_tmp.append([
433
                    hist.timestamp,
434
                    hist.username,
435
                    hist.type_action,
436
                    self.severity[min(int(hist.value), 7)],
437
                    hist.text,
438
                    {'class': class_tr[i % 2]},
439
                    {'class': self.class_severity[min(int(hist.value), 7)]}
440
                ])
441

  
442
            else:
443
                hist_tmp.append([
444
                    hist.timestamp,
445
                    hist.username,
446
                    hist.type_action,
447
                    self.severity[0],
448
                    hist.text,
449
                    {'class': class_tr[i % 2]},
450
                    {'class': self.class_severity[0]}
451
                ])    
410
            #   La classe à appliquer à la ligne
411
            #       (permet d'alterner les couleurs)
412

  
413
            hists[hist.idevent].append([
414
                hist.timestamp,
415
                hist.username,
416
                hist.type_action,
417
                hist.value,
418
                hist.text,
419
                {'class': class_tr[i % 2]},
420
            ])
452 421
            i += 1
453 422
        
454
        hists[last_idevent] = hist_tmp
455 423
        self.hist = hists
456 424

  
457 425
    def generate_tmpl_context(self):
vigiboard/tests/functional/test_vigiboardrequest.py
24 24
    def setUp(self):
25 25
        TestController.setUp(self)
26 26

  
27
        if self.__dict__.get('is_setup', False):
28
            return
29
        self.is_setup = True
30

  
31 27
        # On peuple la base de données.
32 28

  
33 29
        # Les groupes et leurs dépendances
......
80 76

  
81 77
        # Les évènements eux-mêmes
82 78
        event_template = {
83
            'active': True,
84 79
            'message': u'foo',
85 80
        }
86 81

  
......
122 117
        # Les évènements corrélés
123 118
        aggregate_template = {
124 119
            'timestamp_active': datetime.now(),
125
            'severity': 0,
120
            'current_severity': 1,
121
            'initial_severity': 1,
122
            'peak_severity': 1,
126 123
            'status': u'None',
127 124
        }
128 125
        self.aggregate1 = EventsAggregate(

Also available in: Unified diff