Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

vigiboard / vigiboard / controllers / vigiboard_ctl / vigiboardrequest.py @ dde732e5

History | View | Annotate | Download (14.8 KB)

1 20367931 Thomas ANDREJAK
# -*- coding: utf-8 -*-
2
# vim:set expandtab tabstop=4 shiftwidth=4: 
3
"""Gestion de la requête, des plugins et de l'affichage du Vigiboard"""
4
5 dde732e5 Thomas ANDREJAK
from vigiboard.model import Events, Host, Service, \
6 35cea70e Thomas ANDREJAK
        HostGroups, ServiceGroups, EventHistory
7 01862853 Thomas ANDREJAK
from tg import tmpl_context, url, config
8 20367931 Thomas ANDREJAK
from vigiboard.model import DBSession
9 52661754 Thomas ANDREJAK
from sqlalchemy import not_ , and_ , asc , desc
10 20367931 Thomas ANDREJAK
from tw.jquery import JQueryUIDialog
11 35cea70e Thomas ANDREJAK
from vigiboard.widgets.edit_event import EditEventForm , SearchForm
12 977b981c Thomas ANDREJAK
from vigiboard.controllers.userutils import get_user_groups
13 01862853 Thomas ANDREJAK
from vigiboard.controllers.vigiboard_ctl.vigiboard_plugin import VigiboardRequestPlugin
14 52661754 Thomas ANDREJAK
from pylons.i18n import ugettext as _
15 20367931 Thomas ANDREJAK
16
class VigiboardRequest():
17
    
18
    """
19
    Classe gérant la génération de la requête finale,
20
    le préformatage des évènements et celui des historiques
21
    """
22
23
    def __init__(self):
24
25
        """
26
        Initialisation de toutes les variables nécessaires: Liste des groupes de
27 52661754 Thomas ANDREJAK
        l'utilisateur, les classes à appliquer suivant la sévérité, les
28
        différentes étapes de la génération de la requête et la liste des
29
        plugins appliqués.
30 20367931 Thomas ANDREJAK
        """
31
32 52661754 Thomas ANDREJAK
        self.user_groups = get_user_groups()
33
        self.bouton_severity = { 0: 'Minor', 1: 'Minor', 2: 'Minor',
34
                3: 'Minor', 4: 'Minor', 5: 'Minor', 6: 'Major', 7: 'Critical' }
35
        self.class_severity = { 0: 'None', 1: 'None', 2: 'None', 3: 'None',
36
                4: 'None', 5: 'Minor', 6: 'Major', 7: 'Critical' }
37
        self.severity = { 0: _('None'), 1: _('OK'), 2: _('Suppressed'),
38
                3: _('Initial'), 4: _('Maintenance'), 5: _('Minor'),
39
                6: _('Major'), 7: _('Critical') }
40 20367931 Thomas ANDREJAK
41 52661754 Thomas ANDREJAK
        self.class_ack = {'Acknowledged': 'Ack', 'None': '', 'AAClosed': 'Ack'}
42 20367931 Thomas ANDREJAK
43 52661754 Thomas ANDREJAK
        self.generaterq = False
44 20367931 Thomas ANDREJAK
        self.table = [Events]
45
        self.join = [( Host, Events.hostname == Host.name ),
46
                ( Service, Events.servicename == Service.name ),
47
                ( HostGroups , Host.name == HostGroups.hostname ),
48 52661754 Thomas ANDREJAK
                ( ServiceGroups , Service.name == ServiceGroups.servicename )
49
                ]
50 20367931 Thomas ANDREJAK
        self.outerjoin = []
51
        self.filter = [HostGroups.groupname.in_(self.user_groups),
52 52661754 Thomas ANDREJAK
                 ServiceGroups.groupname.in_(self.user_groups),
53
                 not_(and_(Events.active == False,
54
                     Events.status == 'AAClosed')),
55 9c0dbb6a Thomas ANDREJAK
                 Events.timestamp_active != None#,
56
                 #not_(Events.timestamp_active.like('0000-00-00 00:00:00'))
57
                 ]
58
        self.orderby = [desc(Events.status),
59 20367931 Thomas ANDREJAK
                                desc(Events.active),
60
                                desc(Events.severity),
61
                                asc(Events.hostname),
62
                                desc(Events.timestamp)]
63
        self.groupby = []
