Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

vigigraph / vigigraph / controllers / rpc.py @ 56b77667

History | View | Annotate | Download (33.2 KB)

1 079f14f1 Thomas BURGUIERE
# -*- coding: utf-8 -*-
2 56b77667 Francois POIROTTE
# Copyright (C) 2006-2020 CS-SI
3 90a1f4ab Aurelien BOMPARD
# License: GNU GPL v2 <http://www.gnu.org/licenses/gpl-2.0.html>
4
5 079f14f1 Thomas BURGUIERE
"""RPC controller for the combobox of vigigraph"""
6
7 8d86738e Aurelien BOMPARD
# pylint: disable-msg=W0613
8
# W0613: Unused argument : les arguments des contrôleurs sont les composants
9
#        de la query-string de l'URL
10
11
12
import time
13
import urllib2
14 0f65a3b8 Francois POIROTTE
import urlparse
15 16a7bac7 Francois POIROTTE
import logging
16
17 77b7746d Francois POIROTTE
from tg.i18n import ugettext as _, lazy_ugettext as l_, lazy_ungettext as ln_
18 d1850fc4 Francois POIROTTE
from tg import expose, request, redirect, tmpl_context, \
19 75c8d4a7 Vincent QUEMENER
    config, validate, flash, exceptions as http_exc
20 ded8142d Francois POIROTTE
from tg.predicates import not_anonymous, has_permission, in_group, Any, All
21 75c8d4a7 Vincent QUEMENER
22 cfed65e0 Francois POIROTTE
from formencode import schema
23
from tw.forms import validators
24 24589c11 Francois POIROTTE
from sqlalchemy.orm import aliased, lazyload
25 3c4e7981 Francois POIROTTE
from sqlalchemy.sql import functions
26 6aec31f5 Francois POIROTTE
from sqlalchemy import or_
27 cf4ae971 Francois POIROTTE
28 bc2d4167 Francois POIROTTE
from vigilo.turbogears.controllers import BaseController
29
from vigilo.turbogears.helpers import get_current_user
30 24589c11 Francois POIROTTE
from vigilo.turbogears.controllers.proxy import get_through_proxy
31 77b7746d Francois POIROTTE
from tg.decorators import paginate
32 89a96e65 Francis LAHEUGUERE
33 9cc80ca6 Francois POIROTTE
from vigilo.models.session import DBSession
34 24589c11 Francois POIROTTE
from vigilo.models.tables import Host, SupItemGroup, PerfDataSource
35
from vigilo.models.tables import Graph, GraphGroup, Change, UserGroup
36
from vigilo.models.tables import DataPermission
37
from vigilo.models.tables.group import Group
38 7e6517fe Francois POIROTTE
from vigilo.models.tables.grouphierarchy import GroupHierarchy
39 1eeb5d7a Francis LAHEUGUERE
40 454df3f9 Francois POIROTTE
from vigilo.models.tables.secondary_tables import SUPITEM_GROUP_TABLE
41 c765e251 Francois POIROTTE
from vigilo.models.tables.secondary_tables import GRAPH_GROUP_TABLE
42 9cc80ca6 Francois POIROTTE
from vigilo.models.tables.secondary_tables import GRAPH_PERFDATASOURCE_TABLE
43 24589c11 Francois POIROTTE
from vigilo.models.tables.secondary_tables import USER_GROUP_TABLE
44 c765e251 Francois POIROTTE
from vigilo.models.functions import sql_escape_like
45 9a31cbd1 Francois POIROTTE
46 55f029a4 Francis LAHEUGUERE
LOGGER = logging.getLogger(__name__)
47
48 079f14f1 Thomas BURGUIERE
__all__ = ['RpcController']
49 d19e6b55 Francois POIROTTE
50 89b121bb Francois POIROTTE
def ungettext(singular, plural, n):
51
    return ln_(singular, plural, n) % {
52
        'qtty': n,
53
    }
54 079f14f1 Thomas BURGUIERE
55 16a7bac7 Francois POIROTTE
# pylint: disable-msg=R0201
56 079f14f1 Thomas BURGUIERE
class RpcController(BaseController):
57
    """
58 2c334d8b Francis LAHEUGUERE
    Class Controleur TurboGears
59 079f14f1 Thomas BURGUIERE
    """
60 c765e251 Francois POIROTTE
61 62c4c6f5 Francois POIROTTE
    # L'accès à ce contrôleur nécessite d'être identifié.
62 0c6b774c Francois POIROTTE
    allow_only = All(
63
        not_anonymous(msg=l_("You need to be authenticated")),
64
        Any(
65 8089d65a Francois POIROTTE
            config.is_manager,
66 945bd396 Francois POIROTTE
            has_permission('vigigraph-access',
67 d19e6b55 Francois POIROTTE
                msg=l_("You don't have access to VigiGraph")),
68 0c6b774c Francois POIROTTE
        ),
69
    )
70 62c4c6f5 Francois POIROTTE
71 89b121bb Francois POIROTTE
    # Plages de temps affichées sur la page de métrologie complète
72
    # d'un hôte avec la durée associée (en secondes).
73
    # Voir aussi graph.js pour l'équivalent côté JavaScript sur un graphe.
74 c765e251 Francois POIROTTE
    presets = [
75 89b121bb Francois POIROTTE
        {
76
            "caption" :
77
                ungettext("Last %(qtty)d hour", "Last %(qtty)d hours", 12),
78
            "duration" : 43200,
79
        },
80
        {
81
            "caption" :
82
                ungettext("Last %(qtty)d hour", "Last %(qtty)d hours", 24),
83
            "duration" : 86400,
84
        },
85
        {
86
            "caption" :
87
                ungettext("Last %(qtty)d day", "Last %(qtty)d days", 2),
88
            "duration" : 192800,
89
        },
90
        {
91
            "caption" :
92
                ungettext("Last %(qtty)d day", "Last %(qtty)d days", 7),
93
            "duration" : 604800,
94
        },
95
        {
96
            "caption" :
97
                ungettext("Last %(qtty)d day", "Last %(qtty)d days", 14),
98
            "duration" : 1209600,
99
        },
100
        {
101
            "caption" :
102
                ungettext("Last %(qtty)d month", "Last %(qtty)d months", 1),
103
            "duration" : 86400 * 30,
104
        },
105
        {
106
            "caption" :
107
                ungettext("Last %(qtty)d month", "Last %(qtty)d months", 3),
108
            "duration" : 86400 * 30 * 3,
109
        },
110
        {
111
            "caption" :
112
                ungettext("Last %(qtty)d month", "Last %(qtty)d months", 6),
113
            "duration" : 86400 * 30 * 6,
114
        },
115
        {
116
            "caption" :
117
                ungettext("Last %(qtty)d year", "Last %(qtty)d years", 1),
118
            "duration" : 86400 * 365,
119
        },
120 c765e251 Francois POIROTTE
    ]
