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')) |