Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

vigiboard / vigiboard / controllers / plugins / details.py @ ecf084d9

History | View | Annotate | Download (8.84 KB)

1
# -*- coding: utf-8 -*-
2
# vim:set expandtab tabstop=4 shiftwidth=4:
3
################################################################################
4
#
5
# Copyright (C) 2007-2015 CS-SI
6
#
7
# This program is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License version 2 as
9
# published by the Free Software Foundation.
10
#
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
################################################################################
20

    
21
"""
22
Un plugin pour VigiBoard qui ajoute une colonne avec les liens vers les
23
entrées d'historiques liées à l'événement, ainsi que les liens vers les
24
applications externes.
25
"""
26

    
27
import urllib
28
from tg import config, url, request
29
from pylons.i18n import lazy_ugettext as l_
30
import tw.forms as twf
31
from sqlalchemy.sql.expression import null as expr_null, union_all
32
from sqlalchemy import func
33

    
34
from repoze.what.predicates import has_permission, in_group
35
from vigilo.turbogears.helpers import get_current_user
36

    
37
from vigilo.models.session import DBSession
38
from vigilo.models.tables import Event, CorrEvent, Host, LowLevelService, \
39
    StateName, Map, MapNode, MapNodeHost, MapGroup
40
from vigilo.models.tables.secondary_tables import MAP_GROUP_TABLE
41

    
42
from vigiboard.controllers.plugins import VigiboardRequestPlugin, ITEMS
43

    
44

    
45
class PluginDetails(VigiboardRequestPlugin):
46
    """
47
    Plugin qui ajoute des liens vers les historiques et les applications
48
    externes.
49
    """
50

    
51
    def get_json_data(self, idcorrevent, *args, **kwargs):
52
        """
53
        Renvoie les éléments pour l'affichage de la fenêtre de dialogue
54
        contenant des détails sur un événement corrélé.
55

56
        @param idcorrevent: identifiant de l'événement corrélé.
57
        @type idcorrevent: C{int}
58
        """
59

    
60
        # Obtention de données sur l'événement et sur son historique
61
        host_query = DBSession.query(
62
            Host.idhost.label("idsupitem"),
63
            Host.idhost.label("idhost"),
64
            Host.name.label("host"),
65
            expr_null().label("service"),
66
        )
67
        lls_query = DBSession.query(
68
            LowLevelService.idservice.label("idsupitem"),
69
            Host.idhost.label("idhost"),
70
            Host.name.label("host"),
71
            LowLevelService.servicename.label("service"),
72
        ).join(
73
            (Host, Host.idhost == LowLevelService.idhost),
74
        )
75
        supitems = union_all(lls_query, host_query, correlate=False).alias()
76
        event = DBSession.query(
77
            CorrEvent.idcorrevent,
78
            CorrEvent.idcause,
79
            supitems.c.idhost,
80
            supitems.c.host,
81
            supitems.c.service,
82
            Event.message,
83
            Event.initial_state,
84
            Event.current_state,
85
            Event.peak_state
86
        ).join(
87
            (Event, Event.idevent == CorrEvent.idcause),
88
            (supitems, supitems.c.idsupitem == Event.idsupitem),
89
        ).filter(CorrEvent.idcorrevent == idcorrevent
90
        ).first()
91

    
92
        # On détermine les cartes auxquelles cet utilisateur a accès.
93
        user_maps = []
94
        max_maps = int(config['max_maps'])
95
        is_manager = config.is_manager.is_met(request.environ)
96
        if max_maps != 0 and (is_manager or
97
            has_permission('vigimap-access').is_met(request.environ)):
98
            items = DBSession.query(
99
                    Map.idmap,
100
                    Map.title,
101
                    func.lower(Map.title),
102
                ).distinct(
103
                ).join(
104
                    (MAP_GROUP_TABLE, MAP_GROUP_TABLE.c.idmap == Map.idmap),
105
                    (MapGroup, MapGroup.idgroup == MAP_GROUP_TABLE.c.idgroup),
106
                    (MapNodeHost, MapNodeHost.idmap == Map.idmap),
107
                ).order_by(func.lower(Map.title).asc()
108
                ).filter(MapNodeHost.idhost == event.idhost)
109

    
110
            if not is_manager:
111
                mapgroups = get_current_user().mapgroups(only_direct=True)
112
                # pylint: disable-msg=E1103
