Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

vigigraph / vigigraph / controllers / rpc.py @ 00456667

History | View | Annotate | Download (31 KB)

1
# -*- coding: utf-8 -*-
2
"""RPC controller for the combobox of vigigraph"""
3

    
4
import time
5
import urllib
6
import urllib2
7
import logging
8

    
9
from pylons.i18n import ugettext as _
10
from tg import expose, response, request, redirect, config, url, exceptions
11
from sqlalchemy.orm import aliased
12

    
13
from vigigraph.lib.base import BaseController
14

    
15
from vigilo.models.session import DBSession
16
from vigilo.models.tables import LowLevelService, Host
17
from vigilo.models.tables import SupItemGroup, GroupHierarchy
18
from vigilo.models.tables import PerfDataSource
19
from vigilo.models.tables import Graph, GraphGroup
20
from vigilo.models.tables import Ventilation, VigiloServer, Application
21

    
22
from vigilo.models.tables.secondary_tables import SUPITEM_GROUP_TABLE
23
from vigilo.models.tables.secondary_tables import GRAPH_GROUP_TABLE
24
from vigilo.models.tables.secondary_tables import GRAPH_PERFDATASOURCE_TABLE
25
from vigilo.models.functions import sql_escape_like
26
        
27
from vigilo.turbogears.rrdproxy import RRDProxy
28
from vigilo.turbogears.nagiosproxy import NagiosProxy
29

    
30
from vigigraph.widgets.searchhostform import SearchHostForm
31
from vigigraph.lib import graphs
32

    
33

    
34
LOGGER = logging.getLogger(__name__)
35

    
36
__all__ = ['RpcController']
37

    
38
# pylint: disable-msg=R0201
39
class RpcController(BaseController):
40
    """
41
    Class Controleur TurboGears
42
    """
43

    
44
    presets = [
45
        {"caption" : _("Last %d hours") %  12, "duration" : 43200},
46
        {"caption" : _("Last %d hours") %  24, "duration" : 86400},
47
        {"caption" : _("Last %d days") %    2, "duration" : 192800},
48
        {"caption" : _("Last %d days") %    7, "duration" : 604800},
49
        {"caption" : _("Last %d days") %   14, "duration" : 1209600},
50
        {"caption" : _("Last %d months") %  3, "duration" : 86400*31*3},
51
        {"caption" : _("Last %d months") %  6, "duration" : 86400*183},
52
        {"caption" : _("Last year"), "duration" : 86400*365},
53
    ]
54

    
55
    @expose('json')
56
    def maingroups(self, nocache=None):
57
        """
58
        Determination des groupes principaux (sans parent)
59

60
        @return: groupes principaux
61
        @rtype: document json (sous forme de dict)
62
        """
63
        topgroups = [(tpg.name, str(tpg.idgroup)) \
64
                    for tpg in SupItemGroup.get_top_groups()]
65
        return dict(items=topgroups)
66

    
67
    @expose('json')
68
    def hostgroups(self, maingroupid, nocache=None):
69
        """
70
        Determination des groupes associes au groupe parent
71
        dont identificateur = argument
72

73
        @param maingroupid : identificateur d un groupe principal
74
        @type maingroupid : int
75

76
        @return: groupes
77
        @rtype: document json (sous forme de dict)
78
        """
79
        hostgroups = DBSession.query(
80
                SupItemGroup.name,
81
                SupItemGroup.idgroup,
82
            ).join(
83
                (GroupHierarchy, GroupHierarchy.idchild == \
84
                    SupItemGroup.idgroup),
85
            ).filter(GroupHierarchy.idparent == maingroupid
86
            ).filter(GroupHierarchy.hops == 1
87
            ).order_by(
88
                SupItemGroup.name.asc(),
89
            ).all()
90
        hostgroups = [(hg.name, str(hg.idgroup)) for hg in hostgroups]
91
        return dict(items=hostgroups)
92

    
93
    @expose('json')
94
    def hosts(self, othergroupid, nocache=None):
95
        """
96
        Determination des hotes associes au groupe
97
        dont identificateur = argument
98

99
        @param othergroupid : identificateur d un groupe
100
        @type othergroupid : int
101

102
        @return: hotes
103
        @rtype: document json (sous forme de dict)
104
        """
