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