113
                items = items.filter(MapGroup.idgroup.in_(mapgroups))
114

    
115
            # La valeur -1 supprime la limite.
116
            if max_maps > 0:
117
                # On limite au nombre maximum de cartes demandés + 1.
118
                # Un message sera affiché s'il y a effectivement plus
119
                # de cartes que la limite configurée.
120
                items = items.limit(max_maps + 1)
121

    
122
            user_maps = [(m.idmap, m.title) for m in items.all()]
123

    
124
        context = {
125
            'idcorrevent': idcorrevent,
126
            'host': event.host,
127
            'service': event.service,
128
            'message': event.message,
129
            'maps': user_maps,
130
            'current_state': StateName.value_to_statename(event.current_state),
131
            'initial_state': StateName.value_to_statename(event.initial_state),
132
            'peak_state': StateName.value_to_statename(event.peak_state),
133
        }
134

    
135
        eventdetails = {}
136
        for edname, edlink in enumerate(config['vigiboard_links.eventdetails']):
137
            # Évite que les gardes ne se polluent entre elles.
138
            local_ctx = context.copy()
139

    
140
            # Les liens peuvent être conditionnés à l'aide
141
            # d'une expression ou d'un callable qui agira
142
            # comme un prédicat de test.
143
            if 'only_if' in edlink:
144
                if callable(edlink['only_if']):
145
                    display_link = edlink['only_if'](local_ctx)
146
                else:
147
                    display_link = edlink['only_if']
148
                if not display_link:
149
                    continue
150

    
151
            if callable(edlink['uri']):
152
                uri = edlink['uri'](local_ctx)
153
            else:
154
                uri = edlink['uri'] % local_ctx
155

    
156
            eventdetails[unicode(edname)] = {
157
                'url': url(uri),
158
                'target': edlink.get('target', '_blank')
159
            }
160

    
161
        return dict(
162
                current_state = StateName.value_to_statename(
163
                                    event.current_state),
164
                initial_state = StateName.value_to_statename(
165
                                    event.initial_state),
166
                peak_state = StateName.value_to_statename(
167
                                    event.peak_state),
168
                idcorrevent = idcorrevent,
169
                host = event.host,
170
                service = event.service,
171
                eventdetails = eventdetails,
172
                maps = user_maps,
173
                idcause = event.idcause,
174
            )
175

    
176
    def get_data(self, event):
177
        state = StateName.value_to_statename(event[0].cause.current_state)
178
        peak_state = StateName.value_to_statename(event[0].cause.peak_state)
179
        init_state = StateName.value_to_statename(event[0].cause.initial_state)
180
        return {
181
            'state': state,
182
            'peak_state': peak_state,
183
            'initial_state': init_state,
184
            'id': event[0].idcorrevent,
185
        }
186

    
187
    def get_search_fields(self):
188
        states = DBSession.query(StateName.idstatename, StateName.statename
189
                    ).order_by(StateName.order.asc()).all()
190
        # Liste des valeurs acceptées pour la validation.
191
        valid = []
192
        # Liste des options présentes dans le champ de sélection.
193
        options = []
194
        for s in states:
195
            valid.extend([str(s.idstatename), s.statename])
196
            options.append( (
197
                str(s.idstatename),
198
                s.statename,
199
                {'title': l_(s.statename)}
200
            ) )
201

    
202
        return [
203
            twf.MultipleSelectField(
204
                'state',
205
                label_text=l_('Current state'),
206
                options=options,
207
                validator=twf.validators.OneOf(
208
                    valid,
209
                    if_invalid=[],
210
                    if_missing=[],
211
                ),
212
            ),
213
        ]
214

    
215
    def handle_search_fields(self, query, search, state, subqueries):
216
        if state != ITEMS:
217
            return
218

    
219
        states = []
220
        for value in search.get('state'):
221
            try:
222
                states.append(int(value))
223
            except (ValueError, TypeError):
224
                try:
225
                    states.append(StateName.statename_to_value(value))
226
                except:
227
                    # On ignore silencieusement un critère de recherche erroné.
228
                    pass
229

    
230
        if states:
231
            query.add_filter(Event.current_state.in_(states))
232

    
233
    def get_sort_criterion(self, query, column):
234
        columns = {
235
            'details': StateName.order,
236
            'problem': StateName.statename.in_([u'OK', u'UP']),
237
        }
238
        return columns.get(column)
239