64
        self.plugin = []
65 52661754 Thomas ANDREJAK
        self.events = []
66
        self.idevents = []
67
        self.hist = []
68
        self.req = DBSession
69
70
    def add_plugin(self, *argv):
71 20367931 Thomas ANDREJAK
        
72
        """
73
        Ajout d'un plugin, on lui prélève ses ajouts dans la requête
74
        """
75
        for i in argv :
76 52661754 Thomas ANDREJAK
            if isinstance(i, VigiboardRequestPlugin):
77 35cea70e Thomas ANDREJAK
                if i.table :
78
                    self.add_table(*i.table)
79
                if i.join :
80
                    self.add_join(*i.join)
81
                if i.outerjoin :
82
                    self.add_outer_join(*i.outerjoin)
83
                if i.filter :
84
                    self.add_filter(*i.filter)
85
                if i.groupby :    
86
                    self.add_group_by(*i.groupby)
87
                if i.orderby :
88
                    self.add_order_by(*i.orderby)
89 20367931 Thomas ANDREJAK
                self.plugin.append(i)
90
91 52661754 Thomas ANDREJAK
    def generate_request(self):
92 20367931 Thomas ANDREJAK
        
93
        """
94
        Génération de la requête avec l'ensemble des données stockées
95
        et la place dans la variable rq de la classe
96
        """
97 01862853 Thomas ANDREJAK
        for plug in config['vigiboard_plugins']:
98
            try:
99
                mypac = __import__(
100
                    'vigiboard.controllers.vigiboard_ctl.vigiboard_plugin.' +\
101
                            plug[0],globals(), locals(), [plug[1]],-1)
102
                self.add_plugin(getattr(mypac,plug[1])())
103
            except:
104
                raise
105 20367931 Thomas ANDREJAK
        
106
        # query et join ont besoin de referrence
107 52661754 Thomas ANDREJAK
        self.req = self.req.query(*self.table)
108
        self.req = self.req.join(*self.join)
109 20367931 Thomas ANDREJAK
110
        # le reste, non
111
        for i in self.outerjoin:
112 52661754 Thomas ANDREJAK
            self.req = self.req.outerjoin(i)
113 20367931 Thomas ANDREJAK
        for i in self.filter:
114 52661754 Thomas ANDREJAK
            self.req = self.req.filter(i)
115 20367931 Thomas ANDREJAK
        for i in self.groupby:
116 52661754 Thomas ANDREJAK
            self.req = self.req.group_by(i)
117 20367931 Thomas ANDREJAK
        for i in self.orderby:
118 52661754 Thomas ANDREJAK
            self.req = self.req.order_by(i)
119 20367931 Thomas ANDREJAK
120 52661754 Thomas ANDREJAK
    def num_rows(self):
121 20367931 Thomas ANDREJAK
122
        """
123
        Retourne le nombre de lignes de la requête.
124
        Si celle-ci n'est pas encore générée, on le fait.
125

126
        @return: Nombre de ligne
127
        """
128
129
        if not self.generaterq :
130 52661754 Thomas ANDREJAK
            self.generate_request()
131 20367931 Thomas ANDREJAK
            self.generaterq = True
132 52661754 Thomas ANDREJAK
        return self.req.count()
133 20367931 Thomas ANDREJAK
134 52661754 Thomas ANDREJAK
    def add_table(self, *argv):
135 20367931 Thomas ANDREJAK
        
136
        """
137
        Ajoute une ou plusieurs tables/élément d'une table à
138
        la requête.
139

140
        @param argv: Liste des tables à ajouter
141
        """
142
        
143
        #On vérifi qu'il n'y a pas de doublons dans la liste des
144
        #tables finale
145
        
146
        for i in argv :
147
            for j in self.table:
148
                if str(i) == str(j):
149
                    break
150
            self.table.append(i)
151
152 52661754 Thomas ANDREJAK
    def add_join(self, *argv):
153 20367931 Thomas ANDREJAK
        
154
        """
155
        Ajoute une ou plusieurs jointures à
156
        la requête.
157

158
        @param argv: Liste des jointures à ajouter
159
        """
160
        
161
        #On vérifi qu'il n'y a pas de doublons dans la liste des
162
        #jointures finale
163
        
164
        for i in argv:
165
            for j in self.join:
166
                if str(i) == str(j):
167
                    break
