vigigraph / vigigraph / controllers / rpc.py @ e2dbeada
History | View | Annotate | Download (29.2 KB)
1 |
# -*- coding: utf-8 -*-
|
---|---|
2 |
"""RPC controller for the combobox of vigigraph"""
|
3 |
|
4 |
import time, urlparse |
5 |
import urllib |
6 |
import urllib2 |
7 |
import logging |
8 |
|
9 |
# La fonction parse_qsl a été déplacée dans Python 2.6.
|
10 |
try:
|
11 |
from urlparse import parse_qsl |
12 |
except ImportError: |
13 |
from cgi import parse_qsl |
14 |
|
15 |
from pylons.i18n import ugettext as _, lazy_ugettext as l_ |
16 |
from tg import expose, response, request, redirect, tmpl_context, \ |
17 |
config, url, exceptions, validate, flash |
18 |
from repoze.what.predicates import not_anonymous |
19 |
from formencode import validators, schema |
20 |
|
21 |
from sqlalchemy.orm import aliased |
22 |
from sqlalchemy import or_ |
23 |
|
24 |
from vigigraph.lib.base import BaseController |
25 |
|
26 |
from vigilo.models.session import DBSession |
27 |
from vigilo.models.tables import LowLevelService, Host, User |
28 |
from vigilo.models.tables import SupItemGroup |
29 |
from vigilo.models.tables import PerfDataSource |
30 |
from vigilo.models.tables import Graph, GraphGroup |
31 |
from vigilo.models.tables import Ventilation, VigiloServer, Application |
32 |
from vigilo.models.tables.grouphierarchy import GroupHierarchy |
33 |
|
34 |
from vigilo.models.tables.secondary_tables import SUPITEM_GROUP_TABLE |
35 |
from vigilo.models.tables.secondary_tables import GRAPH_GROUP_TABLE |
36 |
from vigilo.models.tables.secondary_tables import GRAPH_PERFDATASOURCE_TABLE |
37 |
from vigilo.models.functions import sql_escape_like |
38 |
|
39 |
from vigilo.turbogears.helpers import get_current_user |
40 |
|
41 |
from vigigraph.widgets.searchhostform import SearchHostForm |
42 |
|
43 |
LOGGER = logging.getLogger(__name__) |
44 |
|
45 |
__all__ = ['RpcController']
|
46 |
|
47 |
|
48 |
# pylint: disable-msg=R0201
|
49 |
class RpcController(BaseController): |
50 |
"""
|
51 |
Class Controleur TurboGears
|
52 |
"""
|
53 |
|
54 |
# L'accès à ce contrôleur nécessite d'être identifié.
|
55 |
allow_only = not_anonymous(l_("You need to be authenticated"))
|
56 |
|
57 |
presets = [ |
58 |
{"caption" : _("Last %d hours") % 12, "duration" : 43200}, |
59 |
{"caption" : _("Last %d hours") % 24, "duration" : 86400}, |
60 |
{"caption" : _("Last %d days") % 2, "duration" : 192800}, |
61 |
{"caption" : _("Last %d days") % 7, "duration" : 604800}, |
62 |
{"caption" : _("Last %d days") % 14, "duration" : 1209600}, |
63 |
{"caption" : _("Last %d months") % 3, "duration" : 86400 * 31 * 3}, |
64 |
{"caption" : _("Last %d months") % 6, "duration" : 86400 * 183}, |
65 |
{"caption" : _("Last year"), "duration" : 86400 * 365}, |
66 |
] |
67 |
|
68 |
def process_form_errors(self, *argv, **kwargv): |
69 |
"""
|
70 |
Gestion des erreurs de validation : On affiche les erreurs
|
71 |
puis on redirige vers la dernière page accédée.
|
72 |
"""
|
73 |
for k in tmpl_context.form_errors: |
74 |
flash("'%s': %s" % (k, tmpl_context.form_errors[k]), 'error') |
75 |
redirect(request.environ.get('HTTP_REFERER', '/')) |
76 |
|
77 |
@expose('json') |
78 |
def maingroups(self, nocache=None): |
79 |
"""
|
80 |
Determination des groupes principaux (sans parent)
|
81 |
|
82 |
@return: Dictionnaire dont la clé "items" contient une liste
|
83 |
de tuples contenant le nom et l'ID des groupes d'éléments
|
84 |
au sommet de la hiérarchie et auquels l'utilisateur a accès.
|
85 |
@rtype: C{dict}
|
86 |
@note: L'ID des groupes est converti en chaîne de caractères
|
87 |
dans le résultat.
|
88 |
"""
|
89 |
user = get_current_user() |
90 |
if user is None: |
91 |
return dict(items=[]) |
92 |
supitemgroups = user.supitemgroups() |
93 |
|
94 |
groups_with_parents = DBSession.query( |
95 |
GroupHierarchy.idparent, |
96 |
).distinct( |
97 |
).filter(GroupHierarchy.idchild.in_(supitemgroups) |
98 |
).all() |
99 |
groups_with_parents = [g.idparent for g in groups_with_parents] |
100 |
|
101 |
children = DBSession.query( |
102 |
SupItemGroup |
103 |
).distinct( |
104 |
).join( |
105 |
(GroupHierarchy, GroupHierarchy.idchild == SupItemGroup.idgroup) |
106 |
).filter(GroupHierarchy.hops > 0)
|
107 |
|
108 |
topgroups = DBSession.query( |
109 |
SupItemGroup, |
110 |
).filter(SupItemGroup.idgroup.in_(groups_with_parents) |
111 |
).except_(children).order_by(SupItemGroup.name).all() |
112 |
topgroups = [(sig.name, str(sig.idgroup)) for sig in topgroups] |
113 |
return dict(items=topgroups) |
114 |
|
115 |
class HostgroupsSchema(schema.Schema): |
116 |
maingroupid = validators.Int(not_empty=True)
|
117 |
nocache = validators.String(if_missing=None)
|
118 |
|
119 |
# @TODO définir un error_handler différent pour remonter l'erreur via JS.
|
120 |
@validate(
|
121 |
validators=HostgroupsSchema(), |
122 |
error_handler=process_form_errors) |
123 |
@expose('json') |
124 |
def hostgroups(self, maingroupid, nocache): |
125 |
"""
|
126 |
Determination des groupes associes au groupe parent
|
127 |
dont identificateur = argument
|
128 |
|
129 |
@param maingroupid: identificateur d un groupe principal
|
130 |
@type maingroupid: C{int}
|
131 |
|
132 |
@return: Dictionnaire dont la clé "items" contient une liste
|
133 |
de tuples avec le nom et l'ID des groupes d'éléments
|
134 |
auxquels l'utilisateur a accès.
|
135 |
@rtype: C{dict}
|
136 |
@note: L'ID des groupes est converti en chaîne de caractères
|
137 |
dans le résultat.
|
138 |
"""
|
139 |
user = get_current_user() |
140 |
if user is None: |
141 |
return dict(items=[]) |
142 |
supitemgroups = user.supitemgroups() |
143 |
|
144 |
hostgroups = DBSession.query( |
145 |
SupItemGroup.name, |
146 |
SupItemGroup.idgroup, |
147 |
).distinct().join( |
148 |
(GroupHierarchy, GroupHierarchy.idchild == \ |
149 |
SupItemGroup.idgroup), |
150 |
).filter(GroupHierarchy.idparent == maingroupid |
151 |
).filter(GroupHierarchy.hops == 1
|
152 |
).filter(SupItemGroup.idgroup.in_(supitemgroups) |
153 |
).order_by( |
154 |
SupItemGroup.name.asc(), |
155 |
).all() |
156 |
hostgroups = [(hg.name, str(hg.idgroup)) for hg in hostgroups] |
157 |
hostgroups.insert(0, (_('No subgroup'), str(maingroupid))) |
158 |
return dict(items=hostgroups) |
159 |
|
160 |
class HostsSchema(schema.Schema): |
161 |
othergroupid = validators.Int(not_empty=True)
|
162 |
nocache = validators.String(if_missing=None)
|
163 |
|
164 |
# @TODO définir un error_handler différent pour remonter l'erreur via JS.
|
165 |
@validate(
|
166 |
validators=HostsSchema(), |
167 |
error_handler=process_form_errors) |
168 |
@expose('json') |
169 |
def hosts(self, othergroupid, nocache): |
170 |
"""
|
171 |
Determination des hotes associes au groupe
|
172 |
dont identificateur = argument
|
173 |
|
174 |
@param othergroupid : identificateur d un groupe
|
175 |
@type othergroupid : int
|
176 |
|
177 |
@return: hotes
|
178 |
@rtype: document json (sous forme de dict)
|
179 |
"""
|
180 |
user = get_current_user() |
181 |
if user is None: |
182 |
return dict(items=[]) |
183 |
supitemgroups = user.supitemgroups() |
184 |
|
185 |
groups_with_parents = DBSession.query( |
186 |
GroupHierarchy.idparent, |
187 |
).distinct( |
188 |
).filter(GroupHierarchy.idchild.in_(supitemgroups) |
189 |
).all() |
190 |
groups_with_parents = [g.idparent for g in groups_with_parents] |
191 |
|
192 |
hosts = DBSession.query( |
193 |
Host.name, |
194 |
Host.idhost, |
195 |
).distinct( |
196 |
).outerjoin( |
197 |
(LowLevelService, LowLevelService.idhost == Host.idhost), |
198 |
).join( |
199 |
(SUPITEM_GROUP_TABLE, or_( |
200 |
SUPITEM_GROUP_TABLE.c.idsupitem == Host.idhost, |
201 |
SUPITEM_GROUP_TABLE.c.idsupitem == |
202 |
LowLevelService.idservice, |
203 |
)), |
204 |
).filter(SUPITEM_GROUP_TABLE.c.idgroup == othergroupid |
205 |
).filter(SUPITEM_GROUP_TABLE.c.idgroup.in_(groups_with_parents) |
206 |
).order_by( |
207 |
Host.name.asc(), |
208 |
).all() |
209 |
|
210 |
hosts = [(h.name, str(h.idhost)) for h in hosts] |
211 |
return dict(items=hosts) |
212 |
|
213 |
class GraphGroupsSchema(schema.Schema): |
214 |
idhost = validators.Int(not_empty=True)
|
215 |
nocache = validators.String(if_missing=None)
|
216 |
|
217 |
# @TODO définir un error_handler différent pour remonter l'erreur via JS.
|
218 |
@validate(
|
219 |
validators=GraphGroupsSchema(), |
220 |
error_handler=process_form_errors) |
221 |
@expose('json') |
222 |
def graphgroups(self, idhost, nocache): |
223 |
"""
|
224 |
Determination des groupes de graphes associes a l hote
|
225 |
dont identificateur = argument
|
226 |
|
227 |
@param idhost : identificateur d un hote
|
228 |
@type idhost : int
|
229 |
|
230 |
@return: groupes de service
|
231 |
@rtype: document json (sous forme de dict)
|
232 |
"""
|
233 |
user = get_current_user() |
234 |
if user is None: |
235 |
return dict(items=[]) |
236 |
supitemgroups = user.supitemgroups() |
237 |
|
238 |
graphgroups = DBSession.query( |
239 |
GraphGroup.name, |
240 |
GraphGroup.idgroup, |
241 |
).distinct( |
242 |
).join( |
243 |
(GRAPH_GROUP_TABLE, GRAPH_GROUP_TABLE.c.idgroup == \ |
244 |
GraphGroup.idgroup), |
245 |
(Graph, Graph.idgraph == GRAPH_GROUP_TABLE.c.idgraph), |
246 |
(GRAPH_PERFDATASOURCE_TABLE, \ |
247 |
GRAPH_PERFDATASOURCE_TABLE.c.idgraph == Graph.idgraph), |
248 |
(PerfDataSource, PerfDataSource.idperfdatasource == \ |
249 |
GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource), |
250 |
(LowLevelService, LowLevelService.idservice == \ |
251 |
PerfDataSource.idservice), |
252 |
(SUPITEM_GROUP_TABLE, or_( |
253 |
SUPITEM_GROUP_TABLE.c.idsupitem == LowLevelService.idhost, |
254 |
SUPITEM_GROUP_TABLE.c.idsupitem == LowLevelService.idservice, |
255 |
)), |
256 |
).filter(LowLevelService.idhost == idhost |
257 |
).filter(SUPITEM_GROUP_TABLE.c.idgroup.in_(supitemgroups) |
258 |
).order_by( |
259 |
GraphGroup.name.asc() |
260 |
).all() |
261 |
|
262 |
graphgroups = [(gg.name, str(gg.idgroup)) for gg in graphgroups] |
263 |
return dict(items=graphgroups) |
264 |
|
265 |
class GraphsSchema(schema.Schema): |
266 |
idgraphgroup = validators.Int(not_empty=True)
|
267 |
idhost = validators.Int(not_empty=True)
|
268 |
nocache = validators.String(if_missing=None)
|
269 |
|
270 |
# @TODO définir un error_handler différent pour remonter l'erreur via JS.
|
271 |
@validate(
|
272 |
validators=GraphsSchema(), |
273 |
error_handler=process_form_errors) |
274 |
@expose('json') |
275 |
def graphs(self, idgraphgroup, idhost, nocache): |
276 |
"""
|
277 |
Determination des graphes
|
278 |
avec un service dont identificateur = argument
|
279 |
|
280 |
@param idgraph : identificateur d un service
|
281 |
@type idgraph : int
|
282 |
|
283 |
@return: graphes
|
284 |
@rtype: document json (sous forme de dict)
|
285 |
"""
|
286 |
user = get_current_user() |
287 |
if user is None: |
288 |
return dict(items=[]) |
289 |
supitemgroups = user.supitemgroups() |
290 |
|
291 |
graphs = DBSession.query( |
292 |
Graph.name, |
293 |
Graph.idgraph, |
294 |
).distinct().join( |
295 |
(GRAPH_GROUP_TABLE, GRAPH_GROUP_TABLE.c.idgraph == \ |
296 |
Graph.idgraph), |
297 |
(GraphGroup, GraphGroup.idgroup == \ |
298 |
GRAPH_GROUP_TABLE.c.idgroup), |
299 |
(GRAPH_PERFDATASOURCE_TABLE, \ |
300 |
GRAPH_PERFDATASOURCE_TABLE.c.idgraph == Graph.idgraph), |
301 |
(PerfDataSource, PerfDataSource.idperfdatasource == \ |
302 |
GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource), |
303 |
(LowLevelService, LowLevelService.idservice == \ |
304 |
PerfDataSource.idservice), |
305 |
(SUPITEM_GROUP_TABLE, or_( |
306 |
SUPITEM_GROUP_TABLE.c.idsupitem == LowLevelService.idhost, |
307 |
SUPITEM_GROUP_TABLE.c.idsupitem == LowLevelService.idservice, |
308 |
)), |
309 |
).filter(GraphGroup.idgroup == idgraphgroup |
310 |
).filter(LowLevelService.idhost == idhost |
311 |
).filter(SUPITEM_GROUP_TABLE.c.idgroup.in_(supitemgroups) |
312 |
).order_by( |
313 |
Graph.name.asc() |
314 |
).all() |
315 |
|
316 |
graphs = [(pds.name, str(pds.idgraph)) for pds in graphs] |
317 |
return dict(items=graphs) |
318 |
|
319 |
class SearchHostAndGraphSchema(schema.Schema): |
320 |
host = validators.String(if_missing=None)
|
321 |
graph = validators.String(if_missing=None)
|
322 |
|
323 |
# @TODO définir un error_handler différent pour remonter l'erreur via JS.
|
324 |
@validate(
|
325 |
validators=SearchHostAndGraphSchema(), |
326 |
error_handler=process_form_errors) |
327 |
@expose('json') |
328 |
def searchHostAndGraph(self, host, graph): |
329 |
"""
|
330 |
Determination des couples (hote-graphe) repondant aux criteres de
|
331 |
recherche sur hote et/ou graphe.
|
332 |
|
333 |
Un critere peut correspondre a un intitule complet hote ou graphe
|
334 |
ou a un extrait.
|
335 |
|
336 |
@param kwargs : arguments nommes
|
337 |
@type kwargs : dict
|
338 |
( arguments nommes -> host et graphe )
|
339 |
|
340 |
@return: couples hote-graphe
|
341 |
@rtype: document json (sous forme de dict)
|
342 |
"""
|
343 |
user = get_current_user() |
344 |
if user is None: |
345 |
return dict(items=[]) |
346 |
supitemgroups = user.supitemgroups() |
347 |
|
348 |
items = [] |
349 |
|
350 |
# On a un nom d'indicateur, mais pas de nom d'hôte,
|
351 |
# on considère que l'utilisateur veut tous les indicateurs
|
352 |
# correspondant au motif, quel que soit l'hôte.
|
353 |
if graph is not None: |
354 |
if host is None: |
355 |
host = '*'
|
356 |
|
357 |
host = sql_escape_like(host) |
358 |
graph = sql_escape_like(graph) |
359 |
|
360 |
items = DBSession.query( |
361 |
Host.name.label('hostname'),
|
362 |
Graph.name.label('graphname'),
|
363 |
).distinct().join( |
364 |
(LowLevelService, LowLevelService.idhost == Host.idhost), |
365 |
(PerfDataSource, PerfDataSource.idservice == \ |
366 |
LowLevelService.idservice), |
367 |
(GRAPH_PERFDATASOURCE_TABLE, \ |
368 |
GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource == \ |
369 |
PerfDataSource.idperfdatasource), |
370 |
(Graph, Graph.idgraph == \ |
371 |
GRAPH_PERFDATASOURCE_TABLE.c.idgraph), |
372 |
(SUPITEM_GROUP_TABLE, or_( |
373 |
SUPITEM_GROUP_TABLE.c.idsupitem == Host.idhost, |
374 |
SUPITEM_GROUP_TABLE.c.idsupitem == LowLevelService.idservice, |
375 |
)), |
376 |
).filter(Host.name.ilike('%' + host + '%') |
377 |
).filter(Graph.name.ilike('%' + graph + '%') |
378 |
).filter(SUPITEM_GROUP_TABLE.c.idgroup.in_(supitemgroups) |
379 |
).order_by( |
380 |
Host.name.asc(), |
381 |
Graph.name.asc(), |
382 |
) |
383 |
|
384 |
# On a ni hôte, ni indicateur. On renvoie une liste vide.
|
385 |
# Si l'utilisateur voulait vraiment quelque chose,
|
386 |
# il n'avait qu'à le demander.
|
387 |
elif host is None: |
388 |
return []
|
389 |
|
390 |
# Sinon, on a juste un motif pour un hôte.
|
391 |
# On renvoie la liste des hôtes correspondant.
|
392 |
else:
|
393 |
host = sql_escape_like(host) |
394 |
items = DBSession.query( |
395 |
Host.name.label('hostname'),
|
396 |
).join( |
397 |
(SUPITEM_GROUP_TABLE, SUPITEM_GROUP_TABLE.c.idsupitem == \ |
398 |
Host.idhost), |
399 |
).filter(Host.name.ilike('%' + host + '%') |
400 |
).filter(SUPITEM_GROUP_TABLE.c.idsupitem.in_(supitemgroups) |
401 |
).order_by(Host.name.asc()) |
402 |
|
403 |
items = items.limit(100).all()
|
404 |
if graph is None: |
405 |
items = [(item.hostname, "") for item in items] |
406 |
else:
|
407 |
items = [(item.hostname, item.graphname) for item in items] |
408 |
return dict(items=items) |
409 |
|
410 |
class SelectHostAndGraphSchema(schema.Schema): |
411 |
host = validators.String(if_missing=None)
|
412 |
graph = validators.String(if_missing=None)
|
413 |
nocache = validators.String(if_missing=None)
|
414 |
|
415 |
# @TODO définir un error_handler différent pour remonter l'erreur via JS.
|
416 |
@validate(
|
417 |
validators=SearchHostAndGraphSchema(), |
418 |
error_handler=process_form_errors) |
419 |
@expose('json') |
420 |
def selectHostAndGraph(self, host, graph, nocache): |
421 |
"""
|
422 |
Renvoie les valeurs à sélectionner dans les comboboxes
|
423 |
de VigiGraph pour afficher les données de l'hôte ou du
|
424 |
couple hôte/graphe sélectionné.
|
425 |
|
426 |
La clé "items" du dictionnaire renvoyé contient une liste avec
|
427 |
2 éléments, chacun de ces éléments étant lui-même une liste.
|
428 |
La 1ère liste contient les noms des groupes d'hôtes à sélectionner.
|
429 |
La 2ème liste contient la liste des groupes de graphes à sélectionner.
|
430 |
|
431 |
Pour le moment, la 2ème liste contiendra au plus 1 élément car
|
432 |
les groupes de graphes ne sont pas récursifs. L'utilisation d'une
|
433 |
liste permet d'assurer facilement une évolution vers des groupes
|
434 |
de graphes récursifs.
|
435 |
"""
|
436 |
|
437 |
# Ce cas ne devrait pas se produire, mais on tente
|
438 |
# d'avoir un comportement gracieux malgré tout.
|
439 |
if (not host) and (not graph): |
440 |
return dict(items=[[], []]) |
441 |
|
442 |
# Groupe principal de l'hôte.
|
443 |
mhg = aliased(SupItemGroup) |
444 |
# Groupe secondaire de l'hôte.
|
445 |
shg = aliased(SupItemGroup) |
446 |
|
447 |
selected_hostgroups = [] |
448 |
selected_graphgroups = [] |
449 |
|
450 |
# @TODO: ajouter la gestion des permissions au code qui suit.
|
451 |
# Pour le moment, la récupération de idsupitemgroup & idgraphgroup
|
452 |
# ne prend pas en compte les permissions réelles de l'utilisateur.
|
453 |
|
454 |
if host:
|
455 |
# Sélectionne l'identifiant du premier SupItemGroup auquel
|
456 |
# l'utilisateur a accès et auquel l'hôte donné appartient.
|
457 |
idsupitemgroup = DBSession.query( |
458 |
SupItemGroup.idgroup, |
459 |
).distinct().join( |
460 |
(SUPITEM_GROUP_TABLE, SUPITEM_GROUP_TABLE.c.idgroup == \ |
461 |
SupItemGroup.idgroup), |
462 |
(Host, Host.idhost == SUPITEM_GROUP_TABLE.c.idsupitem), |
463 |
).filter(Host.name == host |
464 |
).scalar() |
465 |
|
466 |
# Si on a trouvé un tel groupe, on renvoie les noms des
|
467 |
# groupes de la hiérarchie à sélectionner pour arriver
|
468 |
# à celui-ci.
|
469 |
if idsupitemgroup is not None: |
470 |
selected_hostgroups = DBSession.query( |
471 |
SupItemGroup.name, |
472 |
).distinct().join( |
473 |
(GroupHierarchy, GroupHierarchy.idparent == \ |
474 |
GraphGroup.idgroup), |
475 |
).filter(GroupHierarchy.idchild == idsupitemgroup |
476 |
).order_by( |
477 |
GroupHierarchy.hops.desc() |
478 |
).all() |
479 |
|
480 |
if graph:
|
481 |
# Le principe est le même que pour l'hôte, en considérant
|
482 |
# cette fois les GraphGroup à la place des SupItemGroup.
|
483 |
idgraphgroup = DBSession.query( |
484 |
GraphGroup.idgroup, |
485 |
).distinct().join( |
486 |
(GRAPH_GROUP_TABLE, GRAPH_GROUP_TABLE.c.idgroup == \ |
487 |
GraphGroup.idgroup), |
488 |
(Graph, Graph.idgraph == GRAPH_GROUP_TABLE.c.idgraph), |
489 |
).filter(Graph.name == graph |
490 |
).scalar() |
491 |
|
492 |
# Même principe que pour l'hôte.
|
493 |
if idgraphgroup is not None: |
494 |
selected_graphgroups = DBSession.query( |
495 |
GraphGroup.name, |
496 |
).distinct().join( |
497 |
(GroupHierarchy, GroupHierarchy.idparent == \ |
498 |
GraphGroup.idgroup), |
499 |
).filter(GroupHierarchy.idchild == idgraphgroup |
500 |
).order_by( |
501 |
GroupHierarchy.hops.desc() |
502 |
).all() |
503 |
|
504 |
hostgroups = [hg.name for hg in selected_hostgroups] |
505 |
graphgroups = [gg.name for gg in selected_graphgroups] |
506 |
return dict(items=[hostgroups, graphgroups]) |
507 |
|
508 |
@expose('graphslist.html') |
509 |
def graphsList(self, nocache=None, **kwargs): |
510 |
"""
|
511 |
Generation document avec url des graphes affiches
|
512 |
(pour l impression )
|
513 |
|
514 |
@param kwargs : arguments nommes
|
515 |
@type kwargs : dict
|
516 |
|
517 |
@return: url de graphes
|
518 |
@rtype: document html
|
519 |
"""
|
520 |
if not kwargs: |
521 |
return dict(graphslist=[]) |
522 |
|
523 |
# TRANSLATORS: Format Python de date/heure, lisible par un humain.
|
524 |
format = _("%a, %d %b %Y %H:%M:%S")
|
525 |
graphslist = [] |
526 |
for url in kwargs.itervalues(): |
527 |
parts = urlparse.urlparse(url) |
528 |
params = dict(parse_qsl(parts.query))
|
529 |
|
530 |
graph = {} |
531 |
start = int(params.get('start', time.time() - 86400)) |
532 |
duration = int(params.get('duration', 86400)) |
533 |
|
534 |
graph['graph'] = params.get('graphtemplate') |
535 |
graph['start_date'] = time.strftime(format, time.localtime(start))
|
536 |
graph['end_date'] = time.strftime(format,
|
537 |
time.localtime(start + duration)) |
538 |
graph['img_src'] = url
|
539 |
graph['host'] = params['host'] |
540 |
graphslist.append(graph) |
541 |
return dict(graphslist=graphslist) |
542 |
|
543 |
@expose(content_type='text/plain') |
544 |
def tempoDelayRefresh(self, nocache=None): |
545 |
"""
|
546 |
Determination valeur temporisation pour le rafraichissement automatique
|
547 |
d un graphe
|
548 |
|
549 |
@return: valeur de temporisation
|
550 |
@rtype: C{str}
|
551 |
"""
|
552 |
|
553 |
try:
|
554 |
delay = int(config['delay_refresh']) |
555 |
except ValueError, KeyError: |
556 |
delay = 36000
|
557 |
return str(delay) |
558 |
|
559 |
class GetIndicatorsSchema(schema.Schema): |
560 |
graph = validators.String(not_empty=True)
|
561 |
nocache = validators.String(if_missing=None)
|
562 |
|
563 |
# @TODO définir un error_handler différent pour remonter l'erreur via JS.
|
564 |
@validate(
|
565 |
validators=GetIndicatorsSchema(), |
566 |
error_handler=process_form_errors) |
567 |
@expose('json') |
568 |
def getIndicators(self, graph, nocache): |
569 |
"""
|
570 |
Liste d indicateurs associes a un graphe
|
571 |
|
572 |
@param graph : graphe
|
573 |
@type graph : C{str}
|
574 |
|
575 |
@return: dictionnaire des indicateurs d un graphe
|
576 |
@rtype: document json (sous forme de dict)
|
577 |
"""
|
578 |
|
579 |
indicators = self.getListIndicators(graph)
|
580 |
indicators = [(ind.name, ind.idperfdatasource) for ind in indicators] |
581 |
return dict(items=indicators) |
582 |
|
583 |
|
584 |
class FullHostPageSchema(schema.Schema): |
585 |
host = validators.String(not_empty=True)
|
586 |
start = validators.Int(if_missing=None)
|
587 |
duration = validators.Int(if_missing=86400)
|
588 |
|
589 |
# VIGILO_EXIG_VIGILO_PERF_0010:Visualisation globale des graphes
|
590 |
@validate(
|
591 |
validators=FullHostPageSchema(), |
592 |
error_handler=process_form_errors) |
593 |
@expose('fullhostpage.html') |
594 |
def fullHostPage(self, host, start=None, duration=86400): |
595 |
"""
|
596 |
Affichage de l'ensemble des graphes associes a un hote
|
597 |
* d apres les donnees RRD
|
598 |
* avec une date-heure de debut
|
599 |
* pour une plage de temps
|
600 |
|
601 |
@param host : hôte
|
602 |
@type host : C{str}
|
603 |
@param start : date-heure de debut des donnees
|
604 |
@type start : C{str}
|
605 |
@param duration : plage de temps des données
|
606 |
@type duration : C{str}
|
607 |
(parametre optionnel, initialise a 86400 = plage de 1 jour)
|
608 |
|
609 |
@return: page avec les images des graphes et boutons de deplacement dans le temps
|
610 |
@rtype: page html
|
611 |
"""
|
612 |
|
613 |
if start is None: |
614 |
start = int(time.time()) - int(duration) |
615 |
|
616 |
# @TODO définir des validateurs sur les paramètres
|
617 |
start = int(start)
|
618 |
duration = int(duration)
|
619 |
|
620 |
user = get_current_user() |
621 |
if user is None: |
622 |
return dict(host=host, start=start, duration=duration, |
623 |
presets=self.presets, graphs=[])
|
624 |
supitemgroups = user.supitemgroups() |
625 |
|
626 |
# Récupération de la liste des noms des graphes,
|
627 |
# avec vérification des permissions de l'utilisateur.
|
628 |
graphs = DBSession.query( |
629 |
Graph.name |
630 |
).distinct( |
631 |
).join( |
632 |
(GRAPH_PERFDATASOURCE_TABLE, |
633 |
GRAPH_PERFDATASOURCE_TABLE.c.idgraph == Graph.idgraph), |
634 |
(PerfDataSource, PerfDataSource.idperfdatasource == |
635 |
GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource), |
636 |
(LowLevelService, LowLevelService.idservice == |
637 |
PerfDataSource.idservice), |
638 |
).outerjoin( |
639 |
(Host, Host.idhost == LowLevelService.idhost), |
640 |
).join( |
641 |
(SUPITEM_GROUP_TABLE, or_( |
642 |
SUPITEM_GROUP_TABLE.c.idsupitem == |
643 |
LowLevelService.idservice, |
644 |
SUPITEM_GROUP_TABLE.c.idsupitem == Host.idhost, |
645 |
)) |
646 |
).filter(SUPITEM_GROUP_TABLE.c.idgroup.in_(supitemgroups) |
647 |
).all() |
648 |
|
649 |
return dict(host=host, start=start, duration=duration, |
650 |
presets=self.presets, graphs=graphs)
|
651 |
|
652 |
|
653 |
class SingleGraphSchema(schema.Schema): |
654 |
host = validators.String(not_empty=True)
|
655 |
graph = validators.String(not_empty=True)
|
656 |
start = validators.Int(if_missing=None)
|
657 |
duration = validators.Int(if_missing=86400)
|
658 |
|
659 |
# VIGILO_EXIG_VIGILO_PERF_0020:Visualisation unitaire des graphes
|
660 |
@validate(
|
661 |
validators=SingleGraphSchema(), |
662 |
error_handler=process_form_errors) |
663 |
@expose('singlegraph.html') |
664 |
def singleGraph(self, host, graph, start, duration): |
665 |
"""
|
666 |
Affichage d un graphe associe a un hote et un graphe
|
667 |
* d apres les donnees RRD
|
668 |
* avec une date-heure de debut
|
669 |
* pour une plage de temps
|
670 |
|
671 |
@param host : hôte
|
672 |
@type host : C{str}
|
673 |
@param graph : graphe
|
674 |
@type graph : C{str}
|
675 |
@param start : date-heure de debut des donnees
|
676 |
@type start : C{str}
|
677 |
@param duration : plage de temps des données
|
678 |
@type duration : C{str}
|
679 |
(parametre optionnel, initialise a 86400 = plage de 1 jour)
|
680 |
|
681 |
@return: page avec l image du graphe et boutons de deplacement dans le temps
|
682 |
@rtype: page html
|
683 |
"""
|
684 |
|
685 |
if start is None: |
686 |
start = int(time.time()) - int(duration) |
687 |
|
688 |
# @TODO définir des validateurs sur les paramètres
|
689 |
start = int(start)
|
690 |
duration = int(duration)
|
691 |
|
692 |
return dict(host=host, graph=graph, start=start, duration=duration, \ |
693 |
presets=self.presets)
|
694 |
|
695 |
@expose('searchhostform.html') |
696 |
def searchHostForm(self): |
697 |
"""
|
698 |
Formulaire de recherche sur les hotes
|
699 |
|
700 |
@return: page avec formulaire de recherche
|
701 |
@rtype: page html
|
702 |
"""
|
703 |
searchhostform = SearchHostForm('search_host_form', \
|
704 |
submit_text=None)
|
705 |
|
706 |
return dict(searchhostform=searchhostform) |
707 |
|
708 |
class SearchHostSchema(schema.Schema): |
709 |
query = validators.String(if_missing=None)
|
710 |
|
711 |
@validate(
|
712 |
validators=SearchHostSchema(), |
713 |
error_handler=process_form_errors) |
714 |
@expose('searchhost.html') |
715 |
def searchHost(self, query): |
716 |
"""
|
717 |
Affiche les résultats de la recherche par nom d'hôte.
|
718 |
La requête de recherche (L{query}) correspond à un préfixe
|
719 |
qui sera recherché dans le nom d'hôte. Ce préfixe peut
|
720 |
contenir les caractères '*' et '?' qui agissent comme des
|
721 |
"jokers".
|
722 |
|
723 |
@param query: Prefixe de recherche sur les noms d'hôtes
|
724 |
@type query: C{unicode}
|
725 |
"""
|
726 |
|
727 |
if not query: |
728 |
redirect("searchHostForm")
|
729 |
|
730 |
query = sql_escape_like(query.strip()) |
731 |
user = get_current_user() |
732 |
if user is None: |
733 |
return dict(items=[]) |
734 |
supitemgroups = user.supitemgroups() |
735 |
|
736 |
# Récupère les hôtes auxquels l'utilisateur a réellement accès.
|
737 |
hosts = DBSession.query( |
738 |
Host.name, |
739 |
).distinct( |
740 |
).outerjoin( |
741 |
(LowLevelService, LowLevelService.idhost == Host.idhost), |
742 |
).join( |
743 |
(SUPITEM_GROUP_TABLE, or_( |
744 |
SUPITEM_GROUP_TABLE.c.idsupitem == Host.idhost, |
745 |
SUPITEM_GROUP_TABLE.c.idsupitem == |
746 |
LowLevelService.idservice, |
747 |
)), |
748 |
).filter(SUPITEM_GROUP_TABLE.c.idgroup.in_(supitemgroups) |
749 |
).filter(Host.name.like(query+'%')
|
750 |
).order_by( |
751 |
Host.name.asc(), |
752 |
).all() |
753 |
return dict(hosts=hosts) |
754 |
|
755 |
# VIGILO_EXIG_VIGILO_PERF_0030:Moteur de recherche des graphes
|
756 |
@expose('getopensearch.xml', content_type='text/xml') |
757 |
def getOpenSearch(self): |
758 |
"""
|
759 |
Moteur de recherche des graphes
|
760 |
|
761 |
@return: document
|
762 |
@rtype: document xml
|
763 |
"""
|
764 |
|
765 |
# @TODO: une URL relative ne suffit-elle pas
|
766 |
# ex: /public
|
767 |
here = "http://"
|
768 |
here += request.host |
769 |
dir_l = url('/public')
|
770 |
|
771 |
result = dict(here=here, dir=dir_l)
|
772 |
|
773 |
return result
|
774 |
|
775 |
def getListIndicators(self, graph=None): |
776 |
"""
|
777 |
Liste d indicateurs associes a un graphe
|
778 |
|
779 |
@param graph : graphe
|
780 |
@type graph : C{str}
|
781 |
|
782 |
@return: liste d indicateurs
|
783 |
@rtype : list
|
784 |
"""
|
785 |
|
786 |
indicators = [] |
787 |
if graph is not None: |
788 |
indicators = DBSession.query \ |
789 |
(PerfDataSource.name, PerfDataSource.idperfdatasource) \ |
790 |
.join((GRAPH_PERFDATASOURCE_TABLE, \ |
791 |
GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource == \ |
792 |
PerfDataSource.idperfdatasource)) \ |
793 |
.join((Graph, \ |
794 |
Graph.idgraph == GRAPH_PERFDATASOURCE_TABLE.c.idgraph)) \ |
795 |
.filter(Graph.name == graph) \ |
796 |
.all() |
797 |
return indicators
|
798 |
|