Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

vigiboard / vigiboard / controllers / root.py @ 5f2cd70a

History | View | Annotate | Download (15.4 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 vigiboard.model import DBSession
12
from vigiboard.model import Event, EventHistory, EventsAggregate, \
13
                            Host, HostGroup, \
14
                            User
15
from repoze.what.predicates import Any, not_anonymous
16
from vigiboard.widgets.edit_event import edit_event_status_options
17
from vigiboard.controllers.vigiboardrequest import VigiboardRequest
18
from vigiboard.controllers.vigiboard_controller import VigiboardRootController
19

    
20
__all__ = ('RootController', )
21

    
22
class RootController(VigiboardRootController):
23
    
24
    """
25
    Le controller général de vigiboard
26
    """
27

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

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

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

    
63
        try:
64
            page = int(page)
65
        except ValueError:
66
            abort(404)
67

    
68
        if page < 1:
69
            page = 1
70

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

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

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

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

    
106
        # Calcul des éléments à afficher et du nombre de pages possibles
107
        total_rows = aggregates.num_rows()
108
        item_per_page = int(config['vigiboard_item_per_page'])
109

    
110
        if total_rows <= item_per_page * (page-1):
111
            page = 1
112
        id_first_row = item_per_page * (page-1)
113
        id_last_row = min(id_first_row + item_per_page, total_rows)
114

    
115
        aggregates.format_events(id_first_row, id_last_row)
116
        aggregates.generate_tmpl_context()
117

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

145
        @param id: identifiant de l'évènement
146
        """
147

    
148
        # Obtention de données sur l'évènement et sur son historique
149
        username = request.environ.get('repoze.who.identity'
150
                    ).get('repoze.who.userid')
151
        user = User.by_user_name(username)
152

    
153
        event = DBSession.query(
154
                        EventsAggregate.severity,
155
                        Event.hostname,
156
                        Event.servicename,
157
                        Event.idevent
158
                 ).join(
159
                    (Event, EventsAggregate.idcause == Event.idevent),
160
                    (HostGroup, Event.hostname == HostGroup.hostname),
161
                 ).filter(HostGroup.groupname.in_(user.groups)
162
                 ).filter(EventsAggregate.idaggregate == idaggregate).one()
163

    
164
        initial_state = DBSession.query(
165
                    EventHistory,
166
                 ).filter(EventHistory.idevent == event.idevent
167
                 ).order_by(asc(EventHistory.timestamp)
168
                 ).order_by(asc(EventHistory.type_action))
169

    
170
        if initial_state.count() > 0 :
171
            for i in initial_state:
172
                if i.value != '' and i.value is not None:
173
                    initial_state = i.value
174
                    break
175
        else :
176
            initial_state = 0
177

    
178
        severity = (
179
                _('None'), _('OK'), _('Suppressed'), _('Initial'),
180
                _('Maintenance'), _('Minor'), _('Major'), _('Critical')
181
            )
182
        if event.severity is None:
183
            current_state = _('Unknown')
184
        else:
185
            current_state = severity[event.severity]
186

    
187
        eventdetails = {}
188
        for edname, edlink in \
189
                config['vigiboard_links.eventdetails'].iteritems():
190

    
191
            eventdetails[edname] = edlink[1] % {
192
                    'idaggregate': idaggregate,
193
                    'host': event.hostname,
194
                    'service': event.servicename
195
                    }
196

    
197
        return dict(
198
                initial_state = severity[int(initial_state)],
199
                current_state = current_state,
200
                idaggregate = idaggregate,
201
                host = event.hostname,
202
                service = event.servicename,
203
                eventdetails = eventdetails,
204
            )
205

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

215
        @param idevent: identifiant de l'évènement souhaité
216
        """
217

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

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

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

263
        @param host: Nom de l'hôte souhaité.
264
        @param service: Nom du service souhaité
265
        """
266

    
267
        username = request.environ['repoze.who.identity']['repoze.who.userid']
268
        events = VigiboardRequest(User.by_user_name(username))
269
        events.add_filter(Event.hostname == host,
270
                Event.servicename == service)
271
        del events.filter[2]
272

    
273
        # Vérification qu'il y a au moins 1 évènement qui correspond
274
        if events.num_rows() == 0 :
275
            redirect('/')
276
       
277
        events.format_events(0, events.num_rows())
278
        events.format_history()
279
        events.generate_tmpl_context() 
280
        return dict(
281
                    events = events.events,
282
                    rows_info = {
283
                        'id_first_row': 1,
284
                        'id_last_row': 1,
285
                        'total_rows': 1,
286
                    },
287
                    pages = [1],
288
                    page = 1,
289
                    event_edit_status_options = edit_event_status_options,
290
                    history = events.hist,
291
                    hist_error = True,
292
                    plugin_context = events.context_fct,
293
                    search = {
294
                        'host': None,
295
                        'service': None,
296
                        'output': None,
297
                        'tt': None
298
                    }
299
                )
300

    
301
    @validate(validators={
302
        "id":validators.Regex(r'^[^,]+(,[^,]*)*,?$'),
303
#        "trouble_ticket":validators.Regex(r'^[0-9]*$'),
304
        "status":validators.OneOf(['NoChange', 'None', 'Acknowledged',
305
                'AAClosed'])
306
        }, error_handler=process_form_errors)
307
    @require(Any(not_anonymous(), msg=_("You need to be authenticated")))
308
    def update(self,**krgv):
309
        
310
        """
311
        Mise à jour d'un évènement suivant les arguments passés.
312
        Cela peut être un changement de ticket ou un changement de statut.
313
        
314
        @param krgv['id']: Le ou les identifiants des évènements à traiter
315
        @param krgv['tt']: Nouveau numéro du ticket associé.
316
        @param krgv['status']: Nouveau status de/des évènements.
317
        """
318
        
319
        # Si l'utilisateur édite plusieurs évènements à la fois,
320
        # il nous faut chacun des identifiants
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
                event.trouble_ticket = krgv['trouble_ticket']
349
                history = EventHistory(
350
                        type_action="Ticket change",
351
                        idevent=event.idcause,
352
                        value='',
353
                        text='',
354
                        username=username,
355
                    )
356
                DBSession.add(history)   
357

    
358
            if krgv['status'] != 'NoChange' :
359
                event.status = krgv['status']
360
                history = EventHistory(
361
                        type_action="Acknowlegement change state",
362
                        idevent=event.idcause,
363
                        value='',
364
                        text='',
365
                        username=username,
366
                    )
367
                DBSession.add(history)
368

    
369
        DBSession.flush()       
370
        flash(_('Updated successfully'))
371
        redirect(request.environ.get('HTTP_REFERER', url('/')))
372

    
373

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

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

    
407
    @validate(validators= {"refresh": validators.Int()},
408
            error_handler = process_form_errors)
409
    @expose('json')
410
    def set_refresh(self, refresh):
411
        """
412
        Save refresh time
413
        """
414
        session['refresh'] = refresh
415
        session.save()
416
        return dict(ret= 'ok')