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

# Source Code for Module Products.ZenEvents.ActionRule

      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  import time
     14  import re
     15  from sets import Set
     16  import logging
     17  log = logging.getLogger("zen.ActionRule")
     18
     19  from Globals import InitializeClass
     20  from Globals import DTMLFile
     21  from AccessControl import ClassSecurityInfo
     22  from Products.ZenModel.ZenossSecurity import *
     23  from Acquisition import aq_parent
     24
     25  from Products.ZenModel.ZenModelRM import ZenModelRM
     26  from Products.ZenRelations.RelSchema import *
     27  from Products.ZenUtils import Time
     28  from Products.ZenEvents.EventFilter import EventFilter
     29  from Products.ZenWidgets import messaging
     30
     31  from ActionRuleWindow import ActionRuleWindow
     32 -def _downcase(s):
     33      return s[0:1].lower() + s[1:]
     34
     35 -def manage_addActionRule(context, id, REQUEST=None):
     36      """Create an action rule"""
     37      ed = ActionRule(id)
     38      context._setObject(id, ed)
     39      if REQUEST is not None:
     40          REQUEST['RESPONSE'].redirect(context.absolute_url() + '/manage_main')
     41
     42  addActionRule = DTMLFile('dtml/addActionRule',globals())
     43
     44 -class ActionRule(ZenModelRM, EventFilter):
     45      """
     46      Rule applied to events that then executes an action on matching events.
     47      """
     48
     49      meta_type = "ActionRule"
     50
     51      where = "severity >= 4 and eventState = 0 and prodState = 1000"
     52      delay = 0
     53      repeatTime = 0
     54      action = "email"
     55      format = "[zenoss] %(device)s %(summary)s"
     56      body =  "Device: %(device)s\n" \
     57              "Component: %(component)s\n" \
     58              "Severity: %(severityString)s\n" \
     59              "Time: %(firstTime)s\n" \
     60              "Message:\n%(message)s\n" \
     61              "<a href=\"%(eventUrl)s\">Event Detail</a>\n" \
     62              "<a href=\"%(ackUrl)s\">Acknowledge</a>\n" \
     63              "<a href=\"%(deleteUrl)s\">Delete</a>\n" \
     64              "<a href=\"%(eventsUrl)s\">Device Events</a>\n"
     65      sendClear = True
     66      clearFormat = "[zenoss] CLEAR: %(device)s %(clearOrEventSummary)s"
     67      clearBody =  \
     68              "Event: '%(summary)s'\n" \
     69              "Cleared by: '%(clearSummary)s'\n" \
     70              "At: %(clearFirstTime)s\n" \
     71              "Device: %(device)s\n" \
     72              "Component: %(component)s\n" \
     73              "Severity: %(severityString)s\n" \
     74              "Message:\n%(message)s\n" \
     75              "<a href=\"%(undeleteUrl)s\">Undelete</a>\n"
     76      enabled = False
     77      actionTypes = ("page", "email")
     78      targetAddr = ""
     79      plainText = False
     80
     81      _properties = ZenModelRM._properties + (
     82          {'id':'where', 'type':'text', 'mode':'w'},
     83          {'id':'format', 'type':'text', 'mode':'w'},
     84          {'id':'body', 'type':'text', 'mode':'w'},
     85          {'id':'sendClear', 'type':'boolean', 'mode':'w'},
     86          {'id':'clearFormat', 'type':'text', 'mode':'w'},
     87          {'id':'clearBody', 'type':'text', 'mode':'w'},
     88          {'id':'delay', 'type':'int', 'mode':'w'},
     89          {'id':'action', 'type':'selection', 'mode':'w',
     90              'select_variable': 'actionTypes',},
     91          {'id':'enabled', 'type':'boolean', 'mode':'w'},
     92          {'id':'targetAddr', 'type':'string', 'mode':'w'},
     93          {'id':'repeatTime', 'type':'int', 'mode':'w'},
     94          {'id':'plainText', 'type':'boolean', 'mode':'w'},
     95      )
     96
     97      _relations = (
     98          ("windows", ToManyCont(ToOne,"Products.ZenEvents.ActionRuleWindow","actionRule")),
     99          )
    100
    101      factory_type_information = (
    102          {
    103              'id'             : 'ActionRule',
    104              'meta_type'      : 'ActionRule',
    105              'description'    : """Define action taken against events""",
    106              'icon'           : 'ActionRule.gif',
    107              'product'        : 'ZenEvents',
    108              'factory'        : 'manage_addActionRule',
    109              'immediate_view' : 'editActionRule',
    110              'actions'        :
    111              (
    112                  { 'id'            : 'edit'
    113                  , 'name'          : 'Edit'
    114                  , 'action'        : 'editActionRule'
    115                  , 'permissions'   : (ZEN_CHANGE_ALERTING_RULES,)
    116                  },
    117                  { 'id'            : 'message'
    118                  , 'name'          : 'Message'
    119                  , 'action'        : 'editActionRuleMessage'
    120                  , 'permissions'   : (ZEN_CHANGE_ALERTING_RULES,)
    121                  },
    122                  { 'id'            : 'schedule'
    123                  , 'name'          : 'Schedule'
    124                  , 'action'        : 'editActionRuleSchedule'
    125                  , 'permissions'   : (ZEN_CHANGE_ALERTING_RULES,)
    126                  },
    127              )
    128           },
    129          )
    130
    131      security = ClassSecurityInfo()
    132
    133
    134 -    def breadCrumbs(self, terminator='dmd'):
    135          """Return the breadcrumb links for this object add ActionRules list.
    136          [('url','id'), ...]
    137          """
    138          crumbs = super(ActionRule, self).breadCrumbs(terminator)
    139          url = aq_parent(self).absolute_url_path() + "/editActionRules"
    140          crumbs.insert(-1,(url,'Alerting Rules'))
    141          return crumbs
    142
    143
    144 -    def getEventFields(self):
    145          """Return list of fields used in format.
    146          """
    147          regex = re.compile(r'%\(([^\)]+)\)s')
    148          clearRegex = re.compile(r'%\(clear([^\)]+)\)s')
    149          result = Set()
    150          result.update(regex.findall(self.format))
    151          result.update(regex.findall(self.body))
    152          result.update([ f for f in regex.findall(self.clearFormat) \
    153              if not f.startswith('clear') ])
    154          result.update([ f for f in regex.findall(self.clearBody) \
    155              if not f.startswith('clear') ])
    156          result.update(map(_downcase, clearRegex.findall(self.clearFormat)))
    157          result.update(map(_downcase, clearRegex.findall(self.clearBody)))
    158          notDb = Set('orEventSummary eventUrl eventsUrl ackUrl deleteUrl undeleteUrl severityString'.split())
    159          notMsg = ['severity', 'summary', 'ownerid', 'stateChange']
    160          return list(result - notDb) + notMsg
    161
    162
    163 -    def checkFormat(self):
    164          """Check that the format string has valid fields.
    165          """
    166          evtfields = self.dmd.ZenEventManager.getFieldList()
    167          for field in self.getEventFields():
    168              if field not in evtfields:
    169                  return False
    170          return True
    171
    172
    173 -    def getAddresses(self):
    174          """Return the correct addresses for the action this rule uses.
    175          """
    176          if self.targetAddr:
    177              return [self.targetAddr]
    178          elif self.action == "page":
    179              return self.getUser().getPagerAddresses()
    180          elif self.action == "email":
    181              return self.getUser().getEmailAddresses()
    182
    183
    184 -    def getUser(self):
    185          """Return the user this action is for.
    186          """
    187          return self.getPrimaryParent()
    188
    189 -    def getUserid(self):
    190          """Return the userid this action is for.
    191          """
    192          return self.getUser().getId()
    193
    194
    195      security.declareProtected(ZEN_CHANGE_ALERTING_RULES, 'manage_editActionRule')
    196 -    def manage_editActionRule(self, REQUEST=None):
    197          """Update user settings.
    198          """
    199          if not self.enabled:
    200              self._clearAlertState()
    201          import WhereClause
    202          if REQUEST.form.has_key('onRulePage') \
    203                  and not REQUEST.form.has_key('where'):
    204              clause = WhereClause.fromFormVariables(self.genMeta(), REQUEST.form)
    205              if clause:
    206                  REQUEST.form['where'] = clause
    207              else:
    208                  messaging.IMessageSender(self).sendToBrowser(
    209                      'Invalid',
    210                      'An alerting rule must have at least one criterion.',
    211                      priority=messaging.WARNING
    212                  )
    213                  return self.callZenScreen(REQUEST)
    214          return self.zmanage_editProperties(REQUEST)
    215
    216
    217 -    def _clearAlertState(self):
    218          """Clear state in alert_state before we are deleted.
    219          """
    220          zem = self.dmd.ZenEventManager
    221          conn = zem.connect()
    222          try:
    223              delcmd = "delete from alert_state where %s" % self.sqlwhere()
    224              log.debug("clear alert state '%s'", delcmd)
    225              curs = conn.cursor()
    226              curs.execute(delcmd)
    227          finally: zem.close(conn)
    228
    229 -    def sqlwhere(self):
    230          """Return sql where to select alert_state data for this event.
    231          """
    232          return "userid = '%s' and rule = '%s'" % (self.getUserid(), self.id)
    233
    234 -    def nextActiveWindow(self):
    235          next = None
    236          w = None
    237          for ar in self.windows():
    238              if next is None or ar.next() < next:
    239                  next = ar.next()
    240                  w = ar
    241          return w
    242
    243 -    def nextActive(self):
    244          if self.enabled:
    245              return time.time()
    246          w = self.nextActiveWindow()
    247          if w:
    248              return w.next()
    249
    250 -    def nextActiveNice(self):
    251          if self.enabled:
    252              return "Now"
    253          t = self.nextActive()
    254          if t is None:
    255              return "Never"
    256          return Time.LocalDateTime(t)
    257
    258 -    def nextDurationNice(self):
    259          w = self.nextActiveWindow()
    260          if w is None:
    261              return "Forever"
    262          if self.enabled:
    263              next = w.next()
    264              if next:
    265                  return Time.Duration((next + w.duration) - time.time())
    266          return Time.Duration(w.duration)
    267
    268 -    def repeatNice(self):
    269          w = self.nextActiveWindow()
    270          if w is None:
    271              return "Never"
    272          return w.repeat
    273
    274      security.declareProtected(ZEN_CHANGE_ALERTING_RULES,
    275                                'manage_addActionRuleWindow')
    276 -    def manage_addActionRuleWindow(self, newId, REQUEST=None):
    277          "Add a ActionRule Window to this device"
    278          if newId:
    279              mw = ActionRuleWindow(newId)
    280              self.windows._setObject(newId, mw)
    281          if REQUEST:
    282              messaging.IMessageSender(self).sendToBrowser(
    283                  'Active Period Added',
    284                  'The action rule window has been created successfully.'
    285              )
    286              return self.callZenScreen(REQUEST)
    287
    288      security.declareProtected(ZEN_CHANGE_ALERTING_RULES,
    289                                'manage_deleteActionRuleWindow')
    290 -    def manage_deleteActionRuleWindow(self, windowIds, REQUEST=None):
    291          "Delete a ActionRule Window to this device"
    292          import types
    293          if type(windowIds) in types.StringTypes:
    294              windowIds = [windowIds]
    295          for id in windowIds:
    296              self.windows._delObject(id)
    297          if REQUEST:
    298              messaging.IMessageSender(self).sendToBrowser(
    299                  'Active Period Deleted',
    300                  'The action rule window has been removed.'
    301              )
    302              return self.callZenScreen(REQUEST)
    303
    304
    305  InitializeClass(ActionRule)
    306