105
        hosts = DBSession.query(
106
                Host.name,
107
                Host.idhost,
108
            ).join(
109
                (SUPITEM_GROUP_TABLE, SUPITEM_GROUP_TABLE.c.idsupitem == \
110
                    Host.idhost),
111
                (SupItemGroup, SupItemGroup.idgroup == \
112
                    SUPITEM_GROUP_TABLE.c.idgroup),
113
            ).filter(SupItemGroup.idgroup == othergroupid
114
            ).order_by(
115
                Host.name.asc(),
116
            ).all()
117
            
118
        hosts = [(h.name, str(h.idhost)) for h in hosts]
119
        return dict(items=hosts)
120

    
121
    @expose('json')
122
    def graphgroups(self, idhost, nocache=None):
123
        """
124
        Determination des groupes de graphes associes a l hote
125
        dont identificateur = argument
126

127
        @param idhost : identificateur d un hote
128
        @type idhost : int
129

130
        @return: groupes de service
131
        @rtype: document json (sous forme de dict)
132
        """
133
        graphgroups = DBSession.query(
134
                GraphGroup.name,
135
                GraphGroup.idgroup,
136
            ).distinct(
137
            ).join(
138
                (GRAPH_GROUP_TABLE, GRAPH_GROUP_TABLE.c.idgroup == \
139
                    GraphGroup.idgroup),
140
                (Graph, Graph.idgraph == GRAPH_GROUP_TABLE.c.idgraph),
141
                (GRAPH_PERFDATASOURCE_TABLE, \
142
                    GRAPH_PERFDATASOURCE_TABLE.c.idgraph == Graph.idgraph),
143
                (PerfDataSource, PerfDataSource.idperfdatasource == \
144
                    GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource),
145
                (LowLevelService, LowLevelService.idservice == \
146
                    PerfDataSource.idservice),
147
            ).filter(
148
                LowLevelService.idhost == idhost
149
            ).order_by(
150
                GraphGroup.name.asc()
151
            )
152
        
153
        print "@@@\n%s\n@@@" % graphgroups
154
        graphgroups = graphgroups.all()
155

    
156
        graphgroups = [(gg.name, str(gg.idgroup)) for gg in graphgroups]
157
        return dict(items=graphgroups)
158

    
159
    @expose('json')
160
    def graphs(self, idgraphgroup, idhost, nocache=None):
161
        """
162
        Determination des graphes
163
        avec un service dont identificateur = argument
164

165
        @param idgraph : identificateur d un service
166
        @type idgraph : int
167

168
        @return: graphes
169
        @rtype: document json (sous forme de dict)
170
        """
171
        graphs_l = DBSession.query(
172
                Graph.name,
173
                Graph.idgraph,
174
            ).distinct().join(
175
                (GRAPH_GROUP_TABLE, GRAPH_GROUP_TABLE.c.idgraph == \
176
                    Graph.idgraph),
177
                (GraphGroup, GraphGroup.idgroup == \
178
                    GRAPH_GROUP_TABLE.c.idgroup),
179
                (GRAPH_PERFDATASOURCE_TABLE, \
180
                    GRAPH_PERFDATASOURCE_TABLE.c.idgraph == Graph.idgraph),
181
                (PerfDataSource, PerfDataSource.idperfdatasource == \
182
                    GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource),
183
                (LowLevelService, LowLevelService.idservice == \
184
                    PerfDataSource.idservice),
185
            ).filter(GraphGroup.idgroup == idgraphgroup
186
            ).filter(LowLevelService.idhost == idhost
187
            ).order_by(
188
                Graph.name.asc()
189
            )
190

    
191
        print "@@@\n%s\n@@@" % graphs_l
192
        graphs_l = graphs_l.all()
193

    
194
        graphs_l = [(pds.name, str(pds.idgraph)) for pds in graphs_l]
195
        return dict(items=graphs_l)
196

    
197
    @expose('json')
198
    def searchHostAndGraph(self, **kwargs):
199
        """
200
        Determination des couples (hote-graphe) repondant aux criteres de
201
        recherche sur hote et/ou graphe.
202

203
        Un critere peut correspondre a un intitule complet hote ou graphe
204
        ou a un extrait.
205

206
        @param kwargs : arguments nommes
207
        @type kwargs : dict
208
                         ( arguments nommes -> host et graphe )
209

210
        @return: couples hote-graphe
211
        @rtype: document json (sous forme de dict)
212
        """