121
122 8d86738e Aurelien BOMPARD
    def process_form_errors(self, *args, **kwargs):
123 e2dbeada Francois POIROTTE
        """
124
        Gestion des erreurs de validation : On affiche les erreurs
125
        puis on redirige vers la dernière page accédée.
126
        """
127
        for k in tmpl_context.form_errors:
128
            flash("'%s': %s" % (k, tmpl_context.form_errors[k]), 'error')
129
        redirect(request.environ.get('HTTP_REFERER', '/'))
130
131
    class SearchHostAndGraphSchema(schema.Schema):
132 d1850fc4 Francois POIROTTE
        """Schéma de validation pour la méthode L{searchHostAndGraph}."""
133 cfed65e0 Francois POIROTTE
        search_form_host = validators.UnicodeString(if_missing=None)
134
        search_form_graph = validators.UnicodeString(if_missing=None)
135 e2dbeada Francois POIROTTE
136
    # @TODO définir un error_handler différent pour remonter l'erreur via JS.
137
    @validate(
138 d1850fc4 Francois POIROTTE
        validators = SearchHostAndGraphSchema(),
139
        error_handler = process_form_errors)
140 0f25906a Francis LAHEUGUERE
    @expose('json')
141 77b7746d Francois POIROTTE
    def searchHostAndGraph(self, search_form_host=None, search_form_graph=None):
142 2c334d8b Francis LAHEUGUERE
        """
143 c765e251 Francois POIROTTE
        Determination des couples (hote-graphe) repondant aux criteres de
144
        recherche sur hote et/ou graphe.
145 09301287 Francis LAHEUGUERE

146 c765e251 Francois POIROTTE
        Un critere peut correspondre a un intitule complet hote ou graphe
147
        ou a un extrait.
148 9b20ecb4 Francis LAHEUGUERE

149 c765e251 Francois POIROTTE
        @return: couples hote-graphe
150 7e6517fe Francois POIROTTE
        @rtype: document json (sous forme de dict)
151 2c334d8b Francis LAHEUGUERE
        """
152 924533ae Francois POIROTTE
        limit = 100
153 cf4ae971 Francois POIROTTE
        user = get_current_user()
154 924533ae Francois POIROTTE
        ids = []
155
        labels = []
156 63aa2a70 Francois POIROTTE
157 cf4ae971 Francois POIROTTE
        if user is None:
158
            return dict(items=[])
159 9b20ecb4 Francis LAHEUGUERE
160 7e6517fe Francois POIROTTE
        # On a un nom d'indicateur, mais pas de nom d'hôte,
161
        # on considère que l'utilisateur veut tous les indicateurs
162 cf4ae971 Francois POIROTTE
        # correspondant au motif, quel que soit l'hôte.
163 7c9baa43 Francois POIROTTE
        if search_form_graph:
164
            if not search_form_host:
165 24589c11 Francois POIROTTE
                search_form_host = u'*'
166 c765e251 Francois POIROTTE
167 7c9baa43 Francois POIROTTE
            search_form_host = sql_escape_like(search_form_host)
168
            search_form_graph = sql_escape_like(search_form_graph)
169 c765e251 Francois POIROTTE
170
            items = DBSession.query(
171 7c9baa43 Francois POIROTTE
                    Host.idhost.label('idhost'),
172 c765e251 Francois POIROTTE
                    Host.name.label('hostname'),
173 6aec31f5 Francois POIROTTE
                    Host.address.label('address'),
174 7c9baa43 Francois POIROTTE
                    Graph.idgraph.label('idgraph'),
175 c765e251 Francois POIROTTE
                    Graph.name.label('graphname'),
176 454df3f9 Francois POIROTTE
                ).distinct().join(
177 60c3c88e Francois POIROTTE
                    (PerfDataSource, PerfDataSource.idhost == Host.idhost),
178 c765e251 Francois POIROTTE
                    (GRAPH_PERFDATASOURCE_TABLE, \
179
                        GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource == \
180
                        PerfDataSource.idperfdatasource),
181
                    (Graph, Graph.idgraph == \
182
                        GRAPH_PERFDATASOURCE_TABLE.c.idgraph),
183 60c3c88e Francois POIROTTE
                    (SUPITEM_GROUP_TABLE, SUPITEM_GROUP_TABLE.c.idsupitem == \
184
                        Host.idhost),
185 6aec31f5 Francois POIROTTE
                ).filter(or_(
186
                    Host.name.ilike(search_form_host),
187
                    Host.address.ilike(search_form_host),
188
                )).filter(Graph.name.ilike(search_form_graph)
189 c765e251 Francois POIROTTE
                ).order_by(
190
                    Host.name.asc(),
191
                    Graph.name.asc(),
192
                )
193
194
        # On a ni hôte, ni indicateur. On renvoie une liste vide.
195
        # Si l'utilisateur voulait vraiment quelque chose,
196
        # il n'avait qu'à le demander.
197 7c9baa43 Francois POIROTTE
        elif not search_form_host:
198 c765e251 Francois POIROTTE
            return []
199
200
        # Sinon, on a juste un motif pour un hôte.
201
        # On renvoie la liste des hôtes correspondant.
202 9b20ecb4 Francis LAHEUGUERE
        else:
203 7c9baa43 Francois POIROTTE
            search_form_host = sql_escape_like(search_form_host)
204 c765e251 Francois POIROTTE
            items = DBSession.query(
205 7c9baa43 Francois POIROTTE
                    Host.idhost.label('idhost'),
206 c765e251 Francois POIROTTE
                    Host.name.label('hostname'),
207 6aec31f5 Francois POIROTTE
                    Host.address.label('address'),
208 279ff224 Francois POIROTTE
                ).distinct().join(
209 cf4ae971 Francois POIROTTE
                    (SUPITEM_GROUP_TABLE, SUPITEM_GROUP_TABLE.c.idsupitem == \
210
                        Host.idhost),
211 6aec31f5 Francois POIROTTE
                ).filter(or_(
212
                    Host.name.ilike(search_form_host),
213
                    Host.address.ilike(search_form_host),
214
                )).order_by(Host.name.asc())
