Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

vigiboard / vigiboard / controllers / root.py @ 10848680

History | View | Annotate | Download (16 KB)

1
# -*- coding: utf-8 -*-
2
# vim:set expandtab tabstop=4 shiftwidth=4: 
3
"""Vigiboard Controller"""
4

    
5
from tg import expose, validate, require, flash, \
6
    tmpl_context, request, config, session, redirect, url
7
from tw.forms import validators 
8
from pylons.i18n import ugettext as _
9
from pylons.controllers.util import abort
10
from sqlalchemy import asc
11
from datetime import datetime
12
import math
13

    
14
from vigiboard.model import DBSession
15
from vigiboard.model import Event, EventHistory, EventsAggregate, \
16
                            Host, HostGroup, \
17
                            User
18
from repoze.what.predicates import Any, not_anonymous
19
from vigiboard.widgets.edit_event import edit_event_status_options
20
from vigiboard.controllers.vigiboardrequest import VigiboardRequest
21
from vigiboard.controllers.vigiboard_controller import VigiboardRootController
22

    
23
__all__ = ('RootController', )
24

    
25
class RootController(VigiboardRootController):
26
    
27
    """
28
    Le controller général de vigiboard
29
    """
30

    
31
    def process_form_errors(self, *argv, **kwargv):
32
        """
33
        Gestion des erreurs de validation : On affiche les erreurs
34
        puis on redirige vers la dernière page accédée.
35
        """
36
        for k in tmpl_context.form_errors:
37
            flash("'%s': %s" % (k, tmpl_context.form_errors[k]), 'error')
38
        if request.environ.get('HTTP_REFERER') :
39
            redirect(request.environ.get('HTTP_REFERER'
40
                ).split(request.environ.get('HTTP_HOST'))[1])
41
        else :
42
            redirect('/')
43

    
44
    @expose('vigiboard.html')
45
    @require(Any(not_anonymous(), msg=_("You need to be authenticated")))
46
    def default(self, page = None, host = None, service = None, output = None,
47
            trouble_ticket=None, *argv, **krgv):
48
            
49
        """
50
        Page d'accueil de Vigiboard. Elle affiche, suivant la page demandée
51
        (page 1 par defaut), la liste des évènements, rangés par ordre de prise
52
        en compte, puis de sévérité.
53
        Pour accéder à cette page, l'utilisateur doit être authentifié.
54

55
        @param page: Numéro de la page souhaitée, commence à 1
56
        @param host: Si l'utilisateur souhaite sélectionner seulement certains
57
                     évènements suivant leur hôte, il peut placer une expression
58
                     ici en suivant la structure du LIKE en SQL
59
        @param service: Idem que host mais sur les services
60
        @param output: Idem que host mais sur le text explicatif
61
        @param trouble_ticket: Idem que host mais sur les tickets attribués
62
        """
63
        if page is None:
64
            page = 1
65

    
66
        try:
67
            page = int(page)
68
        except ValueError:
69
            abort(404)
70

    
71
        if page < 1:
72
            page = 1
73

    
74
        username = request.environ['repoze.who.identity']['repoze.who.userid']
75
        aggregates = VigiboardRequest(User.by_user_name(username))
76
        
77
        search = {
78
            'host': '',
79
            'service': '',
80
            'output': '',
81
            'tt': ''
82
        }
83
        # Application des filtres si nécessaire
84
        if host :
85
            search['host'] = host
86
            host = host.replace('%', '\\%').replace('_', '\\_') \
87
                    .replace('*', '%').replace('?', '_')
88
            aggregates.add_filter(Event.hostname.like('%%%s%%' % host))
89

    
90
        if service :
91
            search['service'] = service
92
            service = service.replace('%', '\\%').replace('_', '\\_') \
93
                    .replace('*', '%').replace('?', '_')
94
            aggregates.add_filter(Event.servicename.like('%%%s%%' % service))
95

    
96
        if output :
97
            search['output'] = output
98
            output = output.replace('%', '\\%').replace('_', '\\_') \
99
                    .replace('*', '%').replace('?', '_')
100
            aggregates.add_filter(Event.message.like('%%%s%%' % output))
