Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

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