215 c765e251 Francois POIROTTE
216 63aa2a70 Francois POIROTTE
        # Les managers ont accès à tout.
217
        # Les autres ont un accès restreint.
218 8089d65a Francois POIROTTE
        if not config.is_manager.is_met(request.environ):
219 945bd396 Francois POIROTTE
            supitemgroups = [sig[0] for sig in user.supitemgroups() if sig[1]]
220 fab6312f Aurelien BOMPARD
            # pylint: disable-msg=E1103
221 7e6517fe Francois POIROTTE
            items = items.join(
222
                (GroupHierarchy, GroupHierarchy.idchild == \
223
                    SUPITEM_GROUP_TABLE.c.idgroup)
224
            ).filter(GroupHierarchy.idparent.in_(supitemgroups))
225 63aa2a70 Francois POIROTTE
226 924533ae Francois POIROTTE
        items = items.limit(limit + 1).all() # pylint: disable-msg=E1103
227
        more_results = len(items) > limit
228
229 7c9baa43 Francois POIROTTE
        if not search_form_graph:
230 924533ae Francois POIROTTE
            for i in xrange(min(limit, len(items))):
231
                ids.append((items[i].idhost, None))
232 6aec31f5 Francois POIROTTE
                labels.append((items[i].hostname, items[i].address, None))
233 c765e251 Francois POIROTTE
        else:
234 924533ae Francois POIROTTE
            for i in xrange(min(limit, len(items))):
235
                ids.append((items[i].idhost, items[i].idgraph))
236 6aec31f5 Francois POIROTTE
                labels.append((
237
                    items[i].hostname,
238
                    items[i].address,
239
                    items[i].graphname
240
                ))
241 9b5ab541 Francois POIROTTE
242 924533ae Francois POIROTTE
        return dict(labels=labels, ids=ids, more=more_results)
243 0f25906a Francis LAHEUGUERE
244 9a31cbd1 Francois POIROTTE
    @expose('graphslist.html')
245 0f65a3b8 Francois POIROTTE
    def graphsList(self, graphs=None, **kwargs):
246 2c334d8b Francis LAHEUGUERE
        """
247 0f65a3b8 Francois POIROTTE
        Génération d'une page d'impression avec les graphes sélectionnés.
248 09301287 Francis LAHEUGUERE

249 0f65a3b8 Francois POIROTTE
        @param graphs : Liste des graphes à imprimer
250
        @type graphs  : C{list}
251
        @param kwargs : arguments supplémentaires (inutilisés)
252
        @type kwargs  : c{dict}
253 2c334d8b Francis LAHEUGUERE

254 0f65a3b8 Francois POIROTTE
        @return: Paramètres pour la génération de la page d'impression
255
        @rtype: dict
256 2c334d8b Francis LAHEUGUERE
        """
257 91a61890 Francois POIROTTE
        # @TODO: le must serait de hot-patcher mootools pour que son serializer
258
        # d'URL utilise directement le format attendu par TurboGears
259
        # (notation pointée plutôt qu'avec des crochets)
260
261 0f65a3b8 Francois POIROTTE
        if not graphs:
262 e2dbeada Francois POIROTTE
            return dict(graphslist=[])
263
264 0f65a3b8 Francois POIROTTE
        if not isinstance(graphs, list):
265
            graphs = [graphs]
266
267 948ecfdf Francois POIROTTE
        # On est obligé de convertir le format en UTF-8 car strftime
268
        # n'accepte pas les chaînes Unicode en entrée.
269 e2dbeada Francois POIROTTE
        # TRANSLATORS: Format Python de date/heure, lisible par un humain.
270 948ecfdf Francois POIROTTE
        format = _("%a, %d %b %Y %H:%M:%S").encode('utf8')
271 e2dbeada Francois POIROTTE
        graphslist = []
272 0f65a3b8 Francois POIROTTE
        for graph in graphs:
273
            params = urlparse.parse_qs(graph, True, True)
274 91a61890 Francois POIROTTE
            try:
275 0f65a3b8 Francois POIROTTE
                host = params['host'][0]
276
                graph = params['graph'][0]
277
                start = int(params['start'][0] or time.time() - 86400)
278
                duration = int(params['duration'][0])
279
                nocache = params['nocache'][0]
280
            except (KeyError, TypeError, ValueError):
281 91a61890 Francois POIROTTE
                break
282
283
            if not (host and graph and duration and nocache):
284
                break
285
286
            graphslist.append({
287
                'host': host,
288
                'graph': graph,
289
                'start': start,
290
                'duration': duration,
291
                'nocache': nocache,
292
                'start_date': time.strftime(format,
293
                    time.localtime(start)).decode('utf8'),
294
                'end_date': time.strftime(format,
295
                    time.localtime(start + duration)).decode('utf8')
296
            })
297 c3d8b5c1 Francis LAHEUGUERE
        return dict(graphslist=graphslist)
298 ec3ea7ab Francis LAHEUGUERE
299 7c9baa43 Francois POIROTTE
    @expose('json')
300 ec3ea7ab Francis LAHEUGUERE
    def tempoDelayRefresh(self, nocache=None):
301 2c334d8b Francis LAHEUGUERE
        """
302 09301287 Francis LAHEUGUERE
        Determination valeur temporisation pour le rafraichissement automatique
303
        d un graphe
304 07ad969f Francis LAHEUGUERE

305 5b44cbbd Francis LAHEUGUERE
        @return: valeur de temporisation
306
        @rtype: C{str}
307 2c334d8b Francis LAHEUGUERE
        """
308 07ad969f Francis LAHEUGUERE
309 e2dbeada Francois POIROTTE
        try:
310 8fbb76ad Francois POIROTTE
            delay = int(config['refresh_delay'])
311 d1850fc4 Francois POIROTTE
        except (ValueError, KeyError):
312 8fbb76ad Francois POIROTTE
            delay = 30
313 7c9baa43 Francois POIROTTE
        return {'delay': delay}
314 89a96e65 Francis LAHEUGUERE
315 e2dbeada Francois POIROTTE
    class GetIndicatorsSchema(schema.Schema):
316 d1850fc4 Francois POIROTTE
        """Schéma de validation pour la méthode L{getIndicators}."""
317 cfed65e0 Francois POIROTTE
        host = validators.UnicodeString(not_empty=True)
318
        graph = validators.UnicodeString(not_empty=True)
319
        nocache = validators.UnicodeString(if_missing=None)