101

    
102
        if trouble_ticket :
103
            search['tt'] = trouble_ticket
104
            trouble_ticket = trouble_ticket.replace('%', '\\%') \
105
                    .replace('_', '\\_').replace('*', '%').replace('?', '_')
106
            aggregates.add_filter(EventsAggregate.trouble_ticket.like(
107
                '%%%s%%' % trouble_ticket))
108

    
109
        # Calcul des éléments à afficher et du nombre de pages possibles
110
        total_rows = aggregates.num_rows()
111
        items_per_page = int(config['vigiboard_items_per_page'])
112

    
113
        if total_rows <= items_per_page * (page-1):
114
            page = 1
115
        id_first_row = items_per_page * (page-1)
116
        id_last_row = min(id_first_row + items_per_page, total_rows)
117

    
118
        aggregates.format_events(id_first_row, id_last_row)
119
        aggregates.generate_tmpl_context()
120
        nb_pages = int(math.ceil(total_rows / (items_per_page + 0.0)))
121

    
122
        return dict(
123
               events = aggregates.events,
124
               rows_info = {
125
                   'id_first_row': id_first_row + 1,
126
                   'id_last_row': id_last_row,
127
                   'total_rows': total_rows,
128
               },
129
               pages = range(1, nb_pages + 1),
130
               page = page,
131
               event_edit_status_options = edit_event_status_options,
132
               history = [],
133
               hist_error = False,
134
               plugin_context = aggregates.context_fct,
135
               search = search,
136
            )
137
      
138
    @validate(validators={'idaggregate':validators.String(not_empty=True)},
139
            error_handler=process_form_errors)
140
    @expose('json')
141
    @require(Any(not_anonymous(), msg=_("You need to be authenticated")))
142
    def history_dialog(self, idaggregate):
143
        
144
        """
145
        JSon renvoyant les éléments pour l'affichage de la fenêtre de dialogue
146
        contenant des liens internes et externes.
147
        Pour accéder à cette page, l'utilisateur doit être authentifié.
148

149
        @param id: identifiant de l'évènement
150
        """
151

    
152
        # Obtention de données sur l'évènement et sur son historique
153
        username = request.environ.get('repoze.who.identity'
154
                    ).get('repoze.who.userid')
155
        user = User.by_user_name(username)
156

    
157
        event = DBSession.query(
158
                        EventsAggregate.initial_severity,
159
                        EventsAggregate.current_severity,
160
                        EventsAggregate.peak_severity,
161
                        Event.hostname,
162
                        Event.servicename,
163
                        Event.idevent,
164
                 ).join(
165
                    (Event, EventsAggregate.idcause == Event.idevent),
166
                    (HostGroup, Event.hostname == HostGroup.hostname),
167
                 ).filter(HostGroup.groupname.in_(user.groups)
168
                 ).filter(EventsAggregate.idaggregate == idaggregate
169
                 ).one()
170

    
171
        history = DBSession.query(
172
                    EventHistory,
173
                 ).filter(EventHistory.idevent == event.idevent
174
                 ).order_by(asc(EventHistory.timestamp)
175
                 ).order_by(asc(EventHistory.type_action)).all()
176

    
177
        current_severity = VigiboardRequest.get_severity(event.current_severity)
178
        initial_severity = VigiboardRequest.get_severity(event.initial_severity)
179
        peak_severity = VigiboardRequest.get_severity(event.peak_severity)
180

    
181
        eventdetails = {}
182
        for edname, edlink in \
183
                config['vigiboard_links.eventdetails'].iteritems():
184

    
185
            eventdetails[edname] = edlink[1] % {
186
                    'idaggregate': idaggregate,
187
                    'host': event.hostname,
188
                    'service': event.servicename
189
                    }
190

    
191
        return dict(
192
                initial_state = VigiboardRequest.severity[initial_severity],
193
                current_state = VigiboardRequest.severity[current_severity],
194
                peak_state = VigiboardRequest.severity[peak_severity],
195
                idaggregate = idaggregate,
196
                host = event.hostname,
197
                service = event.servicename,
198
                eventdetails = eventdetails,
199
            )
