Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

vigiboard / vigiboard / controllers / plugins / details.py @ 9b8d9497

History | View | Annotate | Download (8.14 KB)

1
# -*- coding: utf-8 -*-
2
# vim:set expandtab tabstop=4 shiftwidth=4:
3
# Copyright (C) 2007-2016 CS-SI
4
# License: GNU GPL v2 <http://www.gnu.org/licenses/gpl-2.0.html>
5

    
6
"""
7
Un plugin pour VigiBoard qui ajoute une colonne avec les liens vers les
8
entrées d'historiques liées à l'événement, ainsi que les liens vers les
9
applications externes.
10
"""
11

    
12
import urllib
13
from tg import config, url, request
14
from pylons.i18n import lazy_ugettext as l_
15
import tw.forms as twf
16
from sqlalchemy.sql.expression import null as expr_null, union_all
17
from sqlalchemy import func
18

    
19
from repoze.what.predicates import has_permission, in_group
20
from vigilo.turbogears.helpers import get_current_user
21

    
22
from vigilo.models.session import DBSession
23
from vigilo.models.tables import Event, CorrEvent, Host, LowLevelService, \
24
    StateName, Map, MapNode, MapNodeHost, MapGroup
25
from vigilo.models.tables.secondary_tables import MAP_GROUP_TABLE
26

    
27
from vigiboard.controllers.plugins import VigiboardRequestPlugin, ITEMS
28

    
29

    
30
class PluginDetails(VigiboardRequestPlugin):
31
    """
32
    Plugin qui ajoute des liens vers les historiques et les applications
33
    externes.
34
    """
35

    
36
    def get_json_data(self, idcorrevent, *args, **kwargs):
37
        """
38
        Renvoie les éléments pour l'affichage de la fenêtre de dialogue
39
        contenant des détails sur un événement corrélé.
40

41
        @param idcorrevent: identifiant de l'événement corrélé.
42
        @type idcorrevent: C{int}
43
        """
44

    
45
        # Obtention de données sur l'événement et sur son historique
46
        host_query = DBSession.query(
47
            Host.idhost.label("idsupitem"),
48
            Host.idhost.label("idhost"),
49
            Host.name.label("host"),
50
            expr_null().label("service"),
51
        )
52
        lls_query = DBSession.query(
53
            LowLevelService.idservice.label("idsupitem"),
54
            Host.idhost.label("idhost"),
55
            Host.name.label("host"),
56
            LowLevelService.servicename.label("service"),
57
        ).join(
58
            (Host, Host.idhost == LowLevelService.idhost),
59
        )
60
        supitems = union_all(lls_query, host_query, correlate=False).alias()
61
        event = DBSession.query(
62
            CorrEvent.idcorrevent,
63
            CorrEvent.idcause,
64
            supitems.c.idhost,
65
            supitems.c.host,
66
            supitems.c.service,
67
            Event.message,
68
            Event.initial_state,
69
            Event.current_state,
70
            Event.peak_state
71
        ).join(
72
            (Event, Event.idevent == CorrEvent.idcause),
73
            (supitems, supitems.c.idsupitem == Event.idsupitem),
74
        ).filter(CorrEvent.idcorrevent == idcorrevent
75
        ).first()
76

    
77
        # On détermine les cartes auxquelles cet utilisateur a accès.
78
        user_maps = []
79
        max_maps = int(config['max_maps'])
80
        is_manager = config.is_manager.is_met(request.environ)
81
        if max_maps != 0 and (is_manager or
82
            has_permission('vigimap-access').is_met(request.environ)):
83
            items = DBSession.query(
84
                    Map.idmap,
85
                    Map.title,
86
                    func.lower(Map.title),
87
                ).distinct(
88
                ).join(
89
                    (MAP_GROUP_TABLE, MAP_GROUP_TABLE.c.idmap == Map.idmap),
90
                    (MapGroup, MapGroup.idgroup == MAP_GROUP_TABLE.c.idgroup),
91
                    (MapNodeHost, MapNodeHost.idmap == Map.idmap),
92
                ).order_by(func.lower(Map.title).asc()
93
                ).filter(MapNodeHost.idhost == event.idhost)
94

    
95
            if not is_manager:
96
                mapgroups = get_current_user().mapgroups(only_direct=True)
97
                # pylint: disable-msg=E1103