320 e2dbeada Francois POIROTTE
321
    # @TODO définir un error_handler différent pour remonter l'erreur via JS.
322
    @validate(
323 d1850fc4 Francois POIROTTE
        validators = GetIndicatorsSchema(),
324
        error_handler = process_form_errors)
325 89a96e65 Francis LAHEUGUERE
    @expose('json')
326 77b7746d Francois POIROTTE
    def getIndicators(self, host, graph, nocache=None):
327 2c334d8b Francis LAHEUGUERE
        """
328
        Liste d indicateurs associes a un graphe
329

330
        @param graph : graphe
331
        @type graph  : C{str}
332

333 5b44cbbd Francis LAHEUGUERE
        @return: dictionnaire des indicateurs d un graphe
334
        @rtype: document json (sous forme de dict)
335 2c334d8b Francis LAHEUGUERE
        """
336 d19e6b55 Francois POIROTTE
337 a4389258 Francois POIROTTE
        indicators = self.getListIndicators(host, graph)
338 726122aa Aurelien BOMPARD
        indicators = [(ind.name, ind.label) for ind in indicators]
339 c765e251 Francois POIROTTE
        return dict(items=indicators)
340 45dee20d Francis LAHEUGUERE
341 726122aa Aurelien BOMPARD
    class StartTimeSchema(schema.Schema):
342
        """Schéma de validation pour la méthode L{getIndicators}."""
343 cfed65e0 Francois POIROTTE
        host = validators.UnicodeString(not_empty=True)
344
        nocache = validators.UnicodeString(if_missing=None)
345 726122aa Aurelien BOMPARD
346
    # @TODO définir un error_handler différent pour remonter l'erreur via JS.
347
    @validate(
348
        validators = StartTimeSchema(),
349
        error_handler = process_form_errors)
350
    @expose('json')
351 77b7746d Francois POIROTTE
    def startTime(self, host, nocache=None):
352 c2122f56 Francois POIROTTE
        # urllib2.quote() ne fonctionne pas sur le type unicode.
353
        # On transcode d'abord le nom d'hôte en UTF-8.
354
        quote_host = isinstance(host, unicode) and \
355
                        host.encode('utf-8') or host
356 726122aa Aurelien BOMPARD
        return get_through_proxy(
357
            'vigirrd', host,
358 c2122f56 Francois POIROTTE
            '/starttime?host=%s' % urllib2.quote(quote_host, '')
359 726122aa Aurelien BOMPARD
        )
360 e2dbeada Francois POIROTTE
361
    class FullHostPageSchema(schema.Schema):
362 d1850fc4 Francois POIROTTE
        """Schéma de validation pour la méthode L{fullHostPage}."""
363 cfed65e0 Francois POIROTTE
        host = validators.UnicodeString(not_empty=True)
364 e2dbeada Francois POIROTTE
        start = validators.Int(if_missing=None)
365
        duration = validators.Int(if_missing=86400)
366
367 fd508021 Francis LAHEUGUERE
    # VIGILO_EXIG_VIGILO_PERF_0010:Visualisation globale des graphes
368 f82ad767 Francois POIROTTE
    # VIGILO_EXIG_VIGILO_PERF_0020:Visualisation unitaire des graphes
369
    # On utilise la même page pour les 2 fonctionalités.
370 e2dbeada Francois POIROTTE
    @validate(
371 d1850fc4 Francois POIROTTE
        validators = FullHostPageSchema(),
372
        error_handler = process_form_errors)
373 c1db3132 Francis LAHEUGUERE
    @expose('fullhostpage.html')
374 abb1d154 Francis LAHEUGUERE
    def fullHostPage(self, host, start=None, duration=86400):
375
        """
376 2c334d8b Francis LAHEUGUERE
        Affichage de l'ensemble des graphes associes a un hote
377 5b44cbbd Francis LAHEUGUERE
        * d apres les donnees RRD
378
        * avec une date-heure de debut
379 d19e6b55 Francois POIROTTE
        * pour une plage de temps
380

381 2c334d8b Francis LAHEUGUERE
        @param host : hôte
382
        @type host : C{str}
383
        @param start : date-heure de debut des donnees
384
        @type start : C{str}
385 8d86738e Aurelien BOMPARD
        @param duration : plage de temps des données. Parametre optionnel,
386
            initialisé a 86400 = plage de 1 jour.
387 2c334d8b Francis LAHEUGUERE
        @type duration : C{str}
388

389 8d86738e Aurelien BOMPARD
        @return: page avec les images des graphes et boutons de deplacement
390
            dans le temps
391 09301287 Francis LAHEUGUERE
        @rtype: page html
392 abb1d154 Francis LAHEUGUERE
        """
393
        if start is None:
394
            start = int(time.time()) - int(duration)
395 75c8d4a7 Vincent QUEMENER
        else:
396
            start = int(start)
397 9a31cbd1 Francois POIROTTE
        duration = int(duration)
398
399
        user = get_current_user()
400
        if user is None:
401
            return dict(host=host, start=start, duration=duration,
402
                        presets=self.presets, graphs=[])
403
404 75c8d4a7 Vincent QUEMENER
        # Vérification des permissions de l'utilisateur sur l'hôte.
405 8089d65a Francois POIROTTE
        if not config.is_manager.is_met(request.environ):
406 75c8d4a7 Vincent QUEMENER
            # Récupération des groupes auxquels l'utilisateur a accès.
407
            supitemgroups = [sig[0] for sig in user.supitemgroups() if sig[1]]
408 cfed65e0 Francois POIROTTE
409
            # On vérifie que l'hôte en question existe bel et bien.
410
            host_obj = Host.by_host_name(host)
411
            if not host_obj:
412
                message = _('No such host "%s"') % host
413
                LOGGER.warning(message)
414
                raise http_exc.HTTPNotFound(message)
415
416 7e984955 Vincent QUEMENER
            # Récupération des groupes dont l'hôte fait partie
417 cfed65e0 Francois POIROTTE
            hostgroups = [g.idgroup for g in host_obj.groups]
418 7e984955 Vincent QUEMENER
            # Si aucun des groupes de l'hôte ne fait partie des groupes
419
            # auxquels l'utilisateur a accès, on affiche une erreur 403.
420
            if len(set(hostgroups).intersection(set(supitemgroups))) < 1:
421 75c8d4a7 Vincent QUEMENER
                message = _('Access denied to host "%s"') % host
422
                LOGGER.warning(message)
423 24589c11 Francois POIROTTE
                raise http_exc.HTTPForbidden(message)