200

    
201
    @validate(validators={'idaggregate':validators.String(not_empty=True)},
202
            error_handler=process_form_errors)
203
    @expose('vigiboard.html')
204
    @require(Any(not_anonymous(), msg=_("You need to be authenticated")))
205
    def event(self, idaggregate):
206
        """
207
        Affichage de l'historique d'un évènement.
208
        Pour accéder à cette page, l'utilisateur doit être authentifié.
209

210
        @param idevent: identifiant de l'évènement souhaité
211
        """
212

    
213
        username = request.environ['repoze.who.identity']['repoze.who.userid']
214
        events = VigiboardRequest(User.by_user_name(username))
215
        events.add_filter(EventsAggregate.idaggregate == idaggregate)
216
        
217
        # Vérification que l'évènement existe
218
        if events.num_rows() != 1 :
219
            flash(_('Error in DB'), 'error')
220
            redirect('/')
221
       
222
        events.format_events(0, 1)
223
        events.format_history()
224
        events.generate_tmpl_context() 
225

    
226
        return dict(
227
                    events = events.events,
228
                    rows_info = {
229
                        'id_first_row': 1,
230
                        'id_last_row': 1,
231
                        'total_rows': 1,
232
                    },
233
                    pages = [1],
234
                    page = 1,
235
                    event_edit_status_options = edit_event_status_options,
236
                    history = events.hist,
237
                    hist_error = True,
238
                    plugin_context = events.context_fct,
239
                    search = {
240
                        'host': None,
241
                        'service': None,
242
                        'output': None,
243
                        'tt': None
244
                    }
245
                )
246

    
247
    @validate(validators={'host':validators.NotEmpty(),
248
        'service':validators.NotEmpty()}, error_handler=process_form_errors)
249
    @expose('vigiboard.html')
250
    @require(Any(not_anonymous(), msg=_("You need to be authenticated")))
251
    def host_service(self, host, service):
252
        
253
        """
254
        Affichage de l'historique de l'ensemble des évènements correspondant
255
        au host et service demandé.
256
        Pour accéder à cette page, l'utilisateur doit être authentifié.
257

258
        @param host: Nom de l'hôte souhaité.
259
        @param service: Nom du service souhaité
260
        """
261

    
262
        username = request.environ['repoze.who.identity']['repoze.who.userid']
263
        events = VigiboardRequest(User.by_user_name(username))
264
        events.add_filter(Event.hostname == host,
265
                Event.servicename == service)
266
        del events.filter[2]
267

    
268
        # Vérification qu'il y a au moins 1 évènement qui correspond
269
        if events.num_rows() == 0 :
270
            redirect('/')
271

    
272
        events.format_events(0, events.num_rows())
273
        events.format_history()
274
        events.generate_tmpl_context()
275

    
276
        return dict(
277
                    events = events.events,
278
                    rows_info = {
279
                        'id_first_row': 1,
280
                        'id_last_row': 1,
281
                        'total_rows': 1,
282
                    },
283
                    pages = [1],
284
                    page = 1,
285
                    event_edit_status_options = edit_event_status_options,
286
                    history = events.hist,
287
                    hist_error = True,
288
                    plugin_context = events.context_fct,
289
                    search = {
290
                        'host': None,
291
                        'service': None,
292
                        'output': None,
293
                        'tt': None
294
                    }
295
                )
296

    
297
    @validate(validators={
298
        "id":validators.Regex(r'^[^,]+(,[^,]*)*,?$'),
299
#        "trouble_ticket":validators.Regex(r'^[0-9]*$'),
300
        "status":validators.OneOf(['NoChange', 'None', 'Acknowledged',
301
                'AAClosed'])
302
        }, error_handler=process_form_errors)
303
    @require(Any(not_anonymous(), msg=_("You need to be authenticated")))
304
    def update(self,**krgv):
305
        
306
        """
307
        Mise à jour d'un évènement suivant les arguments passés.
308
        Cela peut être un changement de ticket ou un changement de statut.
309
        
310
        @param krgv['id']: Le ou les identifiants des évènements à traiter
311
        @param krgv['tt']: Nouveau numéro du ticket associé.
312
        @param krgv['status']: Nouveau status de/des évènements.
313
        """
