| Trees | Indices | Help |
|
|---|
|
|
1 ###########################################################################
2 #
3 # This program is part of Zenoss Core, an open source monitoring platform.
4 # Copyright (C) 2007, Zenoss Inc.
5 #
6 # This program is free software; you can redistribute it and/or modify it
7 # under the terms of the GNU General Public License version 2 as published by
8 # the Free Software Foundation.
9 #
10 # For complete information please visit: http://www.zenoss.com/oss/
11 #
12 ###########################################################################
13
14 import copy
15 import re
16 import sre_constants
17 import logging
18 import transaction
19 log = logging.getLogger("zen.Events")
20
21 from Globals import DTMLFile
22 from Globals import InitializeClass
23 from AccessControl import ClassSecurityInfo
24 from AccessControl import Permissions
25 from Acquisition import aq_chain
26 from zope.interface import implements
27
28 from Products.ZenModel.interfaces import IIndexed
29 from Products.ZenModel.ZenossSecurity import *
30 from Products.ZenRelations.RelSchema import *
31 from Products.ZenModel.ZenModelRM import ZenModelRM
32 from Products.ZenModel.EventView import EventView
33 from Products.ZenModel.ZenPackable import ZenPackable
34 from Products.ZenWidgets import messaging
35 from Products.ZenUtils.Utils import convToUnits, zdecode
36
37
39 """make a device class"""
40 dc = EventClassInst(id)
41 context._setObject(id, dc)
42 if REQUEST is not None:
43 REQUEST['RESPONSE'].redirect(context.absolute_url() + '/manage_main')
44
45
46 addEventClassInst = DTMLFile('dtml/addEventClassInst',globals())
47
48
50
51 transform = ''
52
53 _properties = (
54 {'id':'transform', 'type':'text', 'mode':'w'},
55 )
56
58 """Modify event with values taken from dict Inst.
59 Any non-None property values are applied to the event.
60 """
61 evt._clearClasses = copy.copy(getattr(self, "zEventClearClasses", []))
62 evt._action = getattr(self, "zEventAction", "status")
63 sev = getattr(self, "zEventSeverity", -1)
64 if sev >= 0:
65 if evt.severity > 0:
66 evt.severity = sev
67 log.debug("Per transform/mapping, using severity %s, action '%s' and clear classes %s",
68 evt.severity, evt._action, evt._clearClasses)
69 updates = {}
70 for name in 'resolution', 'explanation':
71 value = getattr(self, name, None)
72 if value is not None and value != '':
73 updates[name] = value
74 if updates:
75 log.debug("Adding fields from transform/mapping: %s", updates)
76 evt.updateFromDict(updates)
77 return evt
78
80 """
81 Convenience function to number the transform info
82 """
83 numberedTransform = []
84 for lineNo in range(0, len(transformLines)):
85 line = "%3s %s" % (lineNo, transformLines[lineNo])
86 numberedTransform.append(line)
87 return '\n'.join(numberedTransform)
88
90 """
91 Try to convert the rather horrible looking traceback that
92 is hard to understand into something actionable by the user.
93 """
94 transformName = '/%s'% '/'.join(eventclass.getPhysicalPath()[4:])
95 summary = "Error processing transform/mapping on Event Class %s" % \
96 transformName
97
98 import sys
99 from traceback import format_exc, extract_tb
100 badLineNo = extract_tb(sys.exc_info()[2])[-1][1] - 1
101
102 transformLines = eventclass.transform.splitlines()
103 transformFormatted = self.formatTransform(transformLines)
104 exceptionText = format_exc(0).splitlines()[1]
105 message = """%s
106 Problem on line %s: %s
107 %s
108
109 Transform:
110 %s
111 """ % (summary, badLineNo, exceptionText, transformLines[badLineNo],
112 transformFormatted)
113 log.warn(message)
114
115 # Now send an event
116 zem = self.getDmd().ZenEventManager
117 badEvt = dict(
118 dedupid='|'.join([transformName,zem.host]),
119 # Don't send the *same* event class or we trash and
120 # and crash endlessly
121 eventClass='/',
122 device=zem.host,
123 component=transformName,
124 summary=summary,
125 severity=4,
126 message = "Problem with line %s: %s" % (badLineNo,
127 transformLines[badLineNo]),
128 transform=transformFormatted,
129 exception=exceptionText,
130 )
131 zem.sendEvent(badEvt)
132
134 """
135 Apply transforms on an event from the top level of the Event Class Tree
136 down to the actual Event Rules (EventClassInst)
137 """
138 transpath = self._eventClassPath()
139 variables_and_funcs = {
140 'evt':evt, 'device':device, 'dev':device,
141 'convToUnits':convToUnits, 'zdecode':zdecode,
142 'txnCommit':transaction.commit, 'dmd':self.dmd,
143 'log':log,
144 }
145 for eventclass in transpath:
146 if not eventclass.transform: continue
147 try:
148 log.debug('Applying transform/mapping at Event Class %s',
149 eventclass.getPrimaryDmdId())
150 exec(eventclass.transform, variables_and_funcs)
151 log.debug('Results after transform: %s',
152 variables_and_funcs['evt'])
153 except Exception, ex:
154 self.sendTransformException(eventclass, evt)
155
156 return variables_and_funcs['evt']
157
158
160 """
161 Make a string that brings together all the transforms inherited from the
162 base EventClass to self.
163 """
164 transpath = self._eventClassPath()
165 transtext = []
166 for obj in transpath:
167 if not obj.transform: continue
168 if obj.transform == self.transform: break
169 transtext.append("""<a href='%s/editEventClassTransform'>%s<a>
170 """ % (obj.getPrimaryUrlPath(), obj.getPrimaryDmdId()))
171 transtext.append("<pre>%s</pre>" % obj.transform)
172 return "\n".join(transtext)
173
174
176 """Test our transform by compiling it.
177 """
178 try:
179 if self.transform:
180 compile(self.transform, "<string>", "exec")
181 except:
182 return "color:#FF0000;"
183
184
186 """
187 Return the path to our current EventClassInst from the top level
188 EventClass down. We use this to process and display the heirarchy of
189 event transforms.
190 """
191 transpath = []
192 for obj in aq_chain(self):
193 # skip over relationships in the aq_chain
194 if not isinstance(obj, EventClassPropertyMixin): continue
195 if obj.id == 'dmd': break
196 transpath.append(obj)
197 transpath.reverse()
198 return transpath
199
200 # Why is this a subclass of EventView?
201
204 """
205 EventClassInst.
206 """
207 implements(IIndexed)
208 event_key = meta_type = "EventClassInst"
209
210 default_catalog = "eventClassSearch"
211
212 actions = ("status", "history", "heartbeat", "drop")
213
214 _properties = EventClassPropertyMixin._properties + (
215 {'id':'eventClassKey', 'type':'string', 'mode':'w'},
216 {'id':'sequence', 'type':'int', 'mode':'w'},
217 {'id':'rule', 'type':'string', 'mode':'w'},
218 {'id':'regex', 'type':'string', 'mode':'w'},
219 {'id':'example', 'type':'string', 'mode':'w'},
220 {'id':'explanation', 'type':'text', 'mode':'w'},
221 {'id':'resolution', 'type':'text', 'mode':'w'},
222 )
223
224
225 _relations = ZenPackable._relations + (
226 ("eventClass", ToOne(ToManyCont,"Products.ZenEvents.EventClass","instances")),
227 )
228
229
230 # Screen action bindings (and tab definitions)
231 factory_type_information = (
232 {
233 'id' : 'EventClassInst',
234 'meta_type' : 'EventClassInst',
235 'description' : """Base class for all devices""",
236 'icon' : 'EventClassInst.gif',
237 'product' : 'ZenEvents',
238 'factory' : 'manage_addEventClassInst',
239 'immediate_view' : 'eventClassInstStatus',
240 'actions' :
241 (
242 { 'id' : 'status'
243 , 'name' : 'Status'
244 , 'action' : 'eventClassInstStatus'
245 , 'permissions' : (Permissions.view, )
246 },
247 { 'id' : 'edit'
248 , 'name' : 'Edit'
249 , 'action' : 'eventClassInstEdit'
250 , 'permissions' : ("Manage DMD", )
251 },
252 { 'id' : 'sequence'
253 , 'name' : 'Sequence'
254 , 'action' : 'eventClassInstSequence'
255 , 'permissions' : (Permissions.view,)
256 },
257 { 'id' : 'config'
258 , 'name' : 'Configuration Properties'
259 , 'action' : 'zPropertyEditNew'
260 , 'permissions' : ("Manage DMD",)
261 },
262 { 'id' : 'events'
263 , 'name' : 'Events'
264 , 'action' : 'viewEvents'
265 , 'permissions' : (Permissions.view, )
266 },
267 # { 'id' : 'historyEvents'
268 # , 'name' : 'History'
269 # , 'action' : 'viewHistoryEvents'
270 # , 'permissions' : (Permissions.view, )
271 # },
272 { 'id' : 'viewHistory'
273 , 'name' : 'Modifications'
274 , 'action' : 'viewNewHistory'
275 , 'permissions' : (ZEN_VIEW_MODIFICATIONS,)
276 },
277 )
278 },
279 )
280
281 security = ClassSecurityInfo()
282
284 ZenModelRM.__init__(self, id)
285 self.eventClassKey = id
286 self.sequence = None
287 self.rule = ""
288 self.regex = ""
289 self.example = ""
290 self.explanation = ""
291 self.resolution = ""
292
293
295 """Return the status number for this device of class statClass.
296 """
297 return self.getEventManager().getStatusME(self,
298 statusclass=self.getEventClass(),
299 **kwargs)
300
301
305
310
311
313 """Return the dmd key of this mapping ie: /App/Start/zentinel
314 """
315 return self.getOrganizerName() + "/" + self.id
316
317
319 """
320 Apply the event dict regex to extract additional values from the event.
321 """
322 if self.regex:
323 m = re.search(self.regex, evt.message)
324 if m: evt.updateFromDict(m.groupdict())
325 return evt
326
327
329 """Modify event with values taken from dict Inst.
330 Any non-None property values are applied to the event.
331 """
332 evt.eventClass = self.getEventClass()
333 evt.eventClassMapping = '%s/%s' % (self.getEventClass(), self.id)
334 return EventClassPropertyMixin.applyValues(self, evt)
335
337 """Return the rule if it exists else return the regex.
338 limit limits the number of characters returned.
339 """
340 value = self.rule and self.rule or self.regex
341 if not value and self.example:
342 value = self.example
343 if limit: value = value[:limit]
344 return value
345
346
348 """
349 Match an event message against our regex.
350
351 @parameter evt: event to match in our mapping
352 @type evt: dictionary
353 @parameter device: device
354 @type device: DMD object
355 @return: boolean
356 @rtype: boolean
357 """
358 value = False
359 log.debug("match on:%s", self.getPrimaryDmdId())
360 if self.rule:
361 try:
362 log.debug("eval rule:%s", self.rule)
363 value = eval(self.rule, {'evt':evt, 'dev':device, 'device': device})
364 except Exception, e:
365 logging.warn("EventClassInst: %s rule failure: %s",
366 self.getDmdKey(), e)
367 else:
368 try:
369 log.debug("regex='%s' message='%s'", self.regex, evt.message)
370 value = re.search(self.regex, evt.message, re.I)
371 except sre_constants.error: pass
372 return value
373
374
376 """Test our regex using the example event string.
377 """
378 if self.example:
379 try:
380 value = re.search(self.regex, self.example, re.I)
381 if not value: return "color:#FF0000;"
382 except sre_constants.error:
383 return "color:#FF0000;"
384
385
387 """Test our rule by compiling it.
388 """
389 try:
390 if self.rule:
391 compile(self.rule, "<string>", "eval")
392 except:
393 return "color:#FF0000;"
394
395
397 """Return a list of all mappings with the same eventClassKey.
398 """
399 return [ i for i in self.eventClass().find(self.eventClassKey) \
400 if i.eventClassKey == self.eventClassKey ]
401
402
403 security.declareProtected('Manage DMD', 'manage_resequence')
405 """Reorder the sequence of eventClassMappings with the same key.
406 """
407 # first pass set new sequence
408 for i, map in enumerate(self.sameKey()):
409 map.sequence = seqmap[i]
410 # second pass take out any holes
411 for i, map in enumerate(self.sameKey()):
412 map.sequence = i
413 if REQUEST:
414 return self.callZenScreen(REQUEST)
415
416
417 security.declareProtected('Manage DMD', 'manage_editEventClassInst')
418 - def manage_editEventClassInst(self, name="", eventClassKey='',
419 regex='', rule='', example='',
420 transform='',
421 explanation='', resolution='', REQUEST=None):
422 """Edit a EventClassInst from a web page.
423 """
424 redirect = self.rename(name)
425 if eventClassKey and self.eventClassKey != eventClassKey:
426 self.unindex_object()
427 self.sequence = self.eventClass().nextSequenceNumber(eventClassKey)
428 self.eventClassKey = eventClassKey
429 self.index_object()
430 self.regex = regex
431 self.rule = rule
432 self.example = example
433 self.transform = transform
434 self.explanation = explanation
435 self.resolution = resolution
436 if REQUEST:
437 from Products.ZenUtils.Time import SaveMessage
438 messaging.IMessageSender(self).sendToBrowser(
439 'Saved', SaveMessage())
440 return self.callZenScreen(REQUEST, redirect)
441
442
443 InitializeClass(EventClassInst)
444
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Wed Jul 14 12:01:49 2010 | http://epydoc.sourceforge.net |