424 75c8d4a7 Vincent QUEMENER
425
        # Récupération de la liste des noms des graphes associés à l'hôte.
426 9a31cbd1 Francois POIROTTE
        graphs = DBSession.query(
427
                Graph.name
428
            ).distinct(
429
            ).join(
430
                (GRAPH_PERFDATASOURCE_TABLE,
431
                    GRAPH_PERFDATASOURCE_TABLE.c.idgraph == Graph.idgraph),
432
                (PerfDataSource, PerfDataSource.idperfdatasource ==
433
                    GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource),
434 60c3c88e Francois POIROTTE
                (Host, Host.idhost == PerfDataSource.idhost),
435 e71a38ac Francois POIROTTE
            ).filter(Host.name == host)
436 9a31cbd1 Francois POIROTTE
437 63aa2a70 Francois POIROTTE
        graphs = graphs.all()
438 9a31cbd1 Francois POIROTTE
        return dict(host=host, start=start, duration=duration,
439
                    presets=self.presets, graphs=graphs)
440 c1db3132 Francis LAHEUGUERE
441 e2dbeada Francois POIROTTE
442 cfed65e0 Francois POIROTTE
    class SearchHostSchema(schema.Schema):
443 6aec31f5 Francois POIROTTE
        """Schéma de validation pour la méthode L{searchHost}."""
444 cfed65e0 Francois POIROTTE
        allow_extra_fields = True
445
        filter_extra_fields = True
446
        query = validators.UnicodeString(not_empty=True)
447
448 e4b8d982 Francois POIROTTE
    @expose('searchhost.html')
449 cfed65e0 Francois POIROTTE
    @validate(
450
        validators = SearchHostSchema(),
451
        error_handler = process_form_errors)
452 9773b809 Francois POIROTTE
    @paginate('hosts', items_per_page=10)
453 cfed65e0 Francois POIROTTE
    def searchHost(self, query):
454 2c334d8b Francis LAHEUGUERE
        """
455 9a31cbd1 Francois POIROTTE
        Affiche les résultats de la recherche par nom d'hôte.
456 2256d3db Aurelien BOMPARD
        La requête de recherche (C{query}) correspond à un préfixe
457 9a31cbd1 Francois POIROTTE
        qui sera recherché dans le nom d'hôte. Ce préfixe peut
458
        contenir les caractères '*' et '?' qui agissent comme des
459
        "jokers".
460

461 2256d3db Aurelien BOMPARD
        @keyword query: Prefixe de recherche sur les noms d'hôtes
462
        @type    query: C{unicode}
463 2c334d8b Francis LAHEUGUERE
        """
464 9a31cbd1 Francois POIROTTE
        if not query:
465
            redirect("searchHostForm")
466 cfed65e0 Francois POIROTTE
            return
467 10ba3fed Francis LAHEUGUERE
468 9a31cbd1 Francois POIROTTE
        query = sql_escape_like(query.strip())
469
        user = get_current_user()
470
        if user is None:
471
            return dict(items=[])
472 4fe15b02 Francis LAHEUGUERE
473 9a31cbd1 Francois POIROTTE
        # Récupère les hôtes auxquels l'utilisateur a réellement accès.
474
        hosts = DBSession.query(
475
                Host.name,
476 6aec31f5 Francois POIROTTE
                Host.address,
477 9a31cbd1 Francois POIROTTE
            ).distinct(
478
            ).join(
479 60c3c88e Francois POIROTTE
                (SUPITEM_GROUP_TABLE, SUPITEM_GROUP_TABLE.c.idsupitem == \
480
                    Host.idhost),
481 6aec31f5 Francois POIROTTE
            ).filter(or_(
482
                Host.name.like(query + u'%'),
483
                Host.address.like(query + u'%')
484
            )).order_by(Host.name.asc(),)
485 63aa2a70 Francois POIROTTE
486
        # Les managers ont accès à tout.
487
        # Les autres ont un accès restreint.
488 8089d65a Francois POIROTTE
        if not config.is_manager.is_met(request.environ):
489 945bd396 Francois POIROTTE
            supitemgroups = [sig[0] for sig in user.supitemgroups() if sig[1]]
490 7e6517fe Francois POIROTTE
            hosts = hosts.join(
491
                    (GroupHierarchy, GroupHierarchy.idchild == \
492
                        SUPITEM_GROUP_TABLE.c.idgroup)
493
                ).filter(GroupHierarchy.idparent.in_(supitemgroups))
494 63aa2a70 Francois POIROTTE
495 6aec31f5 Francois POIROTTE
        return dict(hosts=[(h.name, h.address) for h in hosts])
496 4fe15b02 Francis LAHEUGUERE
497 fd508021 Francis LAHEUGUERE
    # VIGILO_EXIG_VIGILO_PERF_0030:Moteur de recherche des graphes
498 c765e251 Francois POIROTTE
    @expose('getopensearch.xml', content_type='text/xml')
499 4fe15b02 Francis LAHEUGUERE
    def getOpenSearch(self):
500 2c334d8b Francis LAHEUGUERE
        """
501 09301287 Francis LAHEUGUERE
        Moteur de recherche des graphes
502 2c334d8b Francis LAHEUGUERE

503 5b44cbbd Francis LAHEUGUERE
        @return: document
504 09301287 Francis LAHEUGUERE
        @rtype: document xml
505 2c334d8b Francis LAHEUGUERE
        """
506 9773b809 Francois POIROTTE
        return dict()
507 cdde92ac Francis LAHEUGUERE
508 7c9baa43 Francois POIROTTE
    @expose('json')
509 704b1fa1 Aurelien BOMPARD
    def hosttree(self, parent_id=None, onlytype="", offset=0, noCache=None):
510 cc1a971a Vincent QUEMENER
        """
511
        Affiche un étage de l'arbre de
512
        sélection des hôtes et groupes d'hôtes.
513

514
        @param parent_id: identifiant du groupe d'hôte parent
515
        @type  parent_id: C{int} or None
516
        """
517 7c9baa43 Francois POIROTTE
518
        # Si l'identifiant du groupe parent n'est pas
519
        # spécifié, on retourne la liste des groupes racines,
520 7e6517fe Francois POIROTTE
        # fournie par la méthode get_root_hosts_groups.
521 7c9baa43 Francois POIROTTE
        if parent_id is None:
522
            return self.get_root_host_groups()
523
524
        # TODO: Utiliser un schéma de validation
525
        parent_id = int(parent_id)
