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

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