168
            self.join.append(i)
169
170 52661754 Thomas ANDREJAK
    def add_outer_join(self, *argv):
171 20367931 Thomas ANDREJAK
        
172
        """
173
        Ajoute une ou plusieurs jointures externes à
174
        la requête.
175

176
        @param argv: Liste des jointures externes à ajouter
177
        """
178
        
179
        #On vérifi qu'il n'y a pas de doublons dans la liste des
180
        #jointures externes finale
181
        
182
        for i in argv:
183
            for j in self.outerjoin:
184
                if str(i) == str(j):
185
                    break
186
            self.outerjoin.append(i)    
187
188 52661754 Thomas ANDREJAK
    def add_filter(self, *argv):
189 20367931 Thomas ANDREJAK
190
        """
191
        Ajoute un ou plusieurs filtres à la requête.
192

193
        @param argv: Liste des filtres à ajouter
194
        """
195
        
196
        #On vérifi qu'il n'y a pas de doublons dans la liste des
197
        #filtres finale
198
        
199
        for i in argv:
200
            for j in self.filter:
201
                if str(i) == str(j):
202
                    break
203
            self.filter.append(i)
204
205 52661754 Thomas ANDREJAK
    def add_group_by(self, *argv):
206 20367931 Thomas ANDREJAK
207
        """
208
        Ajoute un ou plusieurs groupements à la requête.
209

210
        @param argv: Liste des groupements à ajouter
211
        """
212
        
213
        #On vérifi qu'il n'y a pas de doublons dans la liste des
214
        #groupements finale
215
        
216
        for i in argv:
217
            for j in self.groupby:
218
                if str(i) == str(j):
219
                    break
220
            self.groupby.append(i)
221
222 52661754 Thomas ANDREJAK
    def add_order_by(self, *argv):
223 20367931 Thomas ANDREJAK
224
        """
225
        Ajoute un ou plusieurs orders à la requête.
226

227
        @param argv: Liste des ordres à ajouter
228
        """
229
        
230
        #On vérifi qu'il n'y a pas de doublons dans la liste des
231
        #ordres finale
232
        
233
        for i in argv:
234
            for j in self.orderby:
235
                if str(i) == str(j):
236
                    break
237
            self.orderby.append(i)
238
239 52661754 Thomas ANDREJAK
    def format_events_img_statu (self, event):
240 20367931 Thomas ANDREJAK
        
241
        """
242
        Suivant l'état de l'évènement, retourne la classe à appliquer
243
        à l'image indiquant si l'évènement est pris en compte ou non.
244

245
        @param event: l'évènement à analyser
246

247
        @return: Dictionnaire représentant la classe à appliquer
248
        """
249
250
        if event.active and event.status == 'AAClosed':
251 95743443 Thomas ANDREJAK
            return { 'src': url('/images/crossed.png') }
252 20367931 Thomas ANDREJAK
        elif event.status == 'Acknowledged' :
253 95743443 Thomas ANDREJAK
            return { 'src': url('/images/checked.png') }
254 20367931 Thomas ANDREJAK
        else:
255
            return None
256
257 52661754 Thomas ANDREJAK
    def format_events(self, first_row, last_row):
258 20367931 Thomas ANDREJAK
        
259
        """
260
        Formate la réponse de la requête et y applique les plugins
261
        pour un affichage simple du résultat par Genshi.
262 52661754 Thomas ANDREJAK
        On génère une liste de liste, chaqu'une étant la description de
263
        l'affichage pour un évènement donné.
264 20367931 Thomas ANDREJAK

265
        @param first_row: Indice de début de la liste des évènements
266
        @param last_row: Indice de fin de la liste des évènements
267
        """
268
        
269
        # Si la requête n'est pas générée, on le fait
270
        if not self.generaterq :
271 52661754 Thomas ANDREJAK
            self.generate_request()
272 20367931 Thomas ANDREJAK
            self.generaterq = True
273
274
        # Liste des éléments pour la tête du tableau
275
276 52661754 Thomas ANDREJAK
        lst_title = ['', _('Date<br />[Duration]'), '#', _('Host'),
277
                _('Service Type<br />Service Name'), _('Output')]
278 20367931 Thomas ANDREJAK
        lst_title.extend([plug.name for plug in self.plugin])
279 52661754 Thomas ANDREJAK
        lst_title.extend(['[T T]', ''])