98
                items = items.filter(MapGroup.idgroup.in_(mapgroups))
99

    
100
            # La valeur -1 supprime la limite.
101
            if max_maps > 0:
102
                # On limite au nombre maximum de cartes demandés + 1.
103
                # Un message sera affiché s'il y a effectivement plus
104
                # de cartes que la limite configurée.
105
                items = items.limit(max_maps + 1)
106

    
107
            user_maps = [(m.idmap, m.title) for m in items.all()]
108

    
109
        context = {
110
            'idcorrevent': idcorrevent,
111
            'host': event.host,
112
            'service': event.service,
113
            'message': event.message,
114
            'maps': user_maps,
115
            'current_state': StateName.value_to_statename(event.current_state),
116
            'initial_state': StateName.value_to_statename(event.initial_state),
117
            'peak_state': StateName.value_to_statename(event.peak_state),
118
        }
119

    
120
        eventdetails = {}
121
        for edname, edlink in enumerate(config['vigiboard_links.eventdetails']):
122
            # Évite que les gardes ne se polluent entre elles.
123
            local_ctx = context.copy()
124

    
125
            # Les liens peuvent être conditionnés à l'aide
126
            # d'une expression ou d'un callable qui agira
127
            # comme un prédicat de test.
128
            if 'only_if' in edlink:
129
                if callable(edlink['only_if']):
130
                    display_link = edlink['only_if'](local_ctx)
131
                else:
132
                    display_link = edlink['only_if']
133
                if not display_link:
134
                    continue
135

    
136
            if callable(edlink['uri']):
137
                uri = edlink['uri'](local_ctx)
138
            else:
139
                uri = edlink['uri'] % local_ctx
140

    
141
            eventdetails[unicode(edname)] = {
142
                'url': url(uri),
143
                'target': edlink.get('target', '_blank')
144
            }
145

    
146
        return dict(
147
                current_state = StateName.value_to_statename(
148
                                    event.current_state),
149
                initial_state = StateName.value_to_statename(
150
                                    event.initial_state),
151
                peak_state = StateName.value_to_statename(
152
                                    event.peak_state),
153
                idcorrevent = idcorrevent,
154
                host = event.host,
155
                service = event.service,
156
                eventdetails = eventdetails,
157
                maps = user_maps,
158
                idcause = event.idcause,
159
            )
160

    
161
    def get_data(self, event):
162
        state = StateName.value_to_statename(event[0].cause.current_state)
163
        peak_state = StateName.value_to_statename(event[0].cause.peak_state)
164
        init_state = StateName.value_to_statename(event[0].cause.initial_state)
165
        return {
166
            'state': state,
167
            'peak_state': peak_state,
168
            'initial_state': init_state,
169
            'id': event[0].idcorrevent,
170
        }
171

    
172
    def get_search_fields(self):
173
        states = DBSession.query(StateName.idstatename, StateName.statename
174
                    ).order_by(StateName.order.asc()).all()
175
        # Liste des valeurs acceptées pour la validation.
176
        valid = []
177
        # Liste des options présentes dans le champ de sélection.
178
        options = []
179
        for s in states:
180
            valid.extend([str(s.idstatename), s.statename])
181
            options.append( (
182
                str(s.idstatename),
183
                s.statename,
184
                {'title': l_(s.statename)}
185
            ) )
186

    
187
        return [
188
            twf.MultipleSelectField(
189
                'state',
190
                label_text=l_('Current state'),
191
                options=options,
192
                validator=twf.validators.OneOf(
193
                    valid,
194
                    if_invalid=[],
195
                    if_missing=[],
196
                ),
197
            ),
198
        ]
199

    
200
    def handle_search_fields(self, query, search, state, subqueries):
201
        if state != ITEMS:
202
            return
203

    
204
        states = []
205
        for value in search.get('state'):
206
            try:
207
                states.append(int(value))
208
            except (ValueError, TypeError):
209
                try:
210
                    states.append(StateName.statename_to_value(value))
211
                except:
212
                    # On ignore silencieusement un critère de recherche erroné.
213
                    pass
214

    
215
        if states:
216
            query.add_filter(Event.current_state.in_(states))
217

    
218
    def get_sort_criterion(self, query, column):
219
        columns = {
220
            'details': StateName.order,
221
            'problem': StateName.statename.in_([u'OK', u'UP']),
222
        }
223
        return columns.get(column)
224