Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

vigigraph / vigigraph / controllers / rpc.py @ 63aa2a70

History | View | Annotate | Download (31.1 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 LowLevelService, 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-read',
56
                msg=l_("You don't have read access on 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 = user.supitemgroups()
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 = user.supitemgroups()
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 = user.supitemgroups()
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
            ).outerjoin(
217
                (LowLevelService, LowLevelService.idhost == Host.idhost),
218
            ).join(
219
                (SUPITEM_GROUP_TABLE, or_(
220
                    SUPITEM_GROUP_TABLE.c.idsupitem == Host.idhost,
221
                    SUPITEM_GROUP_TABLE.c.idsupitem ==
222
                        LowLevelService.idservice,
223
                )),
224
            ).filter(SUPITEM_GROUP_TABLE.c.idgroup == othergroupid
225
            ).filter(SUPITEM_GROUP_TABLE.c.idgroup.in_(groups_with_parents)
226
            ).order_by(
227
                Host.name.asc(),
228
            ).all()
229
            
230
        hosts = [(h.name, str(h.idhost)) for h in hosts]
231
        return dict(items=hosts)
232

    
233
    class GraphGroupsSchema(schema.Schema):
234
        """Schéma de validation pour la méthode L{graphgroups}."""
235
        idhost = validators.Int(not_empty=True)
236
        nocache = validators.String(if_missing=None)
237

    
238
    # @TODO définir un error_handler différent pour remonter l'erreur via JS.
239
    @validate(
240
        validators = GraphGroupsSchema(),
241
        error_handler = process_form_errors)
242
    @expose('json')
243
    def graphgroups(self, idhost, nocache):
244
        """
245
        Determination des groupes de graphes associes a l hote
246
        dont identificateur = argument
247

248
        @param idhost : identificateur d un hote
249
        @type idhost : int
250

251
        @return: groupes de service
252
        @rtype: document json (sous forme de dict)
253
        """
254
        user = get_current_user()
255
        if user is None:
256
            return dict(items=[])
257

    
258
        graphgroups = DBSession.query(
259
                GraphGroup.name,
260
                GraphGroup.idgroup,
261
            ).distinct(
262
            ).join(
263
                (GRAPH_GROUP_TABLE, GRAPH_GROUP_TABLE.c.idgroup == \
264
                    GraphGroup.idgroup),
265
                (Graph, Graph.idgraph == GRAPH_GROUP_TABLE.c.idgraph),
266
                (GRAPH_PERFDATASOURCE_TABLE, \
267
                    GRAPH_PERFDATASOURCE_TABLE.c.idgraph == Graph.idgraph),
268
                (PerfDataSource, PerfDataSource.idperfdatasource == \
269
                    GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource),
270
                (LowLevelService, LowLevelService.idservice == \
271
                    PerfDataSource.idservice),
272
                (SUPITEM_GROUP_TABLE, or_(
273
                    SUPITEM_GROUP_TABLE.c.idsupitem == LowLevelService.idhost,
274
                    SUPITEM_GROUP_TABLE.c.idsupitem ==
275
                        LowLevelService.idservice,
276
                )),
277
            ).filter(LowLevelService.idhost == idhost
278
            ).order_by(GraphGroup.name.asc())
279

    
280
        # Les managers ont accès à tout.
281
        # Les autres ont un accès restreint.
282
        is_manager = in_group('managers').is_met(request.environ)
283
        if not is_manager:
284
            supitemgroups = user.supitemgroups()
285
            graphgroups = graphgroups.filter(
286
                SUPITEM_GROUP_TABLE.c.idgroup.in_(supitemgroups))
287
        
288
        graphgroups = [(gg.name, str(gg.idgroup)) for gg in graphgroups.all()]
289
        return dict(items=graphgroups)
290

    
291
    class GraphsSchema(schema.Schema):
292
        """Schéma de validation pour la méthode L{graphs}."""
293
        idgraphgroup = validators.Int(not_empty=True)
294
        idhost = validators.Int(not_empty=True)
295
        nocache = validators.String(if_missing=None)
296

    
297
    # @TODO définir un error_handler différent pour remonter l'erreur via JS.
298
    @validate(
299
        validators = GraphsSchema(),
300
        error_handler = process_form_errors)
301
    @expose('json')
302
    def graphs(self, idgraphgroup, idhost, nocache):
303
        """
304
        Determination des graphes
305
        avec un service dont identificateur = argument
306

307
        @param idgraph : identificateur d un service
308
        @type idgraph : int
309

310
        @return: graphes
311
        @rtype: document json (sous forme de dict)
312
        """
313
        user = get_current_user()
314
        if user is None:
315
            return dict(items=[])
316

    
317
        graphs = DBSession.query(
318
                Graph.name,
319
                Graph.idgraph,
320
            ).distinct().join(
321
                (GRAPH_GROUP_TABLE, GRAPH_GROUP_TABLE.c.idgraph == \
322
                    Graph.idgraph),
323
                (GraphGroup, GraphGroup.idgroup == \
324
                    GRAPH_GROUP_TABLE.c.idgroup),
325
                (GRAPH_PERFDATASOURCE_TABLE, \
326
                    GRAPH_PERFDATASOURCE_TABLE.c.idgraph == Graph.idgraph),
327
                (PerfDataSource, PerfDataSource.idperfdatasource == \
328
                    GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource),
329
                (LowLevelService, LowLevelService.idservice == \
330
                    PerfDataSource.idservice),
331
                (SUPITEM_GROUP_TABLE, or_(
332
                    SUPITEM_GROUP_TABLE.c.idsupitem == LowLevelService.idhost,
333
                    SUPITEM_GROUP_TABLE.c.idsupitem ==
334
                        LowLevelService.idservice,
335
                )),
336
            ).filter(GraphGroup.idgroup == idgraphgroup
337
            ).filter(LowLevelService.idhost == idhost
338
            ).order_by(Graph.name.asc())
339

    
340
        # Les managers ont accès à tout.
341
        # Les autres ont un accès restreint.
342
        is_manager = in_group('managers').is_met(request.environ)
343
        if not is_manager:
344
            supitemgroups = user.supitemgroups()
345
            graphs = graphs.filter(
346
                SUPITEM_GROUP_TABLE.c.idgroup.in_(supitemgroups))
347

    
348
        graphs = [(pds.name, str(pds.idgraph)) for pds in graphs.all()]
349
        return dict(items=graphs)
350

    
351
    class SearchHostAndGraphSchema(schema.Schema):
352
        """Schéma de validation pour la méthode L{searchHostAndGraph}."""
353
        host = validators.String(if_missing=None)
354
        graph = validators.String(if_missing=None)
355
        nocache = validators.String(if_missing=None)
356

    
357
    # @TODO définir un error_handler différent pour remonter l'erreur via JS.
358
    @validate(
359
        validators = SearchHostAndGraphSchema(),
360
        error_handler = process_form_errors)
361
    @expose('json')
362
    def searchHostAndGraph(self, host, graph, nocache):
363
        """
364
        Determination des couples (hote-graphe) repondant aux criteres de
365
        recherche sur hote et/ou graphe.
366

367
        Un critere peut correspondre a un intitule complet hote ou graphe
368
        ou a un extrait.
369

370
        @param kwargs : arguments nommes
371
        @type kwargs : dict
372
                         ( arguments nommes -> host et graphe )
373

374
        @return: couples hote-graphe
375
        @rtype: document json (sous forme de dict)
376
        """
377
        user = get_current_user()
378
        items = []
379

    
380
        if user is None:
381
            return dict(items=[])
382

    
383
        # On a un nom d'indicateur, mais pas de nom d'hôte,
384
        # on considère que l'utilisateur veut tous les indicateurs
385
        # correspondant au motif, quel que soit l'hôte.
386
        if graph is not None:
387
            if host is None:
388
                host = '*'
389

    
390
            host = sql_escape_like(host)
391
            graph = sql_escape_like(graph)
392

    
393
            items = DBSession.query(
394
                    Host.name.label('hostname'),
395
                    Graph.name.label('graphname'),
396
                ).distinct().join(
397
                    (LowLevelService, LowLevelService.idhost == Host.idhost),
398
                    (PerfDataSource, PerfDataSource.idservice == \
399
                        LowLevelService.idservice),
400
                    (GRAPH_PERFDATASOURCE_TABLE, \
401
                        GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource == \
402
                        PerfDataSource.idperfdatasource),
403
                    (Graph, Graph.idgraph == \
404
                        GRAPH_PERFDATASOURCE_TABLE.c.idgraph),
405
                    (SUPITEM_GROUP_TABLE, or_(
406
                        SUPITEM_GROUP_TABLE.c.idsupitem == Host.idhost,
407
                        SUPITEM_GROUP_TABLE.c.idsupitem ==
408
                            LowLevelService.idservice,
409
                    )),
410
                ).filter(Host.name.ilike('%' + host + '%')
411
                ).filter(Graph.name.ilike('%' + graph + '%')
412
                ).order_by(
413
                    Host.name.asc(),
414
                    Graph.name.asc(),
415
                )
416

    
417
        # On a ni hôte, ni indicateur. On renvoie une liste vide.
418
        # Si l'utilisateur voulait vraiment quelque chose,
419
        # il n'avait qu'à le demander.
420
        elif host is None:
421
            return []
422

    
423
        # Sinon, on a juste un motif pour un hôte.
424
        # On renvoie la liste des hôtes correspondant.
425
        else:
426
            host = sql_escape_like(host)
427
            items = DBSession.query(
428
                    Host.name.label('hostname'),
429
                ).join(
430
                    (SUPITEM_GROUP_TABLE, SUPITEM_GROUP_TABLE.c.idsupitem == \
431
                        Host.idhost),
432
                ).filter(Host.name.ilike('%' + host + '%')
433
                ).order_by(Host.name.asc())
434

    
435
        # Les managers ont accès à tout.
436
        # Les autres ont un accès restreint.
437
        is_manager = in_group('managers').is_met(request.environ)
438
        if not is_manager:
439
            supitemgroups = user.supitemgroups()
440
            items = items.filter(
441
                SUPITEM_GROUP_TABLE.c.idgroup.in_(supitemgroups))
442

    
443
        items = items.limit(100).all()
444
        if graph is None:
445
            items = [(item.hostname, "") for item in items]
446
        else:
447
            items = [(item.hostname, item.graphname) for item in items]
448
        return dict(items=items)
449

    
450
    class SelectHostAndGraphSchema(schema.Schema):
451
        """Schéma de validation pour la méthode L{selectHostAndGraph}."""
452
        host = validators.String(if_missing=None)
453
        graph = validators.String(if_missing=None)
454
        nocache = validators.String(if_missing=None)
455

    
456
    # @TODO définir un error_handler différent pour remonter l'erreur via JS.
457
    @validate(
458
        validators = SelectHostAndGraphSchema(),
459
        error_handler = process_form_errors)
460
    @expose('json')
461
    def selectHostAndGraph(self, host, graph, nocache):
462
        """
463
        Renvoie les valeurs à sélectionner dans les comboboxes
464
        de VigiGraph pour afficher les données de l'hôte ou du
465
        couple hôte/graphe sélectionné.
466

467
        La clé "items" du dictionnaire renvoyé contient une liste avec
468
        2 éléments, chacun de ces éléments étant lui-même une liste.
469
        La 1ère liste contient les noms des groupes d'hôtes à sélectionner.
470
        La 2ème liste contient la liste des groupes de graphes à sélectionner.
471

472
        Pour le moment, la 2ème liste contiendra au plus 1 élément car
473
        les groupes de graphes ne sont pas récursifs. L'utilisation d'une
474
        liste permet d'assurer facilement une évolution vers des groupes
475
        de graphes récursifs.
476
        """
477

    
478
        # Ce cas ne devrait pas se produire, mais on tente
479
        # d'avoir un comportement gracieux malgré tout.
480
        if (not host) and (not graph):
481
            return dict(items=[[], []])
482

    
483
        selected_hostgroups = []
484
        selected_graphgroups = []
485

    
486
        # @TODO: ajouter la gestion des permissions au code qui suit.
487
        # Pour le moment, la récupération de idsupitemgroup & idgraphgroup
488
        # ne prend pas en compte les permissions réelles de l'utilisateur.
489

    
490
        if host:
491
            # Sélectionne l'identifiant du premier SupItemGroup auquel
492
            # l'utilisateur a accès et auquel l'hôte donné appartient.
493
            idsupitemgroup = DBSession.query(
494
                    SupItemGroup.idgroup,
495
                ).distinct().join(
496
                    (SUPITEM_GROUP_TABLE, SUPITEM_GROUP_TABLE.c.idgroup == \
497
                        SupItemGroup.idgroup),
498
                    (Host, Host.idhost == SUPITEM_GROUP_TABLE.c.idsupitem),
499
                ).filter(Host.name == host
500
                ).scalar()
501

    
502
            # Si on a trouvé un tel groupe, on renvoie les noms des
503
            # groupes de la hiérarchie à sélectionner pour arriver
504
            # à celui-ci.
505
            if idsupitemgroup is not None:
506
                selected_hostgroups = DBSession.query(
507
                        SupItemGroup.name,
508
                    ).distinct().join(
509
                        (GroupHierarchy, GroupHierarchy.idparent == \
510
                            GraphGroup.idgroup),
511
                    ).filter(GroupHierarchy.idchild == idsupitemgroup
512
                    ).order_by(
513
                        GroupHierarchy.hops.desc()
514
                    ).all()
515

    
516
        if graph:
517
            # Le principe est le même que pour l'hôte, en considérant
518
            # cette fois les GraphGroup à la place des SupItemGroup.
519
            idgraphgroup = DBSession.query(
520
                    GraphGroup.idgroup,
521
                ).distinct().join(
522
                    (GRAPH_GROUP_TABLE, GRAPH_GROUP_TABLE.c.idgroup == \
523
                        GraphGroup.idgroup),
524
                    (Graph, Graph.idgraph == GRAPH_GROUP_TABLE.c.idgraph),
525
                ).filter(Graph.name == graph
526
                ).scalar()
527

    
528
            # Même principe que pour l'hôte.
529
            if idgraphgroup is not None:
530
                selected_graphgroups = DBSession.query(
531
                        GraphGroup.name,
532
                    ).distinct().join(
533
                        (GroupHierarchy, GroupHierarchy.idparent == \
534
                            GraphGroup.idgroup),
535
                    ).filter(GroupHierarchy.idchild == idgraphgroup
536
                    ).order_by(
537
                        GroupHierarchy.hops.desc()
538
                    ).all()
539

    
540
        hostgroups = [hg.name for hg in selected_hostgroups]
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
        graph = validators.String(not_empty=True)
598
        nocache = validators.String(if_missing=None)
599

    
600
    # @TODO définir un error_handler différent pour remonter l'erreur via JS.
601
    @validate(
602
        validators = GetIndicatorsSchema(),
603
        error_handler = process_form_errors)
604
    @expose('json')
605
    def getIndicators(self, graph, nocache):
606
        """
607
        Liste d indicateurs associes a un graphe
608

609
        @param graph : graphe
610
        @type graph  : C{str}
611

612
        @return: dictionnaire des indicateurs d un graphe
613
        @rtype: document json (sous forme de dict)
614
        """
615

    
616
        indicators = self.getListIndicators(graph)
617
        indicators = [ind.name for ind in indicators]
618
        return dict(items=indicators)
619

    
620

    
621
    class FullHostPageSchema(schema.Schema):
622
        """Schéma de validation pour la méthode L{fullHostPage}."""
623
        host = validators.String(not_empty=True)
624
        start = validators.Int(if_missing=None)
625
        duration = validators.Int(if_missing=86400)
626

    
627
    # VIGILO_EXIG_VIGILO_PERF_0010:Visualisation globale des graphes
628
    @validate(
629
        validators = FullHostPageSchema(),
630
        error_handler = process_form_errors)
631
    @expose('fullhostpage.html')
632
    def fullHostPage(self, host, start=None, duration=86400):
633
        """
634
        Affichage de l'ensemble des graphes associes a un hote
635
        * d apres les donnees RRD
636
        * avec une date-heure de debut
637
        * pour une plage de temps 
638
        
639
        @param host : hôte
640
        @type host : C{str}
641
        @param start : date-heure de debut des donnees
642
        @type start : C{str}
643
        @param duration : plage de temps des données
644
        @type duration : C{str}
645
                         (parametre optionnel, initialise a 86400 = plage de 1 jour)
646

647
        @return: page avec les images des graphes et boutons de deplacement dans le temps
648
        @rtype: page html
649
        """
650

    
651
        if start is None:
652
            start = int(time.time()) - int(duration)
653

    
654
        start = int(start)
655
        duration = int(duration)
656

    
657
        user = get_current_user()
658
        if user is None:
659
            return dict(host=host, start=start, duration=duration,
660
                        presets=self.presets, graphs=[])
661

    
662
        # Récupération de la liste des noms des graphes,
663
        # avec vérification des permissions de l'utilisateur.
664
        graphs = DBSession.query(
665
                Graph.name
666
            ).distinct(
667
            ).join(
668
                (GRAPH_PERFDATASOURCE_TABLE,
669
                    GRAPH_PERFDATASOURCE_TABLE.c.idgraph == Graph.idgraph),
670
                (PerfDataSource, PerfDataSource.idperfdatasource ==
671
                    GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource),
672
                (LowLevelService, LowLevelService.idservice ==
673
                    PerfDataSource.idservice),
674
            ).outerjoin(
675
                (Host, Host.idhost == LowLevelService.idhost),
676
            ).join(
677
                (SUPITEM_GROUP_TABLE, or_(
678
                    SUPITEM_GROUP_TABLE.c.idsupitem ==
679
                        LowLevelService.idservice,
680
                    SUPITEM_GROUP_TABLE.c.idsupitem == Host.idhost,
681
                ))
682
            )
683

    
684
        # Les managers ont accès à tout.
685
        # Les autres ont un accès restreint.
686
        is_manager = in_group('managers').is_met(request.environ)
687
        if not is_manager:
688
            supitemgroups = user.supitemgroups()
689
            graphs = graphs.filter(
690
                SUPITEM_GROUP_TABLE.c.idgroup.in_(supitemgroups))
691

    
692
        graphs = graphs.all()
693
        return dict(host=host, start=start, duration=duration,
694
                    presets=self.presets, graphs=graphs)
695

    
696

    
697
    class SingleGraphSchema(schema.Schema):
698
        """Schéma de validation pour la méthode L{singleGraph}."""
699
        host = validators.String(not_empty=True)
700
        graph = validators.String(not_empty=True)
701
        start = validators.Int(if_missing=None)
702
        duration = validators.Int(if_missing=86400)
703

    
704
    # VIGILO_EXIG_VIGILO_PERF_0020:Visualisation unitaire des graphes
705
    @validate(
706
        validators = SingleGraphSchema(),
707
        error_handler = process_form_errors)
708
    @expose('singlegraph.html')
709
    def singleGraph(self, host, graph, start, duration):
710
        """
711
        Affichage d un graphe associe a un hote et un graphe
712
        * d apres les donnees RRD
713
        * avec une date-heure de debut
714
        * pour une plage de temps 
715
        
716
        @param host : hôte
717
        @type host : C{str}
718
        @param graph : graphe
719
        @type graph  : C{str}
720
        @param start : date-heure de debut des donnees
721
        @type start : C{str}
722
        @param duration : plage de temps des données 
723
        @type duration : C{str}
724
                         (parametre optionnel, initialise a 86400 = plage de 1 jour)
725

726
        @return: page avec l image du graphe et boutons de deplacement dans le temps
727
        @rtype: page html
728
        """
729

    
730
        if start is None:
731
            start = int(time.time()) - int(duration)
732

    
733
        start = int(start)
734
        duration = int(duration)
735

    
736
        return dict(host=host, graph=graph, start=start, duration=duration, \
737
                    presets=self.presets)
738

    
739
    @expose('searchhostform.html')
740
    def searchHostForm(self):
741
        """
742
        Formulaire de recherche sur les hotes
743

744
        @return: page avec formulaire de recherche
745
        @rtype: page html
746
        """
747
        searchhostform = SearchHostForm('search_host_form', \
748
            submit_text=None)
749

    
750
        return dict(searchhostform=searchhostform)
751

    
752
    @expose('searchhost.html')
753
    @paginate('hosts', items_per_page=10)
754
    def searchHost(self, *args, **kwargs):
755
        """
756
        Affiche les résultats de la recherche par nom d'hôte.
757
        La requête de recherche (L{query}) correspond à un préfixe
758
        qui sera recherché dans le nom d'hôte. Ce préfixe peut
759
        contenir les caractères '*' et '?' qui agissent comme des
760
        "jokers".
761

762
        @param query: Prefixe de recherche sur les noms d'hôtes
763
        @type query: C{unicode}
764
        """
765
        query = kwargs.get('query')
766
        if not query:
767
            redirect("searchHostForm")
768

    
769
        query = sql_escape_like(query.strip())
770
        user = get_current_user()
771
        if user is None:
772
            return dict(items=[])
773

    
774
        # Récupère les hôtes auxquels l'utilisateur a réellement accès.
775
        hosts = DBSession.query(
776
                Host.name,
777
            ).distinct(
778
            ).outerjoin(
779
                (LowLevelService, LowLevelService.idhost == Host.idhost),
780
            ).join(
781
                (SUPITEM_GROUP_TABLE, or_(
782
                    SUPITEM_GROUP_TABLE.c.idsupitem == Host.idhost,
783
                    SUPITEM_GROUP_TABLE.c.idsupitem ==
784
                        LowLevelService.idservice,
785
                )),
786
            ).filter(Host.name.like(query + '%')
787
            ).order_by(
788
                Host.name.asc(),
789
            )
790

    
791
        # Les managers ont accès à tout.
792
        # Les autres ont un accès restreint.
793
        is_manager = in_group('managers').is_met(request.environ)
794
        if not is_manager:
795
            supitemgroups = user.supitemgroups()
796
            hosts = hosts.filter(
797
                SUPITEM_GROUP_TABLE.c.idgroup.in_(supitemgroups))
798

    
799
        return dict(hosts=hosts)
800

    
801
    # VIGILO_EXIG_VIGILO_PERF_0030:Moteur de recherche des graphes
802
    @expose('getopensearch.xml', content_type='text/xml')
803
    def getOpenSearch(self):
804
        """
805
        Moteur de recherche des graphes
806

807
        @return: document
808
        @rtype: document xml
809
        """
810
        return dict()
811

    
812
    def getListIndicators(self, graph=None):
813
        """
814
        Liste d indicateurs associes a un graphe
815

816
        @param graph : graphe
817
        @type graph  : C{str}
818

819
        @return: liste d indicateurs
820
        @rtype  : list
821
        """
822

    
823
        indicators = []
824
        if graph is not None:
825
            indicators = DBSession.query \
826
              (PerfDataSource.name) \
827
              .join((GRAPH_PERFDATASOURCE_TABLE, \
828
              GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource == \
829
              PerfDataSource.idperfdatasource)) \
830
              .join((Graph, \
831
              Graph.idgraph == GRAPH_PERFDATASOURCE_TABLE.c.idgraph)) \
832
              .filter(Graph.name == graph) \
833
              .all()
834
        return indicators
835