213
        host = kwargs.get('host')
214
        graph = kwargs.get('graph')
215
        items = None
216

    
217
        # On a un nom d'indicateur, mais pas de nom d'hôte,
218
        # on considère que l'utilisateur veut tous les indicateurs
219
        # correspondant au motif, quelque soit l'hôte.
220
        if graph is not None:
221
            if host is None:
222
                host = '*'
223

    
224
            host = sql_escape_like(host)
225
            graph = sql_escape_like(graph)
226

    
227
            items = DBSession.query(
228
                    Host.name.label('hostname'),
229
                    Graph.name.label('graphname'),
230
                ).distinct().join(
231
                    (LowLevelService, LowLevelService.idhost == Host.idhost),
232
                    (PerfDataSource, PerfDataSource.idservice == \
233
                        LowLevelService.idservice),
234
                    (GRAPH_PERFDATASOURCE_TABLE, \
235
                        GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource == \
236
                        PerfDataSource.idperfdatasource),
237
                    (Graph, Graph.idgraph == \
238
                        GRAPH_PERFDATASOURCE_TABLE.c.idgraph),
239
                ).filter(Host.name.ilike('%' + host + '%')
240
                ).filter(Graph.name.ilike('%' + graph + '%')
241
                ).order_by(
242
                    Host.name.asc(),
243
                    Graph.name.asc(),
244
                )
245

    
246
        # On a ni hôte, ni indicateur. On renvoie une liste vide.
247
        # Si l'utilisateur voulait vraiment quelque chose,
248
        # il n'avait qu'à le demander.
249
        elif host is None:
250
            return []
251

    
252
        # Sinon, on a juste un motif pour un hôte.
253
        # On renvoie la liste des hôtes correspondant.
254
        else:
255
            host = sql_escape_like(host)
256
            items = DBSession.query(
257
                    Host.name.label('hostname'),
258
                ).filter(
259
                    Host.name.ilike('%' + host + '%')
260
                ).order_by(Host.name.asc())
261

    
262
        items = items.limit(100).all()
263
        if graph is None:
264
            items = [(item.hostname, "") for item in items]
265
        else:
266
            items = [(item.hostname, item.graphname) for item in items]
267
        return dict(items=items)
268

    
269
    @expose('json')
270
    def selectHostAndGraph(self, host=None, graph=None, nocache=None):
271
        """
272
        Renvoie les valeurs à sélectionner dans les comboboxes
273
        de VigiGraph pour afficher les données de l'hôte ou du
274
        couple hôte/graphe sélectionné.
275

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

281
        Pour le moment, la 2ème liste contiendra au plus 1 élément car
282
        les groupes de graphes ne sont pas récursifs. L'utilisation d'une
283
        liste permet d'assurer facilement une évolution vers des groupes
284
        de graphes récursifs.
285
        """
286

    
287
        # Ce cas ne devrait pas se produire, mais on tente
288
        # d'avoir un comportement gracieux malgré tout.
289
        if (not host) and (not graph):
290
            return dict(items=[[], []])
291

    
292
        # Groupe principal de l'hôte.
293
        mhg = aliased(SupItemGroup)
294
        # Groupe secondaire de l'hôte.
295
        shg = aliased(SupItemGroup)
296

    
297
        selected_hostgroups = []
298
        selected_graphgroups = []
299

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

    
304
        if host:
305
            # Sélectionne l'identifiant du premier SupItemGroup auquel
306
            # l'utilisateur a accès et auquel l'hôte donné appartient.
307
            idsupitemgroup = DBSession.query(
308
                    SupItemGroup.idgroup,
309
                ).join(
310
                    (SUPITEM_GROUP_TABLE, SUPITEM_GROUP_TABLE.c.idgroup == \
311
                        SupItemGroup.idgroup),
312
                    (Host, Host.idhost == SUPITEM_GROUP_TABLE.c.idsupitem),
313
                ).filter(Host.name == host
314
                ).scalar()
315

    
316
            # Si on a trouvé un tel groupe, on renvoie les noms des
317
            # groupes de la hiérarchie à sélectionner pour arriver
318
            # à celui-ci.