526 704b1fa1 Aurelien BOMPARD
        offset = int(offset)
527 7e6517fe Francois POIROTTE
528
        # On vérifie si le groupe parent fait partie des
529
        # groupes auxquel l'utilisateur a accès, et on
530
        # retourne une liste vide dans le cas contraire
531 8089d65a Francois POIROTTE
        is_manager = config.is_manager.is_met(request.environ)
532 7c9baa43 Francois POIROTTE
        if not is_manager:
533 7e6517fe Francois POIROTTE
            direct_access = False
534
            user = get_current_user()
535 24589c11 Francois POIROTTE
536
            # On calcule la distance de ce groupe par rapport aux groupes
537
            # sur lesquels l'utilisateur a explicitement les permissions.
538
            #
539
            # La distance est définie ainsi :
540
            # 0 : l'utilisateur a des droits explicites sur ce groupe.
541
            # > 0 : l'utilisateur a accès implicitement au groupe.
542
            # < 0 : l'utilisateur n'a pas d'accès (il peut juste parcourir
543
            #       ce groupe)
544
            #
545
            # Il faut 2 étapes pour trouver la distance. La 1ère essaye
546
            # de trouver une distance >= 0, la 2ème une distance <= 0.
547
548
            # Distance positive.
549
            distance = DBSession.query(
550 3c4e7981 Francois POIROTTE
                    functions.max(GroupHierarchy.hops)
551 24589c11 Francois POIROTTE
                ).join(
552
                    (Group, Group.idgroup == GroupHierarchy.idparent),
553 8d86738e Aurelien BOMPARD
                    (DataPermission,
554
                        DataPermission.idgroup == Group.idgroup),
555
                    (UserGroup,
556
                        UserGroup.idgroup == DataPermission.idusergroup),
557 24589c11 Francois POIROTTE
                    (USER_GROUP_TABLE, USER_GROUP_TABLE.c.idgroup == \
558
                        UserGroup.idgroup),
559
                ).filter(USER_GROUP_TABLE.c.username == user.user_name
560 f20684bf Francois POIROTTE
                ).filter(Group.grouptype == u'supitemgroup'
561 24589c11 Francois POIROTTE
                ).filter(GroupHierarchy.idchild == parent_id
562 3c4e7981 Francois POIROTTE
                ).scalar()
563 24589c11 Francois POIROTTE
564
            if distance is None:
565
                # Distance négative.
566
                distance = DBSession.query(
567 3c4e7981 Francois POIROTTE
                        functions.max(GroupHierarchy.hops)
568 7e6517fe Francois POIROTTE
                    ).join(
569 24589c11 Francois POIROTTE
                        (Group, Group.idgroup == GroupHierarchy.idchild),
570 8d86738e Aurelien BOMPARD
                        (DataPermission,
571
                            DataPermission.idgroup == Group.idgroup),
572
                        (UserGroup,
573
                            UserGroup.idgroup == DataPermission.idusergroup),
574 24589c11 Francois POIROTTE
                        (USER_GROUP_TABLE, USER_GROUP_TABLE.c.idgroup == \
575
                            UserGroup.idgroup),
576
                    ).filter(USER_GROUP_TABLE.c.username == user.user_name
577 f20684bf Francois POIROTTE
                    ).filter(Group.grouptype == u'supitemgroup'
578 24589c11 Francois POIROTTE
                    ).filter(GroupHierarchy.idparent == parent_id
579 3c4e7981 Francois POIROTTE
                    ).scalar()
580 24589c11 Francois POIROTTE
                if distance is not None:
581
                    distance = -distance
582
583
            if distance is None:
584
                # Pas d'accès à ce groupe.
585
                return dict(groups = [], items = [])
586
587
            direct_access = distance >= 0
588 7e6517fe Francois POIROTTE
589 704b1fa1 Aurelien BOMPARD
        limit = int(config.get("max_menu_entries", 20))
590
        result = {"groups": [], "items": []}
591
592
        if not onlytype or onlytype == "group":
593
            # On récupère la liste des groupes dont
594
            # l'identifiant du parent est passé en paramètre
595 24589c11 Francois POIROTTE
            gh1 = aliased(GroupHierarchy, name='gh1')
596
            gh2 = aliased(GroupHierarchy, name='gh2')
597
598 704b1fa1 Aurelien BOMPARD
            db_groups = DBSession.query(
599
                SupItemGroup
600 24589c11 Francois POIROTTE
            ).options(lazyload('_path_obj')
601
            ).distinct(
602 704b1fa1 Aurelien BOMPARD
            ).join(
603 24589c11 Francois POIROTTE
                (gh1, gh1.idchild == SupItemGroup.idgroup),
604
            ).filter(gh1.hops == 1
605
            ).filter(gh1.idparent == parent_id
606 704b1fa1 Aurelien BOMPARD
            ).order_by(SupItemGroup.name.asc())
607 24589c11 Francois POIROTTE
608 704b1fa1 Aurelien BOMPARD
            if not is_manager and not direct_access:
609 24589c11 Francois POIROTTE
                # On ne doit afficher que les fils du groupe <parent_id>
610
                # tels que l'utilisateur a accès explicitement à l'un
611
                # des fils de l'un de ces groupes.
612
                db_groups = db_groups.join(
613
                        (gh2, gh2.idparent == gh1.idchild),
614 8d86738e Aurelien BOMPARD
                        (DataPermission,
615
                            DataPermission.idgroup == gh2.idchild),
616
                        (UserGroup,
617
                            UserGroup.idgroup == DataPermission.idusergroup),
618
                        (USER_GROUP_TABLE,
619
                            USER_GROUP_TABLE.c.idgroup == UserGroup.idgroup),
620 24589c11 Francois POIROTTE
                    ).filter(USER_GROUP_TABLE.c.username == user.user_name)
621 704b1fa1 Aurelien BOMPARD
622
            num_children_left = db_groups.count() - offset
623
            if offset:
624
                result["continued_from"] = offset
625
                result["continued_type"] = "group"
626
            all_groups = db_groups.limit(limit).offset(offset).all()
627
            for group in all_groups:
628
                result["groups"].append({
629
                    'id'   : group.idgroup,
630
                    'name' : group.name,
631
                    'type' : "group",
632
                })
633
            if num_children_left > limit:
634
                result["groups"].append({
635
                    'name': _("Next %(limit)s") % {"limit": limit},
636
                    'offset': offset + limit,
637
                    'parent_id': parent_id,
638
                    'type': 'continued',
639
                    'for_type': 'group',
640
                })