314
        
315
        # Si l'utilisateur édite plusieurs évènements à la fois,
316
        # il nous faut chacun des identifiants
317

    
318
        if krgv['id'] is None:
319
            flash(_('No event has been selected'), 'warning')
320
            raise redirect(request.environ.get('HTTP_REFERER', url('/')))
321

    
322
        ids = krgv['id'].split(',')
323
       
324
        if len(ids) > 1 :
325
            ids = ids[:-1]
326
        
327
        username = request.environ['repoze.who.identity']['repoze.who.userid']
328
        events = VigiboardRequest(User.by_user_name(username))
329
        events.add_filter(EventsAggregate.idaggregate.in_(ids))
330
        
331
        # Vérification que au moins un des identifiants existe et est éditable
332
        if events.num_rows() <= 0 :
333
            flash(_('No access to this event'), 'error')
334
            redirect('/')
335
        
336
        # Modification des évènements et création d'un historique
337
        # pour chacun d'eux
338
        
339
        username = request.environ['repoze.who.identity']['repoze.who.userid']
340

    
341
        for req in events.req:
342
            if isinstance(req, EventsAggregate):
343
                event = req
344
            else:
345
                event = req[0]
346

    
347
            if krgv['trouble_ticket'] != '' :
348
                history = EventHistory(
349
                        type_action="Ticket change",
350
                        idevent=event.idcause,
351
                        value=krgv['trouble_ticket'],
352
                        text=_("Changed trouble ticket from '%s' to '%s'") % (
353
                            event.trouble_ticket, krgv['trouble_ticket']
354
                        ),
355
                        username=username,
356
                        timestamp=datetime.now(),
357
                    )
358
                DBSession.add(history)   
359
                event.trouble_ticket = krgv['trouble_ticket']
360

    
361
            if krgv['status'] != 'NoChange' :
362
                history = EventHistory(
363
                        type_action="Acknowlegement change state",
364
                        idevent=event.idcause,
365
                        value=krgv['status'],
366
                        text=_("Changed acknowledgement status from '%s' to '%s'") % (
367
                            event.status, krgv['status']
368
                        ),
369
                        username=username,
370
                        timestamp=datetime.now(),
371
                    )
372
                DBSession.add(history)
373
                event.status = krgv['status']
374

    
375
        DBSession.flush()
376
        flash(_('Updated successfully'))
377
        redirect(request.environ.get('HTTP_REFERER', url('/')))
378

    
379

    
380
    @validate(validators={"plugin_name":validators.OneOf(
381
        [i for [i, j] in config.get('vigiboard_plugins', [])])},
382
                error_handler = process_form_errors)
383
    @expose('json')
384
    def get_plugin_value(self, plugin_name, *arg, **krgv):
385
        """
386
        Permet aux plugins de pouvoir récupérer des valeurs Json
387
        """
388
        plugins = config['vigiboard_plugins']
389
        if plugins is None:
390
            return
391

    
392
        plugin = [i for i in plugins if i[0] == plugin_name][0]
393
        try:
394
            mypac = __import__(
395
                'vigiboard.controllers.vigiboard_plugin.' + plugin[0],
396
                globals(), locals(), [plugin[1]], -1)
397
            plug = getattr(mypac, plugin[1])()
398
            return plug.controller(*arg, **krgv)
399
        except:
400
            raise
401
    
402
#    @validate(validators= {"fontsize": validators.Int()},
403
#                    error_handler = process_form_errors)
404
    @expose('json')
405
    def set_fontsize(self, fontsize):
406
        """
407
        Save font size
408
        """
409
        session['fontsize'] = fontsize
410
        session.save()
411
        return dict(ret= 'ok')
412

    
413
    @validate(validators= {"refresh": validators.Int()},
414
            error_handler = process_form_errors)
415
    @expose('json')
416
    def set_refresh(self, refresh):
417
        """
418
        Save refresh time
419
        """
420
        session['refresh'] = refresh
421
        session.save()
422
        return dict(ret= 'ok')
423