319
            if idsupitemgroup is not None:
320
                selected_hostgroups = DBSession.query(
321
                        SupItemGroup.name,
322
                    ).join(
323
                        (GroupHierarchy, GroupHierarchy.idparent == \
324
                            GraphGroup.idgroup),
325
                    ).filter(GroupHierarchy.idchild == idsupitemgroup
326
                    ).order_by(
327
                        GroupHierarchy.hops.desc()
328
                    ).all()
329

    
330
        if graph:
331
            # Le principe est le même que pour l'hôte, en considérant
332
            # cette fois les GraphGroup à la place des SupItemGroup.
333
            idgraphgroup = DBSession.query(
334
                    GraphGroup.idgroup,
335
                ).join(
336
                    (GRAPH_GROUP_TABLE, GRAPH_GROUP_TABLE.c.idgroup == \
337
                        GraphGroup.idgroup),
338
                    (Graph, Graph.idgraph == GRAPH_GROUP_TABLE.c.idgraph),
339
                ).filter(Graph.name == graph
340
                ).scalar()
341

    
342
            # Même principe que pour l'hôte.
343
            if idgraphgroup is not None:
344
                selected_graphgroups = DBSession.query(
345
                        GraphGroup.name,
346
                    ).join(
347
                        (GroupHierarchy, GroupHierarchy.idparent == \
348
                            GraphGroup.idgroup),
349
                    ).filter(GroupHierarchy.idchild == idgraphgroup
350
                    ).order_by(
351
                        GroupHierarchy.hops.desc()
352
                    ).all()
353

    
354
        hostgroups = [hg.name for hg in selected_hostgroups]
355
        graphgroups = [gg.name for gg in selected_graphgroups]
356
        return dict(items=[hostgroups, graphgroups])        
357

    
358
    @expose(content_type='text/plain')
359
    def getImage(self, host, start=None, duration=86400, graph=None, \
360
    details=1, nocache=0):
361
        """
362
        Determination de l url d un graphe
363
        (via proxy RRD)
364

365
        @param host : hôte
366
        @type host : C{str}
367
        @param start : date-heure de debut des donnees
368
        @type start : C{str}
369
        @param duration : plage de temps des données
370
        @type duration : C{str}
371
                         (parametre optionnel, initialise a 86400 = plage de 1 jour)
372
        @param details : indicateur affichage details dans graphe (legende)
373
        @type details : int
374
        @param graph : graphe
375
        @type graph : C{str}
376

377
        @return: url du graphe
378
        @rtype: C{str}
379
        """
380

    
381
        result = None
382

    
383
        if start is None:
384
            start = int(time.time()) - 24*3600
385

    
386
        # valeurs particulieres
387
        direct = 1
388
        rrdserver = self.getRRDServer(host)
389

    
390
        if rrdserver is not None:
391
            # url
392
            url_web_path = config.get('rrd_web_path')
393
            url_l = '%s%s' % (rrdserver, url_web_path)
394

    
395
            # proxy
396
            rrdproxy = RRDProxy(url_l)
397
            try:
398
                result = rrdproxy.get_img_name_with_params(host, graph, \
399
                direct, duration, start, int(details))
400
            except urllib2.URLError:
401
                txt = _("Can't get RRD graph \"%s\" on host \"%s\"") \
402
                    % (graph, host)
403
                LOGGER.error(txt)
404
                exceptions.HTTPNotFound(comment=txt)
405

    
406
        return result
407

    
408
    # VIGILO_EXIG_VIGILO_PERF_0020:Visualisation unitaire des graphes
409
    @expose(content_type='image/png')
410
    def getImage_png(self, host, start=None, duration=86400, graph=None, \
411
    details=1):
412
        """
413
        Affichage de l image d un graphe
414
        (via proxy RRD)
415

416
        @param host : hôte
417
        @type host : C{str}
418
        @param start : date-heure de debut des donnees
419
        @type start : C{str}
420
        @param duration : plage de temps des données
421
        @type duration : C{str}
422
                      (parametre optionnel, initialise a 86400 = plage de 1 jour)
423
        @param graph : graphe
424
        @type graph : C{str}
425
        @param details : indicateur affichage details dans graphe (legende)
426
        @type details : int
427

428
        @return: image du graphe
429
        @rtype: image png
430
        """