641 7c9baa43 Francois POIROTTE
642
        # On récupère la liste des hôtes appartenant au
643
        # groupe dont l'identifiant est passé en paramètre
644 704b1fa1 Aurelien BOMPARD
        if ((not onlytype or onlytype == "item")
645
                and (is_manager or direct_access)):
646 7c9baa43 Francois POIROTTE
            db_hosts = DBSession.query(
647
                Host.idhost,
648
                Host.name,
649
            ).join(
650 7e6517fe Francois POIROTTE
                (SUPITEM_GROUP_TABLE,
651
                    SUPITEM_GROUP_TABLE.c.idsupitem == Host.idhost
652
                    ),
653 7c9baa43 Francois POIROTTE
            ).filter(SUPITEM_GROUP_TABLE.c.idgroup == parent_id
654
            ).order_by(Host.name.asc())
655 704b1fa1 Aurelien BOMPARD
            num_children_left = db_hosts.count() - offset
656
            if offset:
657
                result["continued_from"] = offset
658
                result["continued_type"] = "item"
659
            all_hosts = db_hosts.limit(limit).offset(offset).all()
660
            for host in all_hosts:
661
                result["items"].append({
662 7c9baa43 Francois POIROTTE
                    'id'   : host.idhost,
663
                    'name' : host.name,
664 704b1fa1 Aurelien BOMPARD
                    'type' : "item",
665
                })
666
            if num_children_left > limit:
667
                result["items"].append({
668
                    'name': _("Next %(limit)s") % {"limit": limit},
669
                    'offset': offset + limit,
670
                    'parent_id': parent_id,
671
                    'type': 'continued',
672
                    'for_type': 'item',
673 7c9baa43 Francois POIROTTE
                })
674
675 704b1fa1 Aurelien BOMPARD
        return result
676 7c9baa43 Francois POIROTTE
677
    @expose('json')
678 704b1fa1 Aurelien BOMPARD
    def graphtree(self, host_id=None, parent_id=None, offset=0, noCache=None):
679 cc1a971a Vincent QUEMENER
        """
680
        Affiche un étage de l'arbre de sélection
681
        des graphes et groupes de graphes.
682

683
        @param parent_id: identifiant du groupe de graphes parent
684
        @type  parent_id: C{int} or None
685
        """
686 7c9baa43 Francois POIROTTE
687
        # Si l'identifiant de l'hôte n'est pas spécifié, on
688
        # retourne un dictionnaire contenant deux listes vides
689
        if host_id is None:
690 7e6517fe Francois POIROTTE
            return dict(groups = [], graphs=[])
691 7c9baa43 Francois POIROTTE
692
        # On vérifie les permissions sur l'hôte
693
        # TODO: Utiliser un schéma de validation
694
        host_id = int(host_id)
695 7e6517fe Francois POIROTTE
        host = DBSession.query(Host
696
            ).filter(Host.idhost == host_id
697
            ).first()
698 7c9baa43 Francois POIROTTE
        if host is None:
699 7e6517fe Francois POIROTTE
            return dict(groups = [], graphs=[])
700 7c9baa43 Francois POIROTTE
        user = get_current_user()
701
        if not host.is_allowed_for(user):
702 7e6517fe Francois POIROTTE
            return dict(groups = [], graphs=[])
703 7c9baa43 Francois POIROTTE
704 b6d2af46 Vincent QUEMENER
        # On récupère la liste des groupes de graphes associés à l'hôte
705 7c9baa43 Francois POIROTTE
        host_graph_groups = DBSession.query(
706
            GraphGroup
707
        ).distinct(
708
        ).join(
709
            (GRAPH_GROUP_TABLE, \
710
                GRAPH_GROUP_TABLE.c.idgroup == GraphGroup.idgroup),
711
            (Graph, Graph.idgraph == GRAPH_GROUP_TABLE.c.idgraph),
712
            (GRAPH_PERFDATASOURCE_TABLE, \
713
                    GRAPH_PERFDATASOURCE_TABLE.c.idgraph == Graph.idgraph),
714
            (PerfDataSource, PerfDataSource.idperfdatasource == \
715
                    GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource),
716 7e6517fe Francois POIROTTE
            (SUPITEM_GROUP_TABLE, \
717
                SUPITEM_GROUP_TABLE.c.idsupitem == PerfDataSource.idhost),
718 7c9baa43 Francois POIROTTE
        ).filter(PerfDataSource.idhost == host_id
719 7e6517fe Francois POIROTTE
        ).order_by(GraphGroup.name.asc()
720
        ).all()
721 7c9baa43 Francois POIROTTE
722
        # Si l'identifiant du groupe parent n'est pas spécifié,
723
        # on récupère la liste des groupes de graphes racines.
724
        if parent_id is None:
725 7e6517fe Francois POIROTTE
            graph_groups = GraphGroup.get_top_groups()
726 7c9baa43 Francois POIROTTE
727
        # Sinon on récupère la liste des graphes dont le
728 7e6517fe Francois POIROTTE
        # groupe passé en paramètre est le parent direct
729 7c9baa43 Francois POIROTTE
        else:
730
            # TODO: Utiliser un schéma de validation
731
            parent_id = int(parent_id)
732 7e6517fe Francois POIROTTE
            graph_groups = DBSession.query(
733
                GraphGroup
734
            ).join(
735
                (GroupHierarchy, GroupHierarchy.idchild == \
736
                    GraphGroup.idgroup),
737
            ).filter(GroupHierarchy.hops == 1
738
            ).filter(GroupHierarchy.idparent == parent_id
739
            ).order_by(GraphGroup.name.asc()
740
            ).all()
741 7c9baa43 Francois POIROTTE
742
        # On réalise l'intersection des deux listes
743
        groups = []
744
        for gg in graph_groups:
745
            if gg in host_graph_groups:
746
                groups.append({
747
                    'id'   : gg.idgroup,
748
                    'name' : gg.name,
749 704b1fa1 Aurelien BOMPARD
                    'type' : "group",
750 7c9baa43 Francois POIROTTE
                })
751
752
        # On récupère la liste des graphes appartenant au
753
        # groupe dont l'identifiant est passé en paramètre
754
        graphs = []
755
        if parent_id:
