vigiboard / vigiboard / controllers / root.py @ cf3c2494
History | View | Annotate | Download (34 KB)
1 | 19e88cb8 | Thomas ANDREJAK | # -*- coding: utf-8 -*-
|
---|---|---|---|
2 | e3c52cfd | Aurelien BOMPARD | # vim:set expandtab tabstop=4 shiftwidth=4:
|
3 | a77de887 | Francois POIROTTE | ################################################################################
|
4 | #
|
||
5 | 3b537383 | Francois POIROTTE | # Copyright (C) 2007-2011 CS-SI
|
6 | a77de887 | Francois POIROTTE | #
|
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 | e181e86c | Francois POIROTTE | """VigiBoard Controller"""
|
22 | 19e88cb8 | Thomas ANDREJAK | |
23 | 7365fb51 | Francois POIROTTE | from datetime import datetime |
24 | from time import mktime |
||
25 | import math |
||
26 | |||
27 | 55759768 | Aurelien BOMPARD | from tg.exceptions import HTTPNotFound, HTTPInternalServerError |
28 | aa0788a2 | Francois POIROTTE | from tg import expose, validate, require, flash, \ |
29 | df25ac35 | Francois POIROTTE | tmpl_context, request, config, session, redirect |
30 | 3e6ee4db | Francois POIROTTE | from tw.forms import validators |
31 | 88cac5bb | Francois POIROTTE | from pylons.i18n import ugettext as _, lazy_ugettext as l_ |
32 | 6ab72614 | Vincent QUEMENER | from sqlalchemy import asc |
33 | 97f6d842 | Vincent QUEMENER | from sqlalchemy.sql import func |
34 | eec46cb0 | Vincent QUEMENER | from sqlalchemy.orm import aliased |
35 | cf3c2494 | Vincent QUEMENER | from sqlalchemy.orm import contains_eager |
36 | 9e0ea30e | Francois POIROTTE | from repoze.what.predicates import Any, All, in_group, \ |
37 | 55759768 | Aurelien BOMPARD | has_permission, not_anonymous, \ |
38 | NotAuthorizedError
|
||
39 | 1a1e8c17 | Francois POIROTTE | from formencode import schema |
40 | 65383903 | Francois POIROTTE | from pkg_resources import working_set |
41 | ee3ae8c8 | Francois POIROTTE | |
42 | e7e3d45e | Francois POIROTTE | from vigilo.models.session import DBSession |
43 | a05b9a37 | Francois POIROTTE | from vigilo.models.tables import Event, EventHistory, CorrEvent, Host, \ |
44 | 9e0ea30e | Francois POIROTTE | SupItem, SupItemGroup, LowLevelService, \ |
45 | eec46cb0 | Vincent QUEMENER | StateName, State, DataPermission |
46 | 0bd9c069 | Francois POIROTTE | from vigilo.models.tables.grouphierarchy import GroupHierarchy |
47 | 080abea3 | Francois POIROTTE | from vigilo.models.functions import sql_escape_like |
48 | eec46cb0 | Vincent QUEMENER | from vigilo.models.tables.secondary_tables import EVENTSAGGREGATE_TABLE, \ |
49 | USER_GROUP_TABLE
|
||
50 | 7365fb51 | Francois POIROTTE | |
51 | e307e626 | Francois POIROTTE | from vigilo.turbogears.controllers.autocomplete import AutoCompleteController |
52 | ea0e5dfb | Francois POIROTTE | from vigilo.turbogears.controllers.proxy import ProxyController |
53 | 98a40b9f | Aurelien BOMPARD | from vigilo.turbogears.controllers.api.root import ApiRootController |
54 | 195aa50d | Francois POIROTTE | from vigilo.turbogears.helpers import get_current_user |
55 | |||
56 | 7365fb51 | Francois POIROTTE | from vigiboard.controllers.vigiboardrequest import VigiboardRequest |
57 | from vigiboard.controllers.vigiboard_controller import VigiboardRootController |
||
58 | 2dbc5942 | Francois POIROTTE | |
59 | 7365fb51 | Francois POIROTTE | from vigiboard.widgets.edit_event import edit_event_status_options |
60 | 2dbc5942 | Francois POIROTTE | from vigiboard.widgets.search_form import create_search_form, get_calendar_lang |
61 | 19e88cb8 | Thomas ANDREJAK | |
62 | e3c52cfd | Aurelien BOMPARD | __all__ = ('RootController', 'get_last_modification_timestamp', |
63 | 97f6d842 | Vincent QUEMENER | 'date_to_timestamp')
|
64 | 19e88cb8 | Thomas ANDREJAK | |
65 | 4d783824 | Francois POIROTTE | # pylint: disable-msg=R0201
|
66 | b8500d1a | Thomas ANDREJAK | class RootController(VigiboardRootController): |
67 | 19e88cb8 | Thomas ANDREJAK | """
|
68 | Le controller général de vigiboard
|
||
69 | """
|
||
70 | e307e626 | Francois POIROTTE | autocomplete = AutoCompleteController() |
71 | ea0e5dfb | Francois POIROTTE | nagios = ProxyController('nagios', '/nagios/', |
72 | not_anonymous(l_('You need to be authenticated')))
|
||
73 | 98a40b9f | Aurelien BOMPARD | api = ApiRootController("/api")
|
74 | ea0e5dfb | Francois POIROTTE | |
75 | ef31cc13 | Francois POIROTTE | |
76 | f2e30877 | Francois POIROTTE | # Prédicat pour la restriction de l'accès aux interfaces.
|
77 | a5f99051 | Francois POIROTTE | # L'utilisateur doit avoir la permission "vigiboard-access"
|
78 | f2e30877 | Francois POIROTTE | # ou appartenir au groupe "managers" pour accéder à VigiBoard.
|
79 | access_restriction = All( |
||
80 | not_anonymous(msg=l_("You need to be authenticated")),
|
||
81 | Any(in_group('managers'),
|
||
82 | a5f99051 | Francois POIROTTE | has_permission('vigiboard-access'),
|
83 | msg=l_("You don't have access to VigiBoard"))
|
||
84 | f2e30877 | Francois POIROTTE | ) |
85 | |||
86 | aa0788a2 | Francois POIROTTE | def process_form_errors(self, *argv, **kwargv): |
87 | 19e88cb8 | Thomas ANDREJAK | """
|
88 | Gestion des erreurs de validation : On affiche les erreurs
|
||
89 | puis on redirige vers la dernière page accédée.
|
||
90 | """
|
||
91 | aa0788a2 | Francois POIROTTE | for k in tmpl_context.form_errors: |
92 | flash("'%s': %s" % (k, tmpl_context.form_errors[k]), 'error') |
||
93 | a9a4679d | Francois POIROTTE | redirect(request.environ.get('HTTP_REFERER', '/')) |
94 | 19e88cb8 | Thomas ANDREJAK | |
95 | 4c08cd96 | Francois POIROTTE | @expose('json') |
96 | def handle_validation_errors_json(self, *args, **kwargs): |
||
97 | kwargs['errors'] = tmpl_context.form_errors
|
||
98 | return dict(kwargs) |
||
99 | e3c52cfd | Aurelien BOMPARD | |
100 | e307e626 | Francois POIROTTE | class DefaultSchema(schema.Schema): |
101 | e181e86c | Francois POIROTTE | """Schéma de validation de la méthode default."""
|
102 | e307e626 | Francois POIROTTE | page = validators.Int(min=1, if_missing=1, if_invalid=1) |
103 | 2dbc5942 | Francois POIROTTE | supitemgroup = validators.Int(if_missing=None, if_invalid=None) |
104 | e307e626 | Francois POIROTTE | host = validators.String(if_missing=None)
|
105 | service = validators.String(if_missing=None)
|
||
106 | output = validators.String(if_missing=None)
|
||
107 | trouble_ticket = validators.String(if_missing=None)
|
||
108 | from_date = validators.String(if_missing=None)
|
||
109 | to_date = validators.String(if_missing=None)
|
||
110 | |||
111 | @validate(
|
||
112 | validators=DefaultSchema(), |
||
113 | error_handler = process_form_errors) |
||
114 | d5ffcf1f | Vincent QUEMENER | @expose('events_table.html') |
115 | f2e30877 | Francois POIROTTE | @require(access_restriction)
|
116 | e307e626 | Francois POIROTTE | def default(self, page, supitemgroup, host, service, |
117 | output, trouble_ticket, from_date, to_date): |
||
118 | 19e88cb8 | Thomas ANDREJAK | """
|
119 | bc94248f | Francois POIROTTE | Page d'accueil de Vigiboard. Elle affiche, suivant la page demandée
|
120 | a2a22ade | Francois POIROTTE | (page 1 par defaut), la liste des événements, rangés par ordre de prise
|
121 | bc94248f | Francois POIROTTE | en compte, puis de sévérité.
|
122 | 19e88cb8 | Thomas ANDREJAK | Pour accéder à cette page, l'utilisateur doit être authentifié.
|
123 |
|
||
124 | bc94248f | Francois POIROTTE | @param page: Numéro de la page souhaitée, commence à 1
|
125 | 19e88cb8 | Thomas ANDREJAK | @param host: Si l'utilisateur souhaite sélectionner seulement certains
|
126 | a2a22ade | Francois POIROTTE | événements suivant leur hôte, il peut placer une expression
|
127 | 19e88cb8 | Thomas ANDREJAK | ici en suivant la structure du LIKE en SQL
|
128 | @param service: Idem que host mais sur les services
|
||
129 | @param output: Idem que host mais sur le text explicatif
|
||
130 | @param trouble_ticket: Idem que host mais sur les tickets attribués
|
||
131 | c9245ffc | Vincent QUEMENER |
|
132 | e3c52cfd | Aurelien BOMPARD | Cette méthode permet de satisfaire les exigences suivantes :
|
133 | - VIGILO_EXIG_VIGILO_BAC_0040,
|
||
134 | e181e86c | Francois POIROTTE | - VIGILO_EXIG_VIGILO_BAC_0070,
|
135 | - VIGILO_EXIG_VIGILO_BAC_0100,
|
||
136 | 19e88cb8 | Thomas ANDREJAK | """
|
137 | 195aa50d | Francois POIROTTE | user = get_current_user() |
138 | 97f6d842 | Vincent QUEMENER | aggregates = VigiboardRequest(user) |
139 | cf3c2494 | Vincent QUEMENER | |
140 | 911069bc | Francois POIROTTE | aggregates.add_table( |
141 | CorrEvent, |
||
142 | aggregates.items.c.hostname, |
||
143 | aggregates.items.c.servicename |
||
144 | ) |
||
145 | aggregates.add_join((Event, CorrEvent.idcause == Event.idevent)) |
||
146 | cf3c2494 | Vincent QUEMENER | aggregates.add_contains_eager(CorrEvent.cause) |
147 | aggregates.add_group_by(Event) |
||
148 | e3c52cfd | Aurelien BOMPARD | aggregates.add_join((aggregates.items, |
149 | bfd8ead8 | Vincent QUEMENER | Event.idsupitem == aggregates.items.c.idsupitem)) |
150 | 5d20c2c5 | Francois POIROTTE | aggregates.add_order_by(asc(aggregates.items.c.hostname)) |
151 | e3c52cfd | Aurelien BOMPARD | |
152 | 2dbc5942 | Francois POIROTTE | search = {} |
153 | 398c727b | Francois POIROTTE | |
154 | 19e88cb8 | Thomas ANDREJAK | # Application des filtres si nécessaire
|
155 | 24d74687 | Francois POIROTTE | if supitemgroup:
|
156 | 0bd9c069 | Francois POIROTTE | search['supitemgroup'] = supitemgroup
|
157 | aggregates.add_join((GroupHierarchy, GroupHierarchy.idchild == |
||
158 | aggregates.items.c.idsupitemgroup)) |
||
159 | aggregates.add_filter(GroupHierarchy.idparent == supitemgroup) |
||
160 | 398c727b | Francois POIROTTE | |
161 | 08d86103 | Francois POIROTTE | if host:
|
162 | 88cac5bb | Francois POIROTTE | search['host_'] = host
|
163 | 08d86103 | Francois POIROTTE | host = sql_escape_like(host) |
164 | 0bd9c069 | Francois POIROTTE | aggregates.add_filter(aggregates.items.c.hostname.ilike( |
165 | '%s' % host))
|
||
166 | bc94248f | Francois POIROTTE | |
167 | 08d86103 | Francois POIROTTE | if service:
|
168 | 693e96f1 | Thomas ANDREJAK | search['service'] = service
|
169 | 08d86103 | Francois POIROTTE | service = sql_escape_like(service) |
170 | 0bd9c069 | Francois POIROTTE | aggregates.add_filter(aggregates.items.c.servicename.ilike( |
171 | '%s' % service))
|
||
172 | bc94248f | Francois POIROTTE | |
173 | 08d86103 | Francois POIROTTE | if output:
|
174 | 693e96f1 | Thomas ANDREJAK | search['output'] = output
|
175 | 08d86103 | Francois POIROTTE | output = sql_escape_like(output) |
176 | 0bd9c069 | Francois POIROTTE | aggregates.add_filter(Event.message.ilike('%s' % output))
|
177 | bc94248f | Francois POIROTTE | |
178 | 08d86103 | Francois POIROTTE | if trouble_ticket:
|
179 | 693e96f1 | Thomas ANDREJAK | search['tt'] = trouble_ticket
|
180 | 08d86103 | Francois POIROTTE | trouble_ticket = sql_escape_like(trouble_ticket) |
181 | 0bd9c069 | Francois POIROTTE | aggregates.add_filter(CorrEvent.trouble_ticket.ilike( |
182 | '%s' % trouble_ticket))
|
||
183 | 19e88cb8 | Thomas ANDREJAK | |
184 | 1101e03e | Francois POIROTTE | if from_date:
|
185 | 88c9eb8e | Francois POIROTTE | search['from_date'] = from_date.lower()
|
186 | 1101e03e | Francois POIROTTE | try:
|
187 | 5bb827fd | Francois POIROTTE | # TRANSLATORS: Format de date et heure Python/JavaScript.
|
188 | # TRANSLATORS: http://www.dynarch.com/static/jscalendar-1.0/doc/html/reference.html#node_sec_5.3.5
|
||
189 | # TRANSLATORS: http://docs.python.org/release/2.5/lib/module-time.html
|
||
190 | 1101e03e | Francois POIROTTE | from_date = datetime.strptime( |
191 | 0842bb2c | Francois POIROTTE | from_date.encode('utf8'),
|
192 | _('%Y-%m-%d %I:%M:%S %p').encode('utf8')) |
||
193 | 1101e03e | Francois POIROTTE | except ValueError: |
194 | 9211ef65 | Francois POIROTTE | # On ignore silencieusement la date invalide reçue.
|
195 | pass
|
||
196 | else:
|
||
197 | aggregates.add_filter(CorrEvent.timestamp_active >= from_date) |
||
198 | 1101e03e | Francois POIROTTE | |
199 | if to_date:
|
||
200 | 88c9eb8e | Francois POIROTTE | search['to_date'] = to_date.lower()
|
201 | 1101e03e | Francois POIROTTE | try:
|
202 | 3ba83d8b | Francois POIROTTE | # TRANSLATORS: Format de date et heure.
|
203 | 5bb827fd | Francois POIROTTE | # TRANSLATORS: http://www.dynarch.com/static/jscalendar-1.0/doc/html/reference.html#node_sec_5.3.5
|
204 | # TRANSLATORS: http://docs.python.org/release/2.5/lib/module-time.html
|
||
205 | 1101e03e | Francois POIROTTE | to_date = datetime.strptime( |
206 | 0842bb2c | Francois POIROTTE | to_date.encode('utf8'),
|
207 | _('%Y-%m-%d %I:%M:%S %p').encode('utf8')) |
||
208 | 1101e03e | Francois POIROTTE | except ValueError: |
209 | 9211ef65 | Francois POIROTTE | # On ignore silencieusement la date invalide reçue.
|
210 | pass
|
||
211 | else:
|
||
212 | aggregates.add_filter(CorrEvent.timestamp_active <= to_date) |
||
213 | 1101e03e | Francois POIROTTE | |
214 | 19e88cb8 | Thomas ANDREJAK | # Calcul des éléments à afficher et du nombre de pages possibles
|
215 | 3d0d254c | Francois POIROTTE | total_rows = aggregates.num_rows() |
216 | ee3ae8c8 | Francois POIROTTE | items_per_page = int(config['vigiboard_items_per_page']) |
217 | 19e88cb8 | Thomas ANDREJAK | |
218 | ee3ae8c8 | Francois POIROTTE | id_first_row = items_per_page * (page-1)
|
219 | id_last_row = min(id_first_row + items_per_page, total_rows)
|
||
220 | 19e88cb8 | Thomas ANDREJAK | |
221 | 88cac5bb | Francois POIROTTE | # Si le numéro de page dépasse le nombre de pages existantes,
|
222 | # on redirige automatiquement vers la 1ère page.
|
||
223 | if total_rows and id_first_row >= total_rows: |
||
224 | redirect('/', page=total_rows / items_per_page, **search)
|
||
225 | |||
226 | 3d0d254c | Francois POIROTTE | aggregates.format_events(id_first_row, id_last_row) |
227 | aggregates.generate_tmpl_context() |
||
228 | baedcd0f | Francois POIROTTE | |
229 | ee3ae8c8 | Francois POIROTTE | nb_pages = int(math.ceil(total_rows / (items_per_page + 0.0))) |
230 | baedcd0f | Francois POIROTTE | if not total_rows: |
231 | id_first_row = 0
|
||
232 | else:
|
||
233 | id_first_row += 1
|
||
234 | 3d0d254c | Francois POIROTTE | |
235 | cf3c2494 | Vincent QUEMENER | # Récupération des données des plugins
|
236 | plugins_data = {} |
||
237 | plugins = dict(config['columns_plugins']) |
||
238 | for plugin in plugins: |
||
239 | plugin_data = plugins[plugin].get_bulk_data( |
||
240 | [event[0].idcorrevent for event in aggregates.events] |
||
241 | ) |
||
242 | if plugin_data :
|
||
243 | plugins_data[plugin] = plugin_data |
||
244 | |||
245 | 19e88cb8 | Thomas ANDREJAK | return dict( |
246 | 73f3220e | Vincent QUEMENER | hostname = None,
|
247 | servicename = None,
|
||
248 | 1101e03e | Francois POIROTTE | events = aggregates.events, |
249 | cf3c2494 | Vincent QUEMENER | plugins_data = plugins_data, |
250 | 1101e03e | Francois POIROTTE | rows_info = { |
251 | 'id_first_row': id_first_row,
|
||
252 | 'id_last_row': id_last_row,
|
||
253 | 'total_rows': total_rows,
|
||
254 | }, |
||
255 | nb_pages = nb_pages, |
||
256 | page = page, |
||
257 | event_edit_status_options = edit_event_status_options, |
||
258 | 2dbc5942 | Francois POIROTTE | search_form = create_search_form, |
259 | 1101e03e | Francois POIROTTE | search = search, |
260 | 2dbc5942 | Francois POIROTTE | get_calendar_lang = get_calendar_lang, |
261 | 1101e03e | Francois POIROTTE | ) |
262 | 19e88cb8 | Thomas ANDREJAK | |
263 | e307e626 | Francois POIROTTE | |
264 | class MaskedEventsSchema(schema.Schema): |
||
265 | e181e86c | Francois POIROTTE | """Schéma de validation de la méthode masked_events."""
|
266 | e307e626 | Francois POIROTTE | idcorrevent = validators.Int(not_empty=True)
|
267 | page = validators.Int(min=1, if_missing=1, if_invalid=1) |
||
268 | |||
269 | @validate(
|
||
270 | validators=MaskedEventsSchema(), |
||
271 | error_handler = process_form_errors) |
||
272 | 00d2e1d1 | Vincent QUEMENER | @expose('raw_events_table.html') |
273 | f2e30877 | Francois POIROTTE | @require(access_restriction)
|
274 | e307e626 | Francois POIROTTE | def masked_events(self, idcorrevent, page): |
275 | 54644278 | Francois POIROTTE | """
|
276 | e181e86c | Francois POIROTTE | Affichage de la liste des événements bruts masqués d'un événement
|
277 | corrélé (événements agrégés dans l'événement corrélé).
|
||
278 | 54644278 | Francois POIROTTE |
|
279 | e181e86c | Francois POIROTTE | @param idcorrevent: identifiant de l'événement corrélé souhaité.
|
280 | @type idcorrevent: C{int}
|
||
281 | 54644278 | Francois POIROTTE | """
|
282 | 195aa50d | Francois POIROTTE | user = get_current_user() |
283 | a05b9a37 | Francois POIROTTE | |
284 | # Récupère la liste des événements masqués de l'événement
|
||
285 | # corrélé donné par idcorrevent.
|
||
286 | 195aa50d | Francois POIROTTE | events = VigiboardRequest(user, False)
|
287 | 54644278 | Francois POIROTTE | events.add_table( |
288 | Event, |
||
289 | events.items.c.hostname, |
||
290 | events.items.c.servicename, |
||
291 | ) |
||
292 | 072f2a16 | Francois POIROTTE | events.add_join((EVENTSAGGREGATE_TABLE, \ |
293 | EVENTSAGGREGATE_TABLE.c.idevent == Event.idevent)) |
||
294 | events.add_join((CorrEvent, CorrEvent.idcorrevent == \ |
||
295 | EVENTSAGGREGATE_TABLE.c.idcorrevent)) |
||
296 | e3c52cfd | Aurelien BOMPARD | events.add_join((events.items, |
297 | 54644278 | Francois POIROTTE | Event.idsupitem == events.items.c.idsupitem)) |
298 | events.add_filter(Event.idevent != CorrEvent.idcause) |
||
299 | events.add_filter(CorrEvent.idcorrevent == idcorrevent) |
||
300 | bcf87133 | Francois POIROTTE | |
301 | a05b9a37 | Francois POIROTTE | # Récupère l'instance de SupItem associé à la cause de
|
302 | # l'événement corrélé. Cette instance est utilisé pour
|
||
303 | # obtenir le nom d'hôte/service auquel la cause est
|
||
304 | # rattachée (afin de fournir un contexte à l'utilisateur).
|
||
305 | hostname = None
|
||
306 | servicename = None
|
||
307 | cause_supitem = DBSession.query( |
||
308 | SupItem, |
||
309 | ).join( |
||
310 | (Event, Event.idsupitem == SupItem.idsupitem), |
||
311 | cf3c2494 | Vincent QUEMENER | (CorrEvent, Event.idevent == CorrEvent.idcause), |
312 | a05b9a37 | Francois POIROTTE | ).filter(CorrEvent.idcorrevent == idcorrevent |
313 | ).one() |
||
314 | |||
315 | if isinstance(cause_supitem, LowLevelService): |
||
316 | hostname = cause_supitem.host.name |
||
317 | servicename = cause_supitem.servicename |
||
318 | elif isinstance(cause_supitem, Host): |
||
319 | hostname = cause_supitem.name |
||
320 | |||
321 | 54644278 | Francois POIROTTE | # Vérification que l'événement existe
|
322 | bcf87133 | Francois POIROTTE | total_rows = events.num_rows() |
323 | if total_rows < 1: |
||
324 | 54644278 | Francois POIROTTE | flash(_('No masked event or access denied'), 'error') |
325 | redirect('/')
|
||
326 | |||
327 | 88cac5bb | Francois POIROTTE | # Calcul des éléments à afficher et du nombre de pages possibles
|
328 | total_rows = events.num_rows() |
||
329 | 54644278 | Francois POIROTTE | items_per_page = int(config['vigiboard_items_per_page']) |
330 | |||
331 | id_first_row = items_per_page * (page-1)
|
||
332 | id_last_row = min(id_first_row + items_per_page, total_rows)
|
||
333 | |||
334 | events.format_events(id_first_row, id_last_row) |
||
335 | events.generate_tmpl_context() |
||
336 | |||
337 | nb_pages = int(math.ceil(total_rows / (items_per_page + 0.0))) |
||
338 | if not total_rows: |
||
339 | id_first_row = 0
|
||
340 | else:
|
||
341 | id_first_row += 1
|
||
342 | |||
343 | return dict( |
||
344 | 0c8b0e15 | Francois POIROTTE | idcorrevent = idcorrevent, |
345 | a05b9a37 | Francois POIROTTE | hostname = hostname, |
346 | servicename = servicename, |
||
347 | 54644278 | Francois POIROTTE | events = events.events, |
348 | cf3c2494 | Vincent QUEMENER | plugins_data = {}, |
349 | 54644278 | Francois POIROTTE | rows_info = { |
350 | 'id_first_row': id_first_row,
|
||
351 | 'id_last_row': id_last_row,
|
||
352 | 'total_rows': total_rows,
|
||
353 | }, |
||
354 | nb_pages = nb_pages, |
||
355 | page = page, |
||
356 | 2dbc5942 | Francois POIROTTE | search_form = create_search_form, |
357 | search = {}, |
||
358 | get_calendar_lang = get_calendar_lang, |
||
359 | 54644278 | Francois POIROTTE | ) |
360 | |||
361 | e307e626 | Francois POIROTTE | |
362 | class EventSchema(schema.Schema): |
||
363 | e181e86c | Francois POIROTTE | """Schéma de validation de la méthode event."""
|
364 | e307e626 | Francois POIROTTE | idevent = validators.Int(not_empty=True)
|
365 | page = validators.Int(min=1, if_missing=1, if_invalid=1) |
||
366 | |||
367 | @validate(
|
||
368 | validators=EventSchema(), |
||
369 | error_handler = process_form_errors) |
||
370 | 00d2e1d1 | Vincent QUEMENER | @expose('history_table.html') |
371 | f2e30877 | Francois POIROTTE | @require(access_restriction)
|
372 | e307e626 | Francois POIROTTE | def event(self, idevent, page): |
373 | 19e88cb8 | Thomas ANDREJAK | """
|
374 | 94f31908 | Francois POIROTTE | Affichage de l'historique d'un événement brut.
|
375 | 19e88cb8 | Thomas ANDREJAK | Pour accéder à cette page, l'utilisateur doit être authentifié.
|
376 |
|
||
377 | 94f31908 | Francois POIROTTE | @param idevent: identifiant de l'événement brut souhaité.
|
378 | @type idevent: C{int}
|
||
379 | e181e86c | Francois POIROTTE | @param page: numéro de la page à afficher.
|
380 | @type page: C{int}
|
||
381 | c9245ffc | Vincent QUEMENER |
|
382 | e181e86c | Francois POIROTTE | Cette méthode permet de satisfaire l'exigence
|
383 | VIGILO_EXIG_VIGILO_BAC_0080.
|
||
384 | 19e88cb8 | Thomas ANDREJAK | """
|
385 | 195aa50d | Francois POIROTTE | user = get_current_user() |
386 | events = VigiboardRequest(user, False)
|
||
387 | 911069bc | Francois POIROTTE | events.add_table( |
388 | 539f69fc | Francois POIROTTE | Event, |
389 | 72ec8dbf | Francois POIROTTE | events.items.c.hostname.label('hostname'),
|
390 | events.items.c.servicename.label('servicename'),
|
||
391 | 911069bc | Francois POIROTTE | ) |
392 | 072f2a16 | Francois POIROTTE | events.add_join((EVENTSAGGREGATE_TABLE, \ |
393 | EVENTSAGGREGATE_TABLE.c.idevent == Event.idevent)) |
||
394 | events.add_join((CorrEvent, CorrEvent.idcorrevent == \ |
||
395 | EVENTSAGGREGATE_TABLE.c.idcorrevent)) |
||
396 | e3c52cfd | Aurelien BOMPARD | events.add_join((events.items, |
397 | bfd8ead8 | Vincent QUEMENER | Event.idsupitem == events.items.c.idsupitem)) |
398 | 94f31908 | Francois POIROTTE | events.add_filter(Event.idevent == idevent) |
399 | 539f69fc | Francois POIROTTE | |
400 | if events.num_rows() != 1: |
||
401 | flash(_('No such event or access denied'), 'error') |
||
402 | 19e88cb8 | Thomas ANDREJAK | redirect('/')
|
403 | 539f69fc | Francois POIROTTE | |
404 | 19e88cb8 | Thomas ANDREJAK | events.format_events(0, 1) |
405 | 539f69fc | Francois POIROTTE | events.generate_tmpl_context() |
406 | history = events.format_history() |
||
407 | |||
408 | total_rows = history.count() |
||
409 | items_per_page = int(config['vigiboard_items_per_page']) |
||
410 | |||
411 | id_first_row = items_per_page * (page-1)
|
||
412 | id_last_row = min(id_first_row + items_per_page, total_rows)
|
||
413 | |||
414 | history_entries = history[id_first_row : id_last_row] |
||
415 | |||
416 | nb_pages = int(math.ceil(total_rows / (items_per_page + 0.0))) |
||
417 | if not total_rows: |
||
418 | id_first_row = 0
|
||
419 | else:
|
||
420 | id_first_row += 1
|
||
421 | 19e88cb8 | Thomas ANDREJAK | |
422 | 72ec8dbf | Francois POIROTTE | event = events.req[0]
|
423 | |||
424 | 19e88cb8 | Thomas ANDREJAK | return dict( |
425 | 0c8b0e15 | Francois POIROTTE | idevent = idevent, |
426 | 72ec8dbf | Francois POIROTTE | hostname = event.hostname, |
427 | servicename = event.servicename, |
||
428 | cf3c2494 | Vincent QUEMENER | plugins_data = {}, |
429 | 911069bc | Francois POIROTTE | rows_info = { |
430 | 539f69fc | Francois POIROTTE | 'id_first_row': id_first_row,
|
431 | 'id_last_row': id_last_row,
|
||
432 | 'total_rows': total_rows,
|
||
433 | 911069bc | Francois POIROTTE | }, |
434 | 539f69fc | Francois POIROTTE | nb_pages = nb_pages, |
435 | page = page, |
||
436 | 15b98053 | Francois POIROTTE | history = history_entries, |
437 | 2dbc5942 | Francois POIROTTE | search_form = create_search_form, |
438 | search = {}, |
||
439 | get_calendar_lang = get_calendar_lang, |
||
440 | 911069bc | Francois POIROTTE | ) |
441 | 19e88cb8 | Thomas ANDREJAK | |
442 | e307e626 | Francois POIROTTE | |
443 | class ItemSchema(schema.Schema): |
||
444 | e181e86c | Francois POIROTTE | """Schéma de validation de la méthode item."""
|
445 | e307e626 | Francois POIROTTE | page = validators.Int(min=1, if_missing=1, if_invalid=1) |
446 | host = validators.String(not_empty=True)
|
||
447 | service = validators.String(if_missing=None)
|
||
448 | |||
449 | 24334b4b | Vincent QUEMENER | @validate(
|
450 | e307e626 | Francois POIROTTE | validators=ItemSchema(), |
451 | 6ab72614 | Vincent QUEMENER | error_handler = process_form_errors) |
452 | eab949e2 | Vincent QUEMENER | @expose('events_table.html') |
453 | f2e30877 | Francois POIROTTE | @require(access_restriction)
|
454 | e307e626 | Francois POIROTTE | def item(self, page, host, service): |
455 | 19e88cb8 | Thomas ANDREJAK | """
|
456 | 539f69fc | Francois POIROTTE | Affichage de l'historique de l'ensemble des événements corrélés
|
457 | jamais ouverts sur l'hôte / service demandé.
|
||
458 | 19e88cb8 | Thomas ANDREJAK | Pour accéder à cette page, l'utilisateur doit être authentifié.
|
459 |
|
||
460 | e181e86c | Francois POIROTTE | @param page: Numéro de la page à afficher.
|
461 | 19e88cb8 | Thomas ANDREJAK | @param host: Nom de l'hôte souhaité.
|
462 | @param service: Nom du service souhaité
|
||
463 | c9245ffc | Vincent QUEMENER |
|
464 | e181e86c | Francois POIROTTE | Cette méthode permet de satisfaire l'exigence
|
465 | VIGILO_EXIG_VIGILO_BAC_0080.
|
||
466 | 19e88cb8 | Thomas ANDREJAK | """
|
467 | 24334b4b | Vincent QUEMENER | idsupitem = SupItem.get_supitem(host, service) |
468 | 1a1e8c17 | Francois POIROTTE | if not idsupitem: |
469 | flash(_('No such host/service'), 'error') |
||
470 | redirect('/')
|
||
471 | 24334b4b | Vincent QUEMENER | |
472 | 195aa50d | Francois POIROTTE | user = get_current_user() |
473 | aggregates = VigiboardRequest(user, False)
|
||
474 | 539f69fc | Francois POIROTTE | aggregates.add_table( |
475 | 911069bc | Francois POIROTTE | CorrEvent, |
476 | 539f69fc | Francois POIROTTE | aggregates.items.c.hostname, |
477 | aggregates.items.c.servicename, |
||
478 | 911069bc | Francois POIROTTE | ) |
479 | 539f69fc | Francois POIROTTE | aggregates.add_join((Event, CorrEvent.idcause == Event.idevent)) |
480 | 0842bb2c | Francois POIROTTE | aggregates.add_join((aggregates.items, |
481 | 539f69fc | Francois POIROTTE | Event.idsupitem == aggregates.items.c.idsupitem)) |
482 | aggregates.add_filter(aggregates.items.c.idsupitem == idsupitem) |
||
483 | baedcd0f | Francois POIROTTE | |
484 | a2a22ade | Francois POIROTTE | # Vérification qu'il y a au moins 1 événement qui correspond
|
485 | 539f69fc | Francois POIROTTE | total_rows = aggregates.num_rows() |
486 | 94f31908 | Francois POIROTTE | if not total_rows: |
487 | 911069bc | Francois POIROTTE | flash(_('No access to this host/service or no event yet'), 'error') |
488 | 19e88cb8 | Thomas ANDREJAK | redirect('/')
|
489 | ee3ae8c8 | Francois POIROTTE | |
490 | 539f69fc | Francois POIROTTE | items_per_page = int(config['vigiboard_items_per_page']) |
491 | |||
492 | id_first_row = items_per_page * (page-1)
|
||
493 | id_last_row = min(id_first_row + items_per_page, total_rows)
|
||
494 | |||
495 | aggregates.format_events(id_first_row, id_last_row) |
||
496 | aggregates.generate_tmpl_context() |
||
497 | |||
498 | nb_pages = int(math.ceil(total_rows / (items_per_page + 0.0))) |
||
499 | if not total_rows: |
||
500 | id_first_row = 0
|
||
501 | else:
|
||
502 | id_first_row += 1
|
||
503 | e3c52cfd | Aurelien BOMPARD | |
504 | 19e88cb8 | Thomas ANDREJAK | return dict( |
505 | 0c8b0e15 | Francois POIROTTE | hostname = host, |
506 | servicename = service, |
||
507 | 539f69fc | Francois POIROTTE | events = aggregates.events, |
508 | cf3c2494 | Vincent QUEMENER | plugins_data = {}, |
509 | 54644278 | Francois POIROTTE | rows_info = { |
510 | 539f69fc | Francois POIROTTE | 'id_first_row': id_first_row,
|
511 | 'id_last_row': id_last_row,
|
||
512 | 'total_rows': total_rows,
|
||
513 | 54644278 | Francois POIROTTE | }, |
514 | 539f69fc | Francois POIROTTE | nb_pages = nb_pages, |
515 | page = page, |
||
516 | 54644278 | Francois POIROTTE | event_edit_status_options = edit_event_status_options, |
517 | 2dbc5942 | Francois POIROTTE | search_form = create_search_form, |
518 | search = {}, |
||
519 | get_calendar_lang = get_calendar_lang, |
||
520 | 54644278 | Francois POIROTTE | ) |
521 | 19e88cb8 | Thomas ANDREJAK | |
522 | e307e626 | Francois POIROTTE | |
523 | class UpdateSchema(schema.Schema): |
||
524 | e181e86c | Francois POIROTTE | """Schéma de validation de la méthode update."""
|
525 | e307e626 | Francois POIROTTE | id = validators.Regex(r'^[0-9]+(,[0-9]+)*,?$')
|
526 | last_modification = validators.Number(not_empty=True)
|
||
527 | trouble_ticket = validators.String(if_missing='')
|
||
528 | 9e0ea30e | Francois POIROTTE | ack = validators.OneOf( |
529 | [unicode(s[0]) for s in edit_event_status_options], |
||
530 | not_empty=True)
|
||
531 | e307e626 | Francois POIROTTE | |
532 | @validate(
|
||
533 | validators=UpdateSchema(), |
||
534 | error_handler = process_form_errors) |
||
535 | 9e0ea30e | Francois POIROTTE | @require(
|
536 | All( |
||
537 | not_anonymous(msg=l_("You need to be authenticated")),
|
||
538 | Any(in_group('managers'),
|
||
539 | a5f99051 | Francois POIROTTE | has_permission('vigiboard-update'),
|
540 | 9e0ea30e | Francois POIROTTE | msg=l_("You don't have write access to VigiBoard"))
|
541 | )) |
||
542 | dcd79358 | Francois POIROTTE | @expose()
|
543 | a9a4679d | Francois POIROTTE | def update(self, id, last_modification, trouble_ticket, ack): |
544 | 19e88cb8 | Thomas ANDREJAK | """
|
545 | a2a22ade | Francois POIROTTE | Mise à jour d'un événement suivant les arguments passés.
|
546 | 8484b8bd | Francois POIROTTE | Cela peut être un changement de ticket ou un changement de statut.
|
547 | e3c52cfd | Aurelien BOMPARD |
|
548 | a9a4679d | Francois POIROTTE | @param id: Le ou les identifiants des événements à traiter
|
549 | @param last_modification: La date de la dernière modification
|
||
550 | 57387640 | Francois POIROTTE | dont l'utilisateur est au courant.
|
551 | a9a4679d | Francois POIROTTE | @param trouble_ticket: Nouveau numéro du ticket associé.
|
552 | @param ack: Nouvel état d'acquittement des événements sélectionnés.
|
||
553 | c9245ffc | Vincent QUEMENER |
|
554 | e3c52cfd | Aurelien BOMPARD | Cette méthode permet de satisfaire les exigences suivantes :
|
555 | e181e86c | Francois POIROTTE | - VIGILO_EXIG_VIGILO_BAC_0020,
|
556 | - VIGILO_EXIG_VIGILO_BAC_0060,
|
||
557 | - VIGILO_EXIG_VIGILO_BAC_0110.
|
||
558 | 19e88cb8 | Thomas ANDREJAK | """
|
559 | |||
560 | 97f6d842 | Vincent QUEMENER | # On vérifie que des identifiants ont bien été transmis via
|
561 | # le formulaire, et on informe l'utilisateur le cas échéant.
|
||
562 | a9a4679d | Francois POIROTTE | if id is None: |
563 | 10848680 | Francois POIROTTE | flash(_('No event has been selected'), 'warning') |
564 | a9a4679d | Francois POIROTTE | raise redirect(request.environ.get('HTTP_REFERER', '/')) |
565 | 5d20c2c5 | Francois POIROTTE | |
566 | 2b740fc8 | Francois POIROTTE | # On récupère la liste de tous les identifiants des événements
|
567 | # à mettre à jour.
|
||
568 | ids = map(int, id.strip(',').split(',')) |
||
569 | 195aa50d | Francois POIROTTE | |
570 | user = get_current_user() |
||
571 | 303419a6 | Francois POIROTTE | events = VigiboardRequest(user) |
572 | 911069bc | Francois POIROTTE | events.add_table(CorrEvent) |
573 | events.add_join((Event, CorrEvent.idcause == Event.idevent)) |
||
574 | 0842bb2c | Francois POIROTTE | events.add_join((events.items, |
575 | bfd8ead8 | Vincent QUEMENER | Event.idsupitem == events.items.c.idsupitem)) |
576 | 780ca169 | Francois POIROTTE | events.add_filter(CorrEvent.idcorrevent.in_(ids)) |
577 | e3c52cfd | Aurelien BOMPARD | |
578 | 5edd29ac | Vincent QUEMENER | events.generate_request() |
579 | idevents = [cause.idcause for cause in events.req] |
||
580 | a9a4679d | Francois POIROTTE | |
581 | 0842bb2c | Francois POIROTTE | # Si des changements sont survenus depuis que la
|
582 | 5edd29ac | Vincent QUEMENER | # page est affichée, on en informe l'utilisateur.
|
583 | a9a4679d | Francois POIROTTE | last_modification = datetime.fromtimestamp(last_modification) |
584 | cur_last_modification = get_last_modification_timestamp(idevents, None)
|
||
585 | if cur_last_modification and last_modification < cur_last_modification: |
||
586 | 5edd29ac | Vincent QUEMENER | flash(_('Changes have occurred since the page was last displayed, '
|
587 | 'your changes HAVE NOT been saved.'), 'warning') |
||
588 | a9a4679d | Francois POIROTTE | raise redirect(request.environ.get('HTTP_REFERER', '/')) |
589 | f744bc14 | Francois POIROTTE | |
590 | 19e88cb8 | Thomas ANDREJAK | # Vérification que au moins un des identifiants existe et est éditable
|
591 | 94f31908 | Francois POIROTTE | if not events.num_rows(): |
592 | 19e88cb8 | Thomas ANDREJAK | flash(_('No access to this event'), 'error') |
593 | redirect('/')
|
||
594 | 8484b8bd | Francois POIROTTE | |
595 | 2b740fc8 | Francois POIROTTE | if ack == u'Forced': |
596 | condition = Any( |
||
597 | in_group('managers'),
|
||
598 | has_permission('vigiboard-admin'),
|
||
599 | msg=l_("You don't have administrative access "
|
||
600 | "to VigiBoard"))
|
||
601 | try:
|
||
602 | condition.check_authorization(request.environ) |
||
603 | except NotAuthorizedError, e:
|
||
604 | reason = unicode(e)
|
||
605 | flash(reason, 'error')
|
||
606 | raise redirect(request.environ.get('HTTP_REFERER', '/')) |
||
607 | |||
608 | # Modification des événements et création d'un historique
|
||
609 | # chaque fois que cela est nécessaire.
|
||
610 | for event in events.req: |
||
611 | f744bc14 | Francois POIROTTE | if trouble_ticket and trouble_ticket != event.trouble_ticket: |
612 | 8484b8bd | Francois POIROTTE | history = EventHistory( |
613 | type_action="Ticket change",
|
||
614 | idevent=event.idcause, |
||
615 | a9a4679d | Francois POIROTTE | value=unicode(trouble_ticket),
|
616 | 2b740fc8 | Francois POIROTTE | text="Changed trouble ticket from '%(from)s' "
|
617 | "to '%(to)s'" % {
|
||
618 | 'from': event.trouble_ticket,
|
||
619 | 'to': trouble_ticket,
|
||
620 | }, |
||
621 | e1133e5a | Francois POIROTTE | username=user.user_name, |
622 | ee3ae8c8 | Francois POIROTTE | timestamp=datetime.now(), |
623 | 8484b8bd | Francois POIROTTE | ) |
624 | 0842bb2c | Francois POIROTTE | DBSession.add(history) |
625 | a9a4679d | Francois POIROTTE | event.trouble_ticket = trouble_ticket |
626 | 8484b8bd | Francois POIROTTE | |
627 | 9e0ea30e | Francois POIROTTE | # Changement du statut d'acquittement.
|
628 | if ack != u'NoChange': |
||
629 | 2b740fc8 | Francois POIROTTE | changed_ack = ack |
630 | 9e0ea30e | Francois POIROTTE | # Pour forcer l'acquittement d'un événement,
|
631 | # il faut en plus avoir la permission
|
||
632 | # "vigiboard-admin".
|
||
633 | if ack == u'Forced': |
||
634 | 2b740fc8 | Francois POIROTTE | changed_ack = u'AAClosed'
|
635 | 7e0c4383 | Francois POIROTTE | cause = event.cause |
636 | f8020955 | Francois POIROTTE | # On met systématiquement l'événement à l'état "OK",
|
637 | # même s'il s'agit d'un hôte.
|
||
638 | # Techniquement, c'est incorrect, mais on fait ça
|
||
639 | # pour masquer l'événement de toutes façons...
|
||
640 | 7e0c4383 | Francois POIROTTE | cause.current_state = \ |
641 | 2b740fc8 | Francois POIROTTE | StateName.statename_to_value(u'OK')
|
642 | |||
643 | f8020955 | Francois POIROTTE | # Mise à jour de l'état dans State, pour que
|
644 | # VigiMap soit également mis à jour.
|
||
645 | DBSession.query(State).filter( |
||
646 | 7e0c4383 | Francois POIROTTE | State.idsupitem == cause.idsupitem, |
647 | f8020955 | Francois POIROTTE | ).update({ |
648 | 'state': StateName.statename_to_value(u'OK'), |
||
649 | }) |
||
650 | |||
651 | 2b740fc8 | Francois POIROTTE | history = EventHistory( |
652 | type_action="Forced change state",
|
||
653 | idevent=event.idcause, |
||
654 | value=u'OK',
|
||
655 | text="Forced state to 'OK'",
|
||
656 | username=user.user_name, |
||
657 | timestamp=datetime.now(), |
||
658 | ) |
||
659 | DBSession.add(history) |
||
660 | 9e0ea30e | Francois POIROTTE | |
661 | 19e88cb8 | Thomas ANDREJAK | history = EventHistory( |
662 | 88cac5bb | Francois POIROTTE | type_action=u"Acknowledgement change state",
|
663 | 8484b8bd | Francois POIROTTE | idevent=event.idcause, |
664 | 9e0ea30e | Francois POIROTTE | value=ack, |
665 | 9494bbb3 | Vincent QUEMENER | text="Changed acknowledgement status "
|
666 | "from '%s' to '%s'" % (
|
||
667 | 2b740fc8 | Francois POIROTTE | event.status, changed_ack |
668 | ee3ae8c8 | Francois POIROTTE | ), |
669 | e1133e5a | Francois POIROTTE | username=user.user_name, |
670 | ee3ae8c8 | Francois POIROTTE | timestamp=datetime.now(), |
671 | 8484b8bd | Francois POIROTTE | ) |
672 | 19e88cb8 | Thomas ANDREJAK | DBSession.add(history) |
673 | 2b740fc8 | Francois POIROTTE | event.status = changed_ack |
674 | 3d0d254c | Francois POIROTTE | |
675 | 10848680 | Francois POIROTTE | DBSession.flush() |
676 | 19e88cb8 | Thomas ANDREJAK | flash(_('Updated successfully'))
|
677 | a9a4679d | Francois POIROTTE | redirect(request.environ.get('HTTP_REFERER', '/')) |
678 | 19e88cb8 | Thomas ANDREJAK | |
679 | e307e626 | Francois POIROTTE | |
680 | class GetPluginValueSchema(schema.Schema): |
||
681 | e181e86c | Francois POIROTTE | """Schéma de validation de la méthode get_plugin_value."""
|
682 | e307e626 | Francois POIROTTE | idcorrevent = validators.Int(not_empty=True)
|
683 | 65383903 | Francois POIROTTE | plugin_name = validators.String(not_empty=True)
|
684 | e307e626 | Francois POIROTTE | # Permet de passer des paramètres supplémentaires au plugin.
|
685 | allow_extra_fields = True
|
||
686 | |||
687 | @validate(
|
||
688 | validators=GetPluginValueSchema(), |
||
689 | 4c08cd96 | Francois POIROTTE | error_handler = handle_validation_errors_json) |
690 | 8ad24667 | Thomas ANDREJAK | @expose('json') |
691 | f2e30877 | Francois POIROTTE | @require(access_restriction)
|
692 | cf3c2494 | Vincent QUEMENER | def plugin_json(self, idcorrevent, plugin_name, *arg, **krgv): |
693 | 8ad24667 | Thomas ANDREJAK | """
|
694 | 4dd2035e | Francois POIROTTE | Permet de récupérer la valeur d'un plugin associée à un CorrEvent
|
695 | donné via JSON.
|
||
696 | 8ad24667 | Thomas ANDREJAK | """
|
697 | 65383903 | Francois POIROTTE | plugins = dict(config['columns_plugins']) |
698 | if plugin_name not in plugins: |
||
699 | raise HTTPNotFound(_("No such plugin '%s'") % plugin_name) |
||
700 | |||
701 | 4dd2035e | Francois POIROTTE | # Permet de vérifier si l'utilisateur a bien les permissions
|
702 | # pour accéder à cet événement et si l'événement existe.
|
||
703 | 195aa50d | Francois POIROTTE | user = get_current_user() |
704 | events = VigiboardRequest(user, False)
|
||
705 | 4dd2035e | Francois POIROTTE | events.add_table(CorrEvent.idcorrevent) |
706 | events.add_join((Event, CorrEvent.idcause == Event.idevent)) |
||
707 | 0842bb2c | Francois POIROTTE | events.add_join((events.items, |
708 | bfd8ead8 | Vincent QUEMENER | Event.idsupitem == events.items.c.idsupitem)) |
709 | 4dd2035e | Francois POIROTTE | events.add_filter(CorrEvent.idcorrevent == idcorrevent) |
710 | |||
711 | # Pas d'événement ou permission refusée. On ne distingue pas
|
||
712 | # les 2 cas afin d'éviter la divulgation d'informations.
|
||
713 | if not events.num_rows(): |
||
714 | df25ac35 | Francois POIROTTE | raise HTTPNotFound(_('No such incident or insufficient ' |
715 | 'permissions'))
|
||
716 | 0f56fff9 | Francois POIROTTE | |
717 | cf3c2494 | Vincent QUEMENER | return plugins[plugin_name].get_json_data(idcorrevent, *arg, **krgv)
|
718 | 1bb369b9 | Francois POIROTTE | |
719 | @validate(validators={
|
||
720 | "fontsize": validators.Regex(
|
||
721 | r'[0-9]+(pt|px|em|%)',
|
||
722 | 6ab72614 | Vincent QUEMENER | regexOps = ('I',)
|
723 | 4c08cd96 | Francois POIROTTE | )}, error_handler = handle_validation_errors_json) |
724 | 693e96f1 | Thomas ANDREJAK | @expose('json') |
725 | b8500d1a | Thomas ANDREJAK | def set_fontsize(self, fontsize): |
726 | 4dd2035e | Francois POIROTTE | """Enregistre la taille de la police dans les préférences."""
|
727 | b8500d1a | Thomas ANDREJAK | session['fontsize'] = fontsize
|
728 | session.save() |
||
729 | e2e218d7 | Francois POIROTTE | return dict() |
730 | 693e96f1 | Thomas ANDREJAK | |
731 | 08d86103 | Francois POIROTTE | @validate(validators={"refresh": validators.Int()}, |
732 | 4c08cd96 | Francois POIROTTE | error_handler = handle_validation_errors_json) |
733 | 693e96f1 | Thomas ANDREJAK | @expose('json') |
734 | b8500d1a | Thomas ANDREJAK | def set_refresh(self, refresh): |
735 | 4dd2035e | Francois POIROTTE | """Enregistre le temps de rafraichissement dans les préférences."""
|
736 | b8500d1a | Thomas ANDREJAK | session['refresh'] = refresh
|
737 | session.save() |
||
738 | e2e218d7 | Francois POIROTTE | return dict() |
739 | |||
740 | @expose('json') |
||
741 | def set_theme(self, theme): |
||
742 | 4dd2035e | Francois POIROTTE | """Enregistre le thème à utiliser dans les préférences."""
|
743 | # On sauvegarde l'ID du thème sans vérifications
|
||
744 | # car les thèmes (styles CSS) sont définies dans
|
||
745 | # les packages de thèmes (ex: vigilo-themes-default).
|
||
746 | # La vérification de la valeur est faite dans les templates.
|
||
747 | e2e218d7 | Francois POIROTTE | session['theme'] = theme
|
748 | session.save() |
||
749 | return dict() |
||
750 | 2b740fc8 | Francois POIROTTE | |
751 | ea0e5dfb | Francois POIROTTE | @require(access_restriction)
|
752 | @expose('json') |
||
753 | 48acee1e | Francois POIROTTE | def get_groups(self, parent_id=None): |
754 | """
|
||
755 | Affiche un étage de l'arbre de
|
||
756 | sélection des hôtes et groupes d'hôtes.
|
||
757 |
|
||
758 | @param parent_id: identifiant du groupe d'hôte parent
|
||
759 | @type parent_id: C{int} or None
|
||
760 | """
|
||
761 | |||
762 | # Si l'identifiant du groupe parent n'est pas
|
||
763 | # spécifié, on retourne la liste des groupes racines,
|
||
764 | # fournie par la méthode get_root_hosts_groups.
|
||
765 | if parent_id is None: |
||
766 | return self.get_root_host_groups() |
||
767 | |||
768 | 0bd9c069 | Francois POIROTTE | # TODO: Utiliser un schéma de validation
|
769 | parent_id = int(parent_id)
|
||
770 | ea0e5dfb | Francois POIROTTE | |
771 | cf3c2494 | Vincent QUEMENER | # On récupère la liste des groupes de supitems dont
|
772 | # l'identifiant du parent est passé en paramètre.
|
||
773 | supitem_groups = DBSession.query( |
||
774 | SupItemGroup.idgroup, |
||
775 | SupItemGroup.name, |
||
776 | ).join( |
||
777 | (GroupHierarchy, |
||
778 | GroupHierarchy.idchild == SupItemGroup.idgroup), |
||
779 | ).filter(GroupHierarchy.idparent == parent_id |
||
780 | ).filter(GroupHierarchy.idchild != parent_id) |
||
781 | |||
782 | # Si l'utilisateur n'appartient pas au groupe 'managers',
|
||
783 | # on filtre les résultats en fonction de ses permissions.
|
||
784 | ea0e5dfb | Francois POIROTTE | is_manager = in_group('managers').is_met(request.environ)
|
785 | 0bd9c069 | Francois POIROTTE | if not is_manager: |
786 | user = get_current_user() |
||
787 | eec46cb0 | Vincent QUEMENER | GroupHierarchy_aliased = aliased(GroupHierarchy, |
788 | name='GroupHierarchy_aliased')
|
||
789 | cf3c2494 | Vincent QUEMENER | supitem_groups.join( |
790 | (GroupHierarchy_aliased, |
||
791 | GroupHierarchy_aliased.idchild == SupItemGroup.idgroup), |
||
792 | (DataPermission, |
||
793 | DataPermission.idgroup == GroupHierarchy_aliased.idparent), |
||
794 | (USER_GROUP_TABLE, USER_GROUP_TABLE.c.idgroup == \ |
||
795 | DataPermission.idusergroup), |
||
796 | ).filter(USER_GROUP_TABLE.c.username == user.user_name) |
||
797 | eec46cb0 | Vincent QUEMENER | |
798 | 48acee1e | Francois POIROTTE | groups = [] |
799 | cf3c2494 | Vincent QUEMENER | for group in supitem_groups.distinct().all(): |
800 | 48acee1e | Francois POIROTTE | groups.append({ |
801 | 'id' : group.idgroup,
|
||
802 | 'name' : group.name,
|
||
803 | }) |
||
804 | |||
805 | return dict(groups = groups, leaves = []) |
||
806 | |||
807 | def get_root_host_groups(self): |
||
808 | """
|
||
809 | Retourne tous les groupes racines (c'est à dire n'ayant
|
||
810 | aucun parent) d'hôtes auquel l'utilisateur a accès.
|
||
811 |
|
||
812 | @return: Un dictionnaire contenant la liste de ces groupes.
|
||
813 | @rtype : C{dict} of C{list} of C{dict} of C{mixed}
|
||
814 | """
|
||
815 | ea0e5dfb | Francois POIROTTE | |
816 | 0bd9c069 | Francois POIROTTE | # On récupère tous les groupes qui ont un parent.
|
817 | children = DBSession.query( |
||
818 | SupItemGroup, |
||
819 | ).distinct( |
||
820 | ).join( |
||
821 | (GroupHierarchy, GroupHierarchy.idchild == SupItemGroup.idgroup) |
||
822 | ).filter(GroupHierarchy.hops > 0)
|
||
823 | |||
824 | # Ensuite on les exclut de la liste des groupes,
|
||
825 | # pour ne garder que ceux qui sont au sommet de
|
||
826 | # l'arbre et qui constituent nos "root groups".
|
||
827 | root_groups = DBSession.query( |
||
828 | SupItemGroup, |
||
829 | ).except_(children |
||
830 | ).order_by(SupItemGroup.name) |
||
831 | 48acee1e | Francois POIROTTE | |
832 | # On filtre ces groupes racines afin de ne
|
||
833 | # retourner que ceux auquels l'utilisateur a accès
|
||
834 | user = get_current_user() |
||
835 | is_manager = in_group('managers').is_met(request.environ)
|
||
836 | if not is_manager: |
||
837 | eec46cb0 | Vincent QUEMENER | |
838 | root_groups = root_groups.join( |
||
839 | (GroupHierarchy, |
||
840 | GroupHierarchy.idchild == SupItemGroup.idgroup), |
||
841 | (DataPermission, |
||
842 | DataPermission.idgroup == GroupHierarchy.idparent), |
||
843 | (USER_GROUP_TABLE, USER_GROUP_TABLE.c.idgroup == \ |
||
844 | DataPermission.idusergroup), |
||
845 | ).filter(USER_GROUP_TABLE.c.username == user.user_name) |
||
846 | 48acee1e | Francois POIROTTE | |
847 | groups = [] |
||
848 | 0bd9c069 | Francois POIROTTE | for group in root_groups.all(): |
849 | 48acee1e | Francois POIROTTE | groups.append({ |
850 | 'id' : group.idgroup,
|
||
851 | 'name' : group.name,
|
||
852 | }) |
||
853 | |||
854 | return dict(groups = groups, leaves=[]) |
||
855 | |||
856 | 0842bb2c | Francois POIROTTE | def get_last_modification_timestamp(event_id_list, |
857 | 4dd2035e | Francois POIROTTE | value_if_none=datetime.now()): |
858 | 97f6d842 | Vincent QUEMENER | """
|
859 | 0842bb2c | Francois POIROTTE | Récupère le timestamp de la dernière modification
|
860 | 97f6d842 | Vincent QUEMENER | opérée sur l'un des événements dont l'identifiant
|
861 | fait partie de la liste passée en paramètre.
|
||
862 | """
|
||
863 | last_modification_timestamp = DBSession.query( |
||
864 | func.max(EventHistory.timestamp), |
||
865 | ).filter(EventHistory.idevent.in_(event_id_list) |
||
866 | ).scalar() |
||
867 | e9ccb711 | Francois POIROTTE | if not last_modification_timestamp: |
868 | 24334b4b | Vincent QUEMENER | if not value_if_none: |
869 | return None |
||
870 | else:
|
||
871 | last_modification_timestamp = value_if_none |
||
872 | e9ccb711 | Francois POIROTTE | return datetime.fromtimestamp(mktime(
|
873 | last_modification_timestamp.timetuple())) |