431
        result = None
432

    
433
        if start is None:
434
            start = int(time.time()) - 24*3600
435

    
436
        # valeurs particulieres
437
        direct = 1
438
        rrdserver = self.getRRDServer(host)
439
        
440
        if rrdserver is not None:
441
            # url
442
            url_web_path = config.get('rrd_web_path')
443
            url_l = '%s%s' % (rrdserver, url_web_path)
444

    
445
            # proxy
446
            rrdproxy = RRDProxy(url_l)
447
            try:
448
                result = rrdproxy.get_img_with_params(host, graph, direct, \
449
                duration, start, int(details))
450
            except urllib2.URLError:
451
                txt = _("Can't get RRD graph \"%s\" on host \"%s\"") \
452
                    % (graph, host)
453
                LOGGER.error(txt)
454
                exceptions.HTTPNotFound(comment=txt)
455

    
456
        return result
457

    
458
    @expose()
459
    def imagePage(self, server, graphtemplate):
460
        """
461
        Affichage de l image d un graphe
462

463
        @param server : hôte
464
        @type server : C{str}
465
        @param graphtemplate : graphe
466
        @type graphtemplate : C{str}
467

468
        @return: page avec l image du graphe (redirection sur getImage_png)
469
        @rtype: page
470
        """
471
        redirect('getImage_png?host=%s&graph=%s' % (server, graphtemplate))
472

    
473
    @expose()
474
    def getStartTime(self, host, nocache=None):
475
        """
476
        Determination de la date-heure de debut des donnees RRD d un hote
477
        (via proxy RRD)
478

479
        @param host : hôte
480
        @type host : C{str}
481

482
        @return: date-heure de debut des donnees RRD
483
        @rtype: C{str}
484
        """
485

    
486
        result = None
487
        getstarttime = 1
488
        rrdserver = self.getRRDServer(host)
489

    
490
        if rrdserver is not None:
491
            # url
492
            url_web_path = config.get('rrd_web_path')
493
            url_l = '%s%s' % (rrdserver, url_web_path)
494
    
495
            # proxy
496
            rrdproxy = RRDProxy(url_l)
497
            try:
498
                result = rrdproxy.get_starttime(host, getstarttime)
499
            except urllib2.URLError:
500
                txt = _("Can't get RRD data on host \"%s\"") \
501
                    % (host)
502
                LOGGER.error(txt)
503
                exceptions.HTTPNotFound(comment=txt)
504

    
505
        return result
506

    
507
    @expose()
508
    def supPage(self, host):
509
        """
510
        Affichage page supervision Nagios pour un hote
511
        (appel fonction status via proxy Nagios)
512
        
513
        @param host : hôte
514
        @type host : C{str}
515

516
        @return: page de supervision Nagios
517
        @rtype: page
518
        """
519
        result = None
520

    
521
        nagiosserver = self.getNagiosServer(host)
522
        if nagiosserver is not None:
523
            # url
524
            url_web_path = config.get('nagios_web_path')
525
            url_l = '%s%s' % (nagiosserver, url_web_path)
526

    
527
            # proxy
528
            nagiosproxy = NagiosProxy(url_l)
529
            try:
530
                result = nagiosproxy.get_status(host)
531
            except urllib2.URLError:
532
                txt = _("Can't get Nagios data on host \"%s\"") \
533
                    % (host)
534
                LOGGER.error(txt)
535
                error_url = '../error/nagios_host_error?host=%s'
536
                redirect(error_url % host)
537
        else:
538
            txt = _("No server has been configured to monitor \"%s\"") % host
539
            LOGGER.error(txt)
540
            error_url = '../error/nagios_host_error?host=%s' % host
541
            redirect(error_url)
542

    
543

    
544
        return result
545

    
546
    @expose()
547
    def servicePage(self, host, service=None):
548
        """
549
        Affichage page supervision Nagios pour un hote
550
        (appel fonction get_extinfo via proxy Nagios)
551

552
        @param host : hôte
553
        @type host : C{str}
554
        @param service : service
555
        @type service : C{str}
556

557
        @return: page de supervision Nagios
558
        @rtype: page
559
        """
560
        result = None
561

    
562
        nagiosserver = self.getNagiosServer(host)
563
        if nagiosserver is not None:
