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