Package ZenEvents :: Module EventClassInst
[hide private]
[frames] | no frames]

Source Code for Module ZenEvents.EventClassInst

  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 Products.ZenModel.ZenossSecurity import * 
 27   
 28  from Products.ZenRelations.RelSchema import * 
 29  from Products.ZenModel.ZenModelRM import ZenModelRM 
 30  from Products.ZenModel.EventView import EventView 
 31  from Products.ZenModel.ZenPackable import ZenPackable 
 32  from Products.ZenWidgets import messaging 
 33  from Products.ZenUtils.Utils import convToUnits, zdecode 
 34   
 35   
36 -def manage_addEventClassInst(context, id, REQUEST = None):
37 """make a device class""" 38 dc = EventClassInst(id) 39 context._setObject(id, dc) 40 if REQUEST is not None: 41 REQUEST['RESPONSE'].redirect(context.absolute_url() + '/manage_main')
42 43 44 addEventClassInst = DTMLFile('dtml/addEventClassInst',globals()) 45 46
47 -class EventClassPropertyMixin(object):
48 49 transform = '' 50 51 _properties = ( 52 {'id':'transform', 'type':'text', 'mode':'w'}, 53 ) 54
55 - def applyValues(self, evt):
56 """Modify event with values taken from dict Inst. 57 Any non-None property values are applied to the event. 58 """ 59 evt._clearClasses = copy.copy(getattr(self, "zEventClearClasses", [])) 60 evt._action = getattr(self, "zEventAction", "status") 61 sev = getattr(self, "zEventSeverity", -1) 62 if sev >= 0: 63 if evt.severity > 0: 64 evt.severity = sev 65 updates = {} 66 for name in 'resolution', 'explanation': 67 value = getattr(self, name, None) 68 if value is not None and value != '': 69 updates[name] = value 70 evt.updateFromDict(updates) 71 return evt
72
73 - def applyTransform(self, evt, device):
74 """ 75 Apply transforms on an event from the top level of the Event Class Tree 76 down to the actual Event Rules (EventClassInst) 77 """ 78 transpath = self._eventClassPath() 79 variables_and_funcs = { 80 'evt':evt, 'device':device, 'dev':device, 81 'convToUnits':convToUnits, 'zdecode':zdecode, 82 'txnCommit':transaction.commit 83 } 84 for eventclass in transpath: 85 if not eventclass.transform: continue 86 try: 87 log.debug('Applying transform at %s', 88 eventclass.getPrimaryDmdId()) 89 exec(eventclass.transform, variables_and_funcs) 90 except Exception, ex: 91 log.exception( 92 "Error processing transform on Event Class %s", 93 eventclass.getPrimaryId()) 94 return variables_and_funcs['evt']
95 96
97 - def inheritedTransforms(self):
98 """ 99 Make a string that brings together all the transforms inherited from the 100 base EventClass to self. 101 """ 102 transpath = self._eventClassPath() 103 transtext = [] 104 for obj in transpath: 105 if not obj.transform: continue 106 if obj.transform == self.transform: break 107 transtext.append("""<a href='%s/editEventClassTransform'>%s<a> 108 """ % (obj.getPrimaryUrlPath(), obj.getPrimaryDmdId())) 109 transtext.append("<pre>%s</pre>" % obj.transform) 110 return "\n".join(transtext)
111 112
113 - def testTransformStyle(self):
114 """Test our transform by compiling it. 115 """ 116 try: 117 if self.transform: 118 compile(self.transform, "<string>", "exec") 119 except: 120 return "color:#FF0000;"
121 122
123 - def _eventClassPath(self):
124 """ 125 Return the path to our current EventClassInst from the top level 126 EventClass down. We use this to process and display the heirarchy of 127 event transforms. 128 """ 129 transpath = [] 130 for obj in aq_chain(self): 131 # skip over relationships in the aq_chain 132 if not isinstance(obj, EventClassPropertyMixin): continue 133 if obj.id == 'dmd': break 134 transpath.append(obj) 135 transpath.reverse() 136 return transpath
137 138 # Why is this a subclass of EventView? 139
140 -class EventClassInst(EventClassPropertyMixin, ZenModelRM, EventView, 141 ZenPackable):
142 """ 143 EventClassInst. 144 """ 145 146 event_key = meta_type = "EventClassInst" 147 148 default_catalog = "eventClassSearch" 149 150 actions = ("status", "history", "heartbeat", "drop") 151 152 _properties = EventClassPropertyMixin._properties + ( 153 {'id':'eventClassKey', 'type':'string', 'mode':'w'}, 154 {'id':'sequence', 'type':'int', 'mode':'w'}, 155 {'id':'rule', 'type':'string', 'mode':'w'}, 156 {'id':'regex', 'type':'string', 'mode':'w'}, 157 {'id':'example', 'type':'string', 'mode':'w'}, 158 {'id':'explanation', 'type':'text', 'mode':'w'}, 159 {'id':'resolution', 'type':'text', 'mode':'w'}, 160 ) 161 162 163 _relations = ZenPackable._relations + ( 164 ("eventClass", ToOne(ToManyCont,"Products.ZenEvents.EventClass","instances")), 165 ) 166 167 168 # Screen action bindings (and tab definitions) 169 factory_type_information = ( 170 { 171 'id' : 'EventClassInst', 172 'meta_type' : 'EventClassInst', 173 'description' : """Base class for all devices""", 174 'icon' : 'EventClassInst.gif', 175 'product' : 'ZenEvents', 176 'factory' : 'manage_addEventClassInst', 177 'immediate_view' : 'eventClassInstStatus', 178 'actions' : 179 ( 180 { 'id' : 'status' 181 , 'name' : 'Status' 182 , 'action' : 'eventClassInstStatus' 183 , 'permissions' : (Permissions.view, ) 184 }, 185 { 'id' : 'edit' 186 , 'name' : 'Edit' 187 , 'action' : 'eventClassInstEdit' 188 , 'permissions' : ("Manage DMD", ) 189 }, 190 { 'id' : 'sequence' 191 , 'name' : 'Sequence' 192 , 'action' : 'eventClassInstSequence' 193 , 'permissions' : (Permissions.view,) 194 }, 195 { 'id' : 'config' 196 , 'name' : 'zProperties' 197 , 'action' : 'zPropertyEdit' 198 , 'permissions' : ("Manage DMD",) 199 }, 200 { 'id' : 'events' 201 , 'name' : 'Events' 202 , 'action' : 'viewEvents' 203 , 'permissions' : (Permissions.view, ) 204 }, 205 # { 'id' : 'historyEvents' 206 # , 'name' : 'History' 207 # , 'action' : 'viewHistoryEvents' 208 # , 'permissions' : (Permissions.view, ) 209 # }, 210 { 'id' : 'viewHistory' 211 , 'name' : 'Modifications' 212 , 'action' : 'viewHistory' 213 , 'permissions' : (ZEN_VIEW_MODIFICATIONS,) 214 }, 215 ) 216 }, 217 ) 218 219 security = ClassSecurityInfo() 220
221 - def __init__(self, id):
222 ZenModelRM.__init__(self, id) 223 self.eventClassKey = id 224 self.sequence = None 225 self.rule = "" 226 self.regex = "" 227 self.example = "" 228 self.explanation = "" 229 self.resolution = ""
230 231
232 - def getStatus(self, **kwargs):
233 """Return the status number for this device of class statClass. 234 """ 235 return self.getEventManager().getStatusME(self, 236 statusclass=self.getEventClass(), 237 **kwargs)
238 239
240 - def getEventClass(self):
241 """Return the full EventClass of this EventClassInst.""" 242 return self.getOrganizerName()
243
244 - def getEventClassHref(self):
245 """Return href of our class. 246 """ 247 return self.eventClass().getPrimaryUrlPath()
248 249
250 - def getDmdKey(self):
251 """Return the dmd key of this mapping ie: /App/Start/zentinel 252 """ 253 return self.getOrganizerName() + "/" + self.id
254 255
256 - def applyExtraction(self, evt):
257 """ 258 Apply the event dict regex to extract additional values from the event. 259 """ 260 if self.regex: 261 m = re.search(self.regex, evt.message) 262 if m: evt.updateFromDict(m.groupdict()) 263 return evt
264 265
266 - def applyValues(self, evt):
267 """Modify event with values taken from dict Inst. 268 Any non-None property values are applied to the event. 269 """ 270 evt.eventClass = self.getEventClass() 271 evt.eventClassMapping = '%s/%s' % (self.getEventClass(), self.id) 272 return EventClassPropertyMixin.applyValues(self, evt)
273
274 - def ruleOrRegex(self, limit=None):
275 """Return the rule if it exists else return the regex. 276 limit limits the number of characters returned. 277 """ 278 value = self.rule and self.rule or self.regex 279 if not value and self.example: 280 value = self.example 281 if limit: value = value[:limit] 282 return value
283 284
285 - def match(self, evt, device):
286 """ 287 Match an event message against our regex. 288 289 @parameter evt: event to match in our mapping 290 @type evt: dictionary 291 @parameter device: device 292 @type device: DMD object 293 @return: boolean 294 @rtype: boolean 295 """ 296 value = False 297 log.debug("match on:%s", self.getPrimaryDmdId()) 298 if self.rule: 299 try: 300 log.debug("eval rule:%s", self.rule) 301 value = eval(self.rule, {'evt':evt, 'dev':device, 'device': device}) 302 except Exception, e: 303 logging.warn("EventClassInst: %s rule failure: %s", 304 self.getDmdKey(), e) 305 else: 306 try: 307 log.debug("regex='%s' message='%s'", self.regex, evt.message) 308 value = re.search(self.regex, evt.message, re.I) 309 except sre_constants.error: pass 310 return value
311 312
313 - def testRegexStyle(self):
314 """Test our regex using the example event string. 315 """ 316 if self.example: 317 try: 318 value = re.search(self.regex, self.example, re.I) 319 if not value: return "color:#FF0000;" 320 except sre_constants.error: 321 return "color:#FF0000;"
322 323
324 - def testRuleStyle(self):
325 """Test our rule by compiling it. 326 """ 327 try: 328 if self.rule: 329 compile(self.rule, "<string>", "eval") 330 except: 331 return "color:#FF0000;"
332 333
334 - def sameKey(self):
335 """Return a list of all mappings with the same eventClassKey. 336 """ 337 return self.eventClass().find(self.eventClassKey)
338 339
340 - def manage_afterAdd(self, item, container):
341 """ 342 Device only propagates afterAdd if it is the added object. 343 """ 344 self.index_object() 345 ZenModelRM.manage_afterAdd(self, item, container)
346 347
348 - def manage_afterClone(self, item):
349 """Not really sure when this is called.""" 350 ZenModelRM.manage_afterClone(self, item) 351 self.index_object()
352 353
354 - def manage_beforeDelete(self, item, container):
355 """ 356 Device only propagates beforeDelete if we are being deleted or copied. 357 Moving and renaming don't propagate. 358 """ 359 ZenModelRM.manage_beforeDelete(self, item, container) 360 self.unindex_object()
361 362 363 security.declareProtected('Manage DMD', 'manage_resequence')
364 - def manage_resequence(self, seqmap, REQUEST=None):
365 """Reorder the sequence of eventClassMappings with the same key. 366 """ 367 # first pass set new sequence 368 for i, map in enumerate(self.sameKey()): 369 map.sequence = seqmap[i] 370 # second pass take out any holes 371 for i, map in enumerate(self.sameKey()): 372 map.sequence = i 373 if REQUEST: 374 return self.callZenScreen(REQUEST)
375 376 377 security.declareProtected('Manage DMD', 'manage_editEventClassInst')
378 - def manage_editEventClassInst(self, name="", eventClassKey='', 379 regex='', rule='', example='', 380 transform='', 381 explanation='', resolution='', REQUEST=None):
382 """Edit a EventClassInst from a web page. 383 """ 384 redirect = self.rename(name) 385 if eventClassKey and self.eventClassKey != eventClassKey: 386 self.unindex_object() 387 self.sequence = self.eventClass().nextSequenceNumber(eventClassKey) 388 self.eventClassKey = eventClassKey 389 self.index_object() 390 self.regex = regex 391 self.rule = rule 392 self.example = example 393 self.transform = transform 394 self.explanation = explanation 395 self.resolution = resolution 396 if REQUEST: 397 from Products.ZenUtils.Time import SaveMessage 398 messaging.IMessageSender(self).sendToBrowser( 399 'Saved', SaveMessage()) 400 return self.callZenScreen(REQUEST, redirect)
401 402 403 InitializeClass(EventClassInst) 404