280 20367931 Thomas ANDREJAK
        
281 52661754 Thomas ANDREJAK
        events = [lst_title]
282
        i = 0
283
        class_tr = ['odd', 'even']
284 20367931 Thomas ANDREJAK
        ids = []
285 52661754 Thomas ANDREJAK
        for req in self.req[first_row : last_row]:
286 20367931 Thomas ANDREJAK
287 52661754 Thomas ANDREJAK
            # Si il y a plus d'un élément dans la liste des tables,
288
            # rq devient une liste plutôt que d'être directement la
289
            # table souhaité
290 20367931 Thomas ANDREJAK
            
291 52661754 Thomas ANDREJAK
            if isinstance(req, Events) :
292
                event = req
293 20367931 Thomas ANDREJAK
            else :
294 52661754 Thomas ANDREJAK
                event = req[0]
295 20367931 Thomas ANDREJAK
            ids.append(event.idevent)
296 52661754 Thomas ANDREJAK
297 20367931 Thomas ANDREJAK
            # La liste pour l'évènement actuel comporte dans l'ordre :
298
            #   L'évènment en lui même
299 52661754 Thomas ANDREJAK
            #   La classe à appliquer sur la ligne (permet d'alterner les
300
            #       couleurs suivant les lignes)
301 20367931 Thomas ANDREJAK
            #   La classe pour la case comportant la flèche de détails
302
            #   La classe pour la date, l'occurrence et l'édition
303
            #   L'image a affiche pour la flèche de détails
304 52661754 Thomas ANDREJAK
            #   Une liste (une case par plugin) de ce que le plugin souhaite
305
            #       afficher en fonction de l'évènement
306
307 20367931 Thomas ANDREJAK
            if event.active :
308 52661754 Thomas ANDREJAK
                events.append([
309 20367931 Thomas ANDREJAK
                    event,
310
                    {'class': class_tr[i%2]},
311 52661754 Thomas ANDREJAK
                    {'class' : self.bouton_severity[event.severity] + \
312
                            self.class_ack[event.status]},
313
                    {'class' : self.bouton_severity[event.severity] + \
314
                            self.class_ack[event.status] },
315 95743443 Thomas ANDREJAK
                    {'src' : '/images/%s2.png' % \
316 52661754 Thomas ANDREJAK
                            self.bouton_severity[event.severity].upper()},
317
                    self.format_events_img_statu(event),
318
                    [[j.__show__(req), j.style] for j in self.plugin]
319 20367931 Thomas ANDREJAK
                    ])
320
            else :
321 52661754 Thomas ANDREJAK
                events.append([
322 20367931 Thomas ANDREJAK
                    event,
323
                    {'class': class_tr[i%2]},
324 52661754 Thomas ANDREJAK
                    {'class' : self.bouton_severity[event.severity] + \
325
                            self.class_ack[event.status] },
326 20367931 Thomas ANDREJAK
                    {'class' : 'Cleared' + self.class_ack[event.status] },
327 95743443 Thomas ANDREJAK
                    {'src' : '/images/%s2.png' % \
328 52661754 Thomas ANDREJAK
                            self.bouton_severity[event.severity].upper()},
329
                    self.format_events_img_statu(event),
330
                    [[j.__show__(req), j.style] for j in self.plugin]
331 20367931 Thomas ANDREJAK
                    ])
332 52661754 Thomas ANDREJAK
            i = i + 1
333
334
        # On sauvegarde la liste précédemment créée puis rempli
335
        # le TmplContext
336
337
        self.events = events
338 20367931 Thomas ANDREJAK
        self.idevents = ids
339
340 52661754 Thomas ANDREJAK
    def format_history (self):
341 20367931 Thomas ANDREJAK
        
342
        """
343
        Formate les historiques correspondant aux évènements sélectionnés
344
        pour un affichage simple du résultat par Genshi.
345
        On génère une liste de liste, chaqu'une étant la description de l'affichage pour un
346
        historique donné.
347
        """
348
349 52661754 Thomas ANDREJAK
        history = DBSession.query(EventHistory
350
                ).filter(EventHistory.idevent.in_(self.idevents)
351
                ).order_by(desc(EventHistory.timestamp)
352
                ).order_by(desc(EventHistory.idhistory))