564
            # url
565
            url_web_path = config.get('nagios_web_path')
566
            url_l = '%s%s' % (nagiosserver, url_web_path)
567

    
568
            # proxy
569
            nagiosproxy = NagiosProxy(url_l)
570
            try:
571
                result = nagiosproxy.get_extinfo(host, service)
572
            except urllib2.URLError:
573
                txt = _("Can't get Nagios data on host \"%s\" service \"%s\"")\
574
                    % (host, service)
575
                LOGGER.error(txt)
576

    
577
                error_url = '../error'
578
                error_url += '/nagios_host_service_error?host=%s&service=%s'
579
                redirect(error_url % (host, service))
580

    
581
        return result
582

    
583
    @expose()
584
    def metroPage(self, host):
585
        """
586
        Affichage page metrologie pour un hote
587
        (via proxy RRD)
588

589
        @param host : hôte
590
        @type host : C{str}
591

592
        @return: page de metrologie
593
        @rtype: page
594
        """
595
        result = None
596

    
597
        rrdserver = self.getRRDServer(host)
598
        if rrdserver is not None:
599
            # url
600
            url_web_path = config.get('rrd_web_path')
601
            url_l = '%s%s' % (rrdserver, url_web_path)
602

    
603
            # proxy
604
            rrdproxy = RRDProxy(url_l)
605
            try:
606
                result = rrdproxy.get_hostC(host)
607
            except urllib2.URLError:
608
                txt = _("Can't get RRD data on host \"%s\"") \
609
                    % (host)
610
                LOGGER.error(txt)
611
                error_url = '../error/rrd_error?host=%s'
612
                redirect(error_url % host)
613

    
614
        return result
615

    
616
    @expose('graphslist.html', content_type='text/html')
617
    def graphsList(self, nocache=None, **kwargs):
618
        """
619
        Generation document avec url des graphes affiches
620
        (pour l impression )
621

622
        @param kwargs : arguments nommes
623
        @type kwargs  : dict
624

625
        @return: url de graphes
626
        @rtype: document html
627
        """
628
        graphslist = graphs.graphsList(**kwargs)
629
        return dict(graphslist=graphslist)
630

    
631
    @expose(content_type='text/plain')
632
    def tempoDelayRefresh(self, nocache=None):
633
        """
634
        Determination valeur temporisation pour le rafraichissement automatique
635
        d un graphe
636

637
        @return: valeur de temporisation
638
        @rtype: C{str}
639
        """
640

    
641
        delay = graphs.tempoDelayRefresh()
642
        return delay
643

    
644
    @expose('json')
645
    def getIndicators(self, nocache=None, graph=None):
646
        """
647
        Liste d indicateurs associes a un graphe
648

649
        @param graph : graphe
650
        @type graph  : C{str}
651

652
        @return: dictionnaire des indicateurs d un graphe
653
        @rtype: document json (sous forme de dict)
654
        """
655

    
656
        indicators = self.getListIndicators(graph)
657
        indicators = [(ind.name, ind.idperfdatasource) for ind in indicators]
658
        return dict(items=indicators)
659

    
660
    def getListIndicators(self, graph=None):
661
        """
662
        Liste d indicateurs associes a un graphe
663

664
        @param graph : graphe
665
        @type graph  : C{str}
666

667
        @return: liste d indicateurs
668
        @rtype  : list
669
        """
670

    
671
        indicators = []
672
        if graph is not None:
673
            indicators = DBSession.query \
674
              (PerfDataSource.name, PerfDataSource.idperfdatasource) \
675
              .join((GRAPH_PERFDATASOURCE_TABLE, \
676
              GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource == \
677
              PerfDataSource.idperfdatasource)) \
678
              .join((Graph, \
679
              Graph.idgraph == GRAPH_PERFDATASOURCE_TABLE.c.idgraph)) \
680
              .filter(Graph.name == graph) \
681
              .all()
682
        return indicators
683

    
684
    # VIGILO_EXIG_VIGILO_PERF_0040:Export des donnees d'un graphe au format CSV
685
    @expose(content_type='text/csv')
686
    def exportCSV(self, nocache=None, host=None, graph=None, indicator=None, \
687
    start=None, end=None):
