1
2
3
4
5
6
7
8
9
10
11 from ZODB.transact import transact
12
13 import copy
14 import re
15 import sre_constants
16 import logging
17 import transaction
18 import urllib
19 from Products.ZenMessaging.audit import audit
20
21 log = logging.getLogger("zen.Events")
22
23 from Globals import InitializeClass
24 from AccessControl import ClassSecurityInfo
25 from AccessControl import Permissions
26 from Acquisition import aq_chain
27 from zope.interface import implements
28
29 from Products.ZenModel.interfaces import IIndexed
30 from Products.ZenModel.ZenossSecurity import *
31 from Products.ZenRelations.RelSchema import *
32 from Products.ZenModel.ZenModelRM import ZenModelRM
33 from Products.ZenModel.EventView import EventView
34 from Products.ZenModel.ZenPackable import ZenPackable
35 from Products.ZenWidgets import messaging
36 from Products.ZenUtils.guid.interfaces import IGloballyIdentifiable
37 from Products.ZenUtils.Utils import convToUnits, zdecode, getDisplayName
38 from Products.ZenUtils.Time import SaveMessage
39 from Products import Zuul
40 from Products.Zuul.interfaces import IInfo
41
42
49
50
52
53 transform = ''
54
55 _properties = (
56 {'id':'transform', 'type':'text', 'mode':'w'},
57 )
58
60 """Modify event with values taken from dict Inst.
61 Any non-None property values are applied to the event.
62 """
63 evt._clearClasses = copy.copy(getattr(self, "zEventClearClasses", []))
64 evt._action = getattr(self, "zEventAction", "status")
65 sev = getattr(self, "zEventSeverity", -1)
66 if sev >= 0:
67 if evt.severity > 0:
68 evt.severity = sev
69 log.debug("Per transform/mapping, using severity %s, action '%s' and clear classes %s",
70 evt.severity, evt._action, evt._clearClasses)
71 updates = {}
72 for name in 'resolution', 'explanation':
73 value = getattr(self, name, None)
74 if value is not None and value != '':
75 updates[name] = value
76 if updates:
77 log.debug("Adding fields from transform/mapping: %s", updates)
78 evt.updateFromDict(updates)
79 return evt
80
87
156
183
184
199
200
209
210
212 """
213 Return the path to our current EventClassInst from the top level
214 EventClass down. We use this to process and display the heirarchy of
215 event transforms.
216 """
217 transpath = []
218 for obj in aq_chain(self):
219
220 if not isinstance(obj, EventClassPropertyMixin): continue
221 if obj.id == 'dmd': break
222 transpath.append(obj)
223 transpath.reverse()
224 return transpath
225
226
227
228 -class EventClassInst(EventClassPropertyMixin, ZenModelRM, EventView,
229 ZenPackable):
230 """
231 EventClassInst.
232 """
233 implements(IIndexed, IGloballyIdentifiable)
234
235 event_key = meta_type = "EventClassInst"
236
237 default_catalog = "eventClassSearch"
238
239 actions = ("status", "history", "heartbeat", "drop")
240
241 _properties = EventClassPropertyMixin._properties + (
242 {'id':'eventClassKey', 'type':'string', 'mode':'w'},
243 {'id':'sequence', 'type':'int', 'mode':'w'},
244 {'id':'rule', 'type':'string', 'mode':'w'},
245 {'id':'regex', 'type':'string', 'mode':'w'},
246 {'id':'example', 'type':'string', 'mode':'w'},
247 {'id':'explanation', 'type':'text', 'mode':'w'},
248 {'id':'resolution', 'type':'text', 'mode':'w'},
249 )
250
251
252 _relations = ZenPackable._relations + (
253 ("eventClass", ToOne(ToManyCont,"Products.ZenEvents.EventClass","instances")),
254 )
255
256
257
258 factory_type_information = (
259 {
260 'id' : 'EventClassInst',
261 'meta_type' : 'EventClassInst',
262 'description' : """Base class for all devices""",
263 'icon' : 'EventClassInst.gif',
264 'product' : 'ZenEvents',
265 'factory' : 'manage_addEventClassInst',
266 'immediate_view' : 'eventClassInstStatus',
267 'actions' :
268 (
269 { 'id' : 'status'
270 , 'name' : 'Status'
271 , 'action' : 'eventClassInstStatus'
272 , 'permissions' : (Permissions.view, )
273 },
274 { 'id' : 'edit'
275 , 'name' : 'Edit'
276 , 'action' : 'eventClassInstEdit'
277 , 'permissions' : ("Manage DMD", )
278 },
279 { 'id' : 'sequence'
280 , 'name' : 'Sequence'
281 , 'action' : 'eventClassInstSequence'
282 , 'permissions' : (Permissions.view,)
283 },
284 { 'id' : 'config'
285 , 'name' : 'Configuration Properties'
286 , 'action' : 'zPropertyEditNew'
287 , 'permissions' : ("Manage DMD",)
288 },
289 { 'id' : 'events'
290 , 'name' : 'Events'
291 , 'action' : 'viewEvents'
292 , 'permissions' : (Permissions.view, )
293 },
294 )
295 },
296 )
297
298 security = ClassSecurityInfo()
299
309
310
315
317 """Return the full EventClass of this EventClassInst."""
318 return self.getOrganizerName()
319
324
325
327 """Return the dmd key of this mapping ie: /App/Start/zentinel
328 """
329 return self.getOrganizerName() + "/" + self.id
330
331
333 """
334 Apply the event dict regex to extract additional values from the event.
335 """
336 if self.regex:
337 m = re.search(self.regex, evt.message)
338 if m: evt.updateFromDict(m.groupdict())
339 return evt
340
341
349
359
360
361 - def match(self, evt, device):
362 """
363 Match an event message against our regex.
364
365 @parameter evt: event to match in our mapping
366 @type evt: dictionary
367 @parameter device: device
368 @type device: DMD object
369 @return: boolean
370 @rtype: boolean
371 """
372 value = False
373 log.debug("match on:%s", self.getPrimaryDmdId())
374 if self.rule:
375 try:
376 log.debug("eval rule:%s", self.rule)
377 value = eval(self.rule, {'evt':evt, 'dev':device, 'device': device})
378 except Exception, e:
379 logging.warn("EventClassInst: %s rule failure: %s",
380 self.getDmdKey(), e)
381 else:
382 try:
383 log.debug("regex='%s' message='%s'", self.regex, evt.message)
384 value = re.search(self.regex, evt.message, re.I)
385 except sre_constants.error: pass
386 return value
387
388
390 """Test our regex using the example event string.
391 """
392 if self.example:
393 try:
394 value = re.search(self.regex, self.example, re.I)
395 if not value: return "color:#FF0000;"
396 except sre_constants.error:
397 return "color:#FF0000;"
398
399
401 """Test our rule by compiling it.
402 """
403 try:
404 if self.rule:
405 compile(self.rule, "<string>", "eval")
406 except:
407 return "color:#FF0000;"
408
409
415
416
417 security.declareProtected('Manage DMD', 'manage_resequence')
419 """
420 Reorder the sequence of eventClassMappings with the same key.
421 """
422 for num, path in zip(seqmap, seqid):
423 self.unrestrictedTraverse(urllib.unquote(path)).sequence = int(num)
424
425 for i, map in enumerate(self.sameKey()):
426 map.sequence = i
427 if REQUEST:
428 audit('UI.EventClassMapping.Resequence', self.id, sequence=seqmap)
429 return self.callZenScreen(REQUEST)
430
431
432 security.declareProtected('Manage DMD', 'manage_editEventClassInst')
433 - def manage_editEventClassInst(self, name='', eventClassKey='',
434 regex='', rule='', example='',
435 transform='',
436 explanation='', resolution='', REQUEST=None):
437 """Edit an EventClassInst from a web page."""
438
439
440 values = locals()
441
442 oldValues = {
443 'name':getDisplayName(self),
444 'eventClassKey':self.eventClassKey,
445 'regex':self.regex,
446 'rule':self.rule,
447 'example':self.example,
448 'transform':self.transform,
449 'explanation':self.explanation,
450 'resolution':self.resolution,
451 }
452
453 redirect = self.rename(name)
454 if eventClassKey and self.eventClassKey != eventClassKey:
455 self.unindex_object()
456 self.sequence = self.eventClass().nextSequenceNumber(eventClassKey)
457 self.eventClassKey = eventClassKey
458 self.index_object()
459 self.regex = regex
460 self.rule = rule
461 self.example = example
462 self.transform = transform
463 self.explanation = explanation
464 self.resolution = resolution
465 if REQUEST:
466 audit('UI.EventClassMapping.Edit', self, data_=values, oldData_=oldValues, skipFields_=['self','REQUEST'])
467 messaging.IMessageSender(self).sendToBrowser(
468 'Saved', SaveMessage())
469 return self.callZenScreen(REQUEST, redirect)
470
471
472 InitializeClass(EventClassInst)
473