756
            db_graphs = DBSession.query(
757
                Graph.idgraph,
758
                Graph.name,
759 b6d2af46 Vincent QUEMENER
            ).distinct(
760 7c9baa43 Francois POIROTTE
            ).join(
761
                (GRAPH_GROUP_TABLE,
762 b6d2af46 Vincent QUEMENER
                    GRAPH_GROUP_TABLE.c.idgraph == Graph.idgraph),
763
                (GRAPH_PERFDATASOURCE_TABLE,
764
                    GRAPH_PERFDATASOURCE_TABLE.c.idgraph == Graph.idgraph),
765
                (PerfDataSource,
766
                    PerfDataSource.idperfdatasource == \
767
                        GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource),
768 7c9baa43 Francois POIROTTE
            ).filter(GRAPH_GROUP_TABLE.c.idgroup == parent_id
769 b6d2af46 Vincent QUEMENER
            ).filter(PerfDataSource.idhost == host_id
770 7c9baa43 Francois POIROTTE
            ).order_by(Graph.name.asc())
771
            for graph in db_graphs.all():
772
                graphs.append({
773
                    'id'   : graph.idgraph,
774
                    'name' : graph.name,
775 704b1fa1 Aurelien BOMPARD
                    'type' : "item",
776 7c9baa43 Francois POIROTTE
                })
777
778 704b1fa1 Aurelien BOMPARD
        return dict(groups=groups, items=graphs)
779 7c9baa43 Francois POIROTTE
780
    def get_root_host_groups(self):
781
        """
782
        Retourne tous les groupes racines (c'est à dire n'ayant
783
        aucun parent) d'hôtes auquel l'utilisateur a accès.
784

785
        @return: Un dictionnaire contenant la liste de ces groupes.
786
        @rtype : C{dict} of C{list} of C{dict} of C{mixed}
787
        """
788
789 7e6517fe Francois POIROTTE
        # On récupère tous les groupes qui ont un parent.
790
        children = DBSession.query(
791
            SupItemGroup,
792
        ).distinct(
793
        ).join(
794
            (GroupHierarchy, GroupHierarchy.idchild == SupItemGroup.idgroup)
795
        ).filter(GroupHierarchy.hops > 0)
796
797
        # Ensuite on les exclut de la liste des groupes,
798
        # pour ne garder que ceux qui sont au sommet de
799
        # l'arbre et qui constituent nos "root groups".
800
        root_groups = DBSession.query(
801
            SupItemGroup,
802
        ).except_(children
803
        ).order_by(SupItemGroup.name)
804 7c9baa43 Francois POIROTTE
805
        # On filtre ces groupes racines afin de ne
806
        # retourner que ceux auquels l'utilisateur a accès
807
        user = get_current_user()
808 8089d65a Francois POIROTTE
        if not config.is_manager.is_met(request.environ):
809 7e6517fe Francois POIROTTE
            user_groups = [ug[0] for ug in user.supitemgroups()]
810
            root_groups = root_groups.filter(
811
                SupItemGroup.idgroup.in_(user_groups))
812 7c9baa43 Francois POIROTTE
813
        groups = []
814 7e6517fe Francois POIROTTE
        for group in root_groups.all():
815 7c9baa43 Francois POIROTTE
            groups.append({
816
                'id'   : group.idgroup,
817
                'name' : group.name,
818 704b1fa1 Aurelien BOMPARD
                'type' : "group",
819 7c9baa43 Francois POIROTTE
            })
820
821 3e3db819 Aurelien BOMPARD
        return dict(groups=groups, items=[])
822 b6d2af46 Vincent QUEMENER
823 a4389258 Francois POIROTTE
    def getListIndicators(self, host, graph):
824 2c334d8b Francis LAHEUGUERE
        """
825 2ed2fd99 Francois POIROTTE
        Liste d indicateurs associes a un graphe
826 cdde92ac Francis LAHEUGUERE

827 2ed2fd99 Francois POIROTTE
        @param graph : graphe
828
        @type graph  : C{str}
829 2c334d8b Francis LAHEUGUERE

830 2ed2fd99 Francois POIROTTE
        @return: liste d indicateurs
831
        @rtype  : list
832 2c334d8b Francis LAHEUGUERE
        """
833
834 2ed2fd99 Francois POIROTTE
        indicators = []
835
        if graph is not None:
836 60c3c88e Francois POIROTTE
            indicators = DBSession.query(
837 726122aa Aurelien BOMPARD
                    PerfDataSource.name, PerfDataSource.label
838 a4389258 Francois POIROTTE
                ).distinct(
839 60c3c88e Francois POIROTTE
                ).join(
840
                    (GRAPH_PERFDATASOURCE_TABLE, \
841
                        GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource == \
842
                        PerfDataSource.idperfdatasource),
843
                    (Graph, Graph.idgraph == \
844
                        GRAPH_PERFDATASOURCE_TABLE.c.idgraph),
845 a4389258 Francois POIROTTE
                    (Host, Host.idhost == PerfDataSource.idhost),
846 60c3c88e Francois POIROTTE
                ).filter(Graph.name == graph
847 a4389258 Francois POIROTTE
                ).filter(Host.name == host
848 60c3c88e Francois POIROTTE
                ).all()
849 2ed2fd99 Francois POIROTTE
        return indicators
850 aed0c054 Aurelien BOMPARD
851
    @expose('json')
852
    def dbmtime(self):
853
        change = Change.by_table_name(u"Graph")
854
        if change is None:
855
            return {"mtime": None}
856
        mtime = change.last_modified.replace(microsecond=0)
857
        return {"mtime": mtime}
858 8f6567c2 Francois POIROTTE
859
    @expose('json')
860
    def selectHostAndGraph(self, host, graph):
861
        # @TODO: vérifier les permissions
862
        ids = DBSession.query(
863
                Host.idhost, Graph.idgraph
864
            ).join(
865
                (PerfDataSource, PerfDataSource.idhost == Host.idhost),
866
                (GRAPH_PERFDATASOURCE_TABLE, \
867
                    GRAPH_PERFDATASOURCE_TABLE.c.idperfdatasource == \
868
                    PerfDataSource.idperfdatasource),
869
                (Graph, Graph.idgraph == \
870
                    GRAPH_PERFDATASOURCE_TABLE.c.idgraph),
871
            ).filter(Graph.name == unicode(graph)
872
            ).filter(Host.name == unicode(host)
873
            ).first()
874
875
        return {
876
            'idhost': ids and ids.idhost or None,
877
            'idgraph': ids and ids.idgraph or None,
878
        }
879 71acc6fa Francois POIROTTE
880
    @expose('json')
881
    def external_links(self):
882
        return dict(links=config['external_links'])