688
        """
689
        Export CSV sous forme de fichier
690
        pour un hote et un graphe et pour l'indicateur suivant
691
        * soit un des indicateurs associes au graphe
692
        * soit l ensemble des indicateurs -> valeur argument = All
693

694
        @param host : hôte
695
        @type host : C{str}
696
        @param graph : graphe
697
        @type graph : C{str}
698
        @param indicator : indicateur graphe
699
        @type indicator : C{str}
700
        @param start : date-heure de debut des donnees
701
        @type start : C{str}
702

703
        @return: fichier genere avec les donnees RRD repondant aux criteres
704
        @rtype  : fichier CSV
705
        """
706

    
707
        result = None
708
        filename = None
709

    
710
        # indicateurs
711
        if indicator is None:
712
            raise ValueError
713

    
714
        rrdserver = self.getRRDServer(host)
715
        if not rrdserver:
716
            raise ValueError, host
717

    
718
        indicators = [ind[0] for ind in self.getListIndicators(graph)]
719
        if indicator != "All":
720
            if indicator not in indicators:
721
                raise ValueError, indicator
722
            indicators = [indicator]
723
            filename = graphs.getExportFileName(host, indicator, start, end)
724

    
725
        else:
726
            filename = graphs.getExportFileName(host, graph, start, end)
727

    
728
        indicators.insert(0, "Timestamp")
729

    
730
        url_web_path = config.get('rrd_web_path', '')
731
        url = '%s%s' % (rrdserver, url_web_path)
732
        rrdproxy = RRDProxy(url)
733

    
734
        try:
735
            result = rrdproxy.exportCSV(server=host, graph=graph, \
736
                indicator=indicator, start=start, end=end)
737
        except urllib2.URLError:
738
            # @TODO utiliser des dicos pour faciliter la traduction.
739
            txt = _("Can't get RRD data on host \"%s\" "
740
                    "graph \"%s\" indicator \"%s\" ") % (host, graph, indicator)
741
            LOGGER.error(txt)
742

    
743
            error_url = '../error'
744
            error_url += '/rrd_exportCSV_error'
745
            error_url += '?host=%s&graph=%s&indicator=%s'
746
            redirect(error_url % (host, graph, indicator))
747
        else:
748
            response.headerlist.append(('Content-Disposition',
749
                'attachment;filename=%s' % filename))
750
            return result
751

    
752

    
753
    # VIGILO_EXIG_VIGILO_PERF_0010:Visualisation globale des graphes
754
    @expose('fullhostpage.html')
755
    def fullHostPage(self, host, start=None, duration=86400):
756
        """
757
        Affichage de l'ensemble des graphes associes a un hote
758
        * d apres les donnees RRD
759
        * avec une date-heure de debut
760
        * pour une plage de temps 
761
        
762
        @param host : hôte
763
        @type host : C{str}
764
        @param start : date-heure de debut des donnees
765
        @type start : C{str}
766
        @param duration : plage de temps des données
767
        @type duration : C{str}
768
                         (parametre optionnel, initialise a 86400 = plage de 1 jour)
769

770
        @return: page avec les images des graphes et boutons de deplacement dans le temps
771
        @rtype: page html
772
        """
773

    
774
        if start is None:
775
            start = int(time.time()) - int(duration)
776

    
777
        # graphes pour hote
778
        hgs = DBSession.query(Graph.name) \
779
              .join((GRAPH_PERFDATASOURCE_TABLE, \
780
              GRAPH_PERFDATASOURCE_TABLE.c.idgraph == Graph.idgraph)) \
781
              .join((PerfDataSource, \
782
              GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource == \
783
              PerfDataSource.idperfdatasource)) \
784
              .join((LowLevelService, \
785
              PerfDataSource.idservice == LowLevelService.idservice)) \
786
              .join((Host, \
787
              LowLevelService.idhost == Host.idhost)) \
788
              .filter(Host.name == host) \
789
              .all()
790

    
791
        # dictionnaire -> {0 : [hote, graph_0], ..., n: [hote, graph_n] }
792
        i = 0
793
        dhgs = {}
794
        for hg in hgs:
795
            elt = [host, hg]
796
            dhgs[i] = elt
797
            i += 1
798

    
799
        return dict(host=host, start=start, duration=duration, \
800
                    presets=self.presets, dhgs=dhgs)