353
354 20367931 Thomas ANDREJAK
        if history.count() == 0:
355 52661754 Thomas ANDREJAK
            self.hist = []
356 20367931 Thomas ANDREJAK
            return
357 52661754 Thomas ANDREJAK
        hists = []
358 20367931 Thomas ANDREJAK
        i = 0
359 52661754 Thomas ANDREJAK
        class_tr = ['odd', 'even']
360 20367931 Thomas ANDREJAK
        hostname = self.events[1][0].hostname
361
        servicename = self.events[1][0].servicename
362 52661754 Thomas ANDREJAK
363
        for hist in history :
364
365 20367931 Thomas ANDREJAK
            # La liste pour l'historique actuel comporte dans l'ordre :
366
            #   Son identifiant
367
            #   Son nom d'hôte
368
            #   Son nom de service
369
            #   Le moment où il a été généré
370
            #   Qui l'a généré
371
            #   Le type d'action qui a été appliqué
372
            #   La sévérité de l'action si besoin est
373
            #   Le détail de l'action
374 52661754 Thomas ANDREJAK
            #   La classe à appliquer à la ligne (permet d'alterner
375
            #       les couleurs)
376 20367931 Thomas ANDREJAK
            #   La classe de la sévérité s'il y a
377 52661754 Thomas ANDREJAK
378
            if hist.value :
379
                hists.append([
380
                    hist.idhistory,
381 20367931 Thomas ANDREJAK
                    hostname,
382
                    servicename,
383 52661754 Thomas ANDREJAK
                    hist.timestamp,
384
                    hist.username,
385
                    hist.type_action,
386
                    self.severity[min(int(hist.value),7)],
387
                    hist.text,
388 20367931 Thomas ANDREJAK
                    {'class' : class_tr[i%2]},
389 52661754 Thomas ANDREJAK
                    {'class':self.class_severity[min(int(hist.value),7)]}
390 20367931 Thomas ANDREJAK
                ])
391
            else:
392 52661754 Thomas ANDREJAK
                hists.append([
393
                    hist.idhistory,
394 20367931 Thomas ANDREJAK
                    hostname,
395
                    servicename,
396 52661754 Thomas ANDREJAK
                    hist.timestamp,
397
                    hist.username,
398
                    hist.type_action,
399 20367931 Thomas ANDREJAK
                    self.severity[0],
400 52661754 Thomas ANDREJAK
                    hist.text,
401 20367931 Thomas ANDREJAK
                    {'class' : class_tr[i%2]},
402
                    {'class':self.class_severity[0]}
403
                ])    
404 52661754 Thomas ANDREJAK
            i = i + 1
405 20367931 Thomas ANDREJAK
        
406 52661754 Thomas ANDREJAK
        self.hist = hists
407 20367931 Thomas ANDREJAK
408 52661754 Thomas ANDREJAK
    def generate_tmpl_context(self):
409
        
410 20367931 Thomas ANDREJAK
        """
411 52661754 Thomas ANDREJAK
        Génère et peuple la variable tmpl_context avec les Dialogs et
412
        formulaires nécessaire au fonctionnement de Vigiboard
413 20367931 Thomas ANDREJAK
        """
414 52661754 Thomas ANDREJAK
415 20367931 Thomas ANDREJAK
        # Dialogue d'édition
416 35cea70e Thomas ANDREJAK
        tmpl_context.edit_event_form = EditEventForm('edit_event_form',
417 52661754 Thomas ANDREJAK
                action=url('/vigiboard/update'))
418
        tmpl_context.edit_eventdialog = JQueryUIDialog(id='Edit_EventsDialog',
419
                autoOpen=False,title=_('Edit Event'))
420 20367931 Thomas ANDREJAK
    
421
        # Dialogue de recherche
422 35cea70e Thomas ANDREJAK
        tmpl_context.search_form = SearchForm('search_form',
423 52661754 Thomas ANDREJAK
                action=url('/vigiboard'))
424
        tmpl_context.searchdialog = JQueryUIDialog(id='SearchDialog',
425
                autoOpen=False,title=_('Search Event'))
426 20367931 Thomas ANDREJAK
        
427
        # Dialogue de détail d'un évènement
428 52661754 Thomas ANDREJAK
        tmpl_context.historydialog = JQueryUIDialog(id='HistoryDialog',
429
                autoOpen=False,title=_('History'))