801

    
802
    @expose('singlegraph.html')
803
    def singleGraph(self, host, graph, start=None, duration=86400):
804
        """
805
        Affichage d un graphe associe a un hote et un graphe
806
        * d apres les donnees RRD
807
        * avec une date-heure de debut
808
        * pour une plage de temps 
809
        
810
        @param host : hôte
811
        @type host : C{str}
812
        @param graph : graphe
813
        @type graph  : C{str}
814
        @param start : date-heure de debut des donnees
815
        @type start : C{str}
816
        @param duration : plage de temps des données 
817
        @type duration : C{str}
818
                         (parametre optionnel, initialise a 86400 = plage de 1 jour)
819

820
        @return: page avec l image du graphe et boutons de deplacement dans le temps
821
        @rtype: page html
822
        """
823

    
824
        if start is None:
825
            start = int(time.time()) - int(duration)
826

    
827
        return dict(host=host, graph=graph, start=start, duration=duration, \
828
                    presets=self.presets)
829

    
830
    @expose('searchhostform.html')
831
    def searchHostForm(self):
832
        """
833
        Formulaire de recherche sur les hotes
834

835
        @return: page avec formulaire de recherche
836
        @rtype: page html
837
        """
838
        searchhostform = SearchHostForm('search_host_form', \
839
            submit_text=None)
840

    
841
        return dict(searchhostform=searchhostform)
842

    
843
    @expose('searchhost.html')
844
    def searchHost(self, query=None):
845
        """
846
        Affichage page pour hotes repondant au critere de recherche
847
        * dans cette page, lien sur pages de metrologie et de supervision
848

849
        @param query : prefixe de recherche sur les hotes
850
        @type query : C{str}
851

852
        @return: page
853
        @rtype: page html
854
        """
855

    
856
        hosts = []
857

    
858
        if query:
859
            r = urllib.unquote_plus(query.strip())
860
            rl = r.split(',')
861

    
862
            # hotes
863
            for part in rl:
864
                hosts += DBSession.query(Host.name) \
865
                        .filter(Host.name.like(part.strip() + '%')) \
866
                        .all()
867
            return dict(hosts=hosts)
868
        else:
869
            redirect("searchHostForm")
870

    
871
    # VIGILO_EXIG_VIGILO_PERF_0030:Moteur de recherche des graphes
872
    @expose('getopensearch.xml', content_type='text/xml')
873
    def getOpenSearch(self):
874
        """
875
        Moteur de recherche des graphes
876

877
        @return: document
878
        @rtype: document xml
879
        """
880

    
881
        here = "http://"
882
        here += request.host
883
        dir_l = url('/public')
884

    
885
        result = dict(here=here, dir=dir_l)
886

    
887
        return result
888

    
889
    def getRRDServer(self, host=None):
890
        """
891
        Determination Serveur RRD pour l hote courant
892
        (Serveur RRD -> nom de l application associee = rrdgraph)
893

894
        @param host : hôte
895
        @type host : C{str}
896

897
        @return: serveur RRD
898
        @rtype: C{str}
899
        """
900

    
901
        result = DBSession.query \
902
            (VigiloServer.name) \
903
            .filter(VigiloServer.idvigiloserver == Ventilation.idvigiloserver) \
904
            .filter(Ventilation.idhost == Host.idhost) \
905
            .filter(Ventilation.idapp == Application.idapp) \
906
            .filter(Host.name == host) \
907
            .filter(Application.name == 'rrdgraph') \
908
            .scalar()
909
        return result
910

    
911
    def getNagiosServer(self, host=None):
912
        """
913
        Determination Serveur Nagios pour l hote courant
914
        (Server Nagios -> nom de l application associee = nagios)
915

916
        @param host : hôte
917
        @type host : C{str}
918

919
        @return: serveur Nagios
920
        @rtype: C{str}
921
        """
922

    
923
        result = DBSession.query \
924
            (VigiloServer.name) \
925
            .filter(VigiloServer.idvigiloserver == Ventilation.idvigiloserver) \
926
            .filter(Ventilation.idhost == Host.idhost) \
927
            .filter(Ventilation.idapp == Application.idapp) \
928
            .filter(Host.name == host) \
929
            .filter(Application.name == 'nagios') \
930
            .scalar()
931
        return result