AlarmTool.py 6.84 KB
Newer Older
Sebastien Robin's avatar
Sebastien Robin committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
##############################################################################
#
# Copyright (c) 2004 Nexedi SARL and Contributors. All Rights Reserved.
#                    Sebastien Robin <seb@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
##############################################################################

29
import time
30 31
import threading

Sebastien Robin's avatar
Sebastien Robin committed
32
from AccessControl import ClassSecurityInfo
33
from AccessControl.SecurityManagement import newSecurityManager
Sebastien Robin's avatar
Sebastien Robin committed
34
from Globals import InitializeClass, DTMLFile, PersistentMapping
Jean-Paul Smets's avatar
Jean-Paul Smets committed
35
from Products.ERP5Type.Core.Folder import Folder
Sebastien Robin's avatar
Sebastien Robin committed
36 37 38 39 40
from Products.ERP5Type.Tool.BaseTool import BaseTool
from Products.ERP5Type import Permissions
from Products.ERP5 import _dtmldir
from DateTime import DateTime

41
from zLOG import LOG, INFO
Sebastien Robin's avatar
Sebastien Robin committed
42

43 44 45
try:
  from Products.TimerService import getTimerService
except ImportError:
46
  def getTimerService(self):
47
    pass
Sebastien Robin's avatar
Sebastien Robin committed
48

49 50 51
last_tic = time.time()
last_tic_lock = threading.Lock()

Sebastien Robin's avatar
Sebastien Robin committed
52 53
class AlarmTool(BaseTool):
  """
54 55
    This tool manages alarms.

Vincent Pelletier's avatar
Vincent Pelletier committed
56
    It is used as a central managment point for all alarms.
Sebastien Robin's avatar
Sebastien Robin committed
57

Vincent Pelletier's avatar
Vincent Pelletier committed
58 59
    Inside this tool we have a way to retrieve all reports comings
    from Alarms,...
Sebastien Robin's avatar
Sebastien Robin committed
60 61 62 63 64 65 66 67 68 69 70 71 72 73
  """
  id = 'portal_alarms'
  meta_type = 'ERP5 Alarm Tool'
  portal_type = 'Alarm Tool'

  # Declarative Security
  security = ClassSecurityInfo()

  security.declareProtected( Permissions.ManagePortal, 'manage_overview' )
  manage_overview = DTMLFile( 'explainAlarmTool', _dtmldir )

  security.declareProtected( Permissions.ManagePortal , 'manageAlarmList' )
  manageAlarmList = DTMLFile( 'manageAlarmList', _dtmldir )

74 75 76 77
  security.declareProtected( Permissions.ManagePortal , 'manageAlarmAdvanced' )
  manageAlarmAdvanced = DTMLFile( 'manageAlarmAdvanced', _dtmldir )


Sebastien Robin's avatar
Sebastien Robin committed
78
  manage_options = ( ( { 'label'   : 'Overview'
Vincent Pelletier's avatar
Vincent Pelletier committed
79 80 81 82 83
                       , 'action'   : 'manage_overview'
                       }
                     , { 'label'   : 'All Alarms'
                       , 'action'   : 'manageAlarmList'
                       }
84 85 86 87
                     , { 'label'   : 'Advanced'
                       , 'action'   : 'manageAlarmAdvanced'
                       }
                     ,
Vincent Pelletier's avatar
Vincent Pelletier committed
88 89 90
                     )
                     + Folder.manage_options
                   )
Sebastien Robin's avatar
Sebastien Robin committed
91

92
  _properties = ( {'id': 'interval', 'type': 'int', 'mode': 'w', }, )
93
  interval = 60 # Default interval for alarms is 60 seconds
Vincent Pelletier's avatar
Vincent Pelletier committed
94

Sebastien Robin's avatar
Sebastien Robin committed
95
  # API to manage alarms
Vincent Pelletier's avatar
Vincent Pelletier committed
96 97 98 99 100 101 102
  # Aim of this API:
  #-- see all alarms stored everywhere
  #-- defines global alarms
  #-- activate an alarm
  #-- see reports
  #-- see active alarms
  #-- retrieve all alarms
Sebastien Robin's avatar
Sebastien Robin committed
103 104

  security.declareProtected(Permissions.ModifyPortalContent, 'getAlarmList')
Vincent Pelletier's avatar
Vincent Pelletier committed
105
  def getAlarmList(self, to_active = 0):
Sebastien Robin's avatar
Sebastien Robin committed
106
    """
Vincent Pelletier's avatar
Vincent Pelletier committed
107
      We retrieve thanks to the catalog the full list of alarms
Sebastien Robin's avatar
Sebastien Robin committed
108
    """
109 110
    user = self.portal_catalog.getOwner()
    newSecurityManager(self.REQUEST, user)
Sebastien Robin's avatar
Sebastien Robin committed
111
    if to_active:
112
      now = DateTime()
Vincent Pelletier's avatar
Vincent Pelletier committed
113
      catalog_search = self.portal_catalog(
114 115
        portal_type = self.getPortalAlarmTypeList(), 
        alarm_date={'query':now,'range':'ngt'}
Vincent Pelletier's avatar
Vincent Pelletier committed
116
      )
117
      # check again the alarm date in case the alarm was not yet reindexed
Vincent Pelletier's avatar
Vincent Pelletier committed
118 119
      alarm_list = [x.getObject() for x in catalog_search \
          if x.getObject().getAlarmDate()<=now]
Sebastien Robin's avatar
Sebastien Robin committed
120
    else:
Vincent Pelletier's avatar
Vincent Pelletier committed
121 122 123
      catalog_search = self.portal_catalog(
        portal_type = self.getPortalAlarmTypeList()
      )
124
      alarm_list = [x.getObject() for x in catalog_search]
Sebastien Robin's avatar
Sebastien Robin committed
125 126 127 128 129
    return alarm_list

  security.declareProtected(Permissions.ModifyPortalContent, 'tic')
  def tic(self):
    """
Vincent Pelletier's avatar
Vincent Pelletier committed
130 131
      We will look at all alarms and see if they should be activated,
      if so then we will activate them.
Sebastien Robin's avatar
Sebastien Robin committed
132 133
    """
    current_date = DateTime()
134 135 136 137
    for alarm in self.getAlarmList(to_active=1):
      if alarm:
        user = alarm.getOwner()
        newSecurityManager(self.REQUEST, user)
138
        if alarm.isActive() or not alarm.isEnabled():
139 140 141 142
          # do nothing if already active, or not enabled
          continue
        alarm.activate().activeSense()

143 144
  security.declareProtected(Permissions.ManageProperties, 'isSubscribed')
  def isSubscribed(self):
145 146 147 148 149 150
    """ return True, if we are subscribed to TimerService.
    Otherwise return False.
    """
    service = getTimerService(self)
    if not service:
      LOG('AlarmTool', INFO, 'TimerService not available')
151 152
      return False

153 154 155 156 157
    path = '/'.join(self.getPhysicalPath())
    if path in service.lisSubscriptions():
      return True
    return False

158 159
  security.declareProtected(Permissions.ManageProperties, 'subscribe')
  def subscribe(self):
Vincent Pelletier's avatar
Vincent Pelletier committed
160 161 162
    """
      Subscribe to the global Timer Service.
    """
163 164
    service = getTimerService(self)
    if not service:
165 166
      LOG('AlarmTool', INFO, 'TimerService not available')
      return
167 168 169 170 171
    service.subscribe(self)
    return "Subscribed to Timer Service"

  security.declareProtected(Permissions.ManageProperties, 'unsubscribe')
  def unsubscribe(self):
Vincent Pelletier's avatar
Vincent Pelletier committed
172 173 174
    """
      Unsubscribe from the global Timer Service.
    """
175 176
    service = getTimerService(self)
    if not service:
177 178
      LOG('AlarmTool', INFO, 'TimerService not available')
      return
179 180 181 182 183
    service.unsubscribe(self)
    return "Usubscribed from Timer Service"

  def manage_beforeDelete(self, item, container):
    self.unsubscribe()
184
    BaseTool.inheritedAttribute('manage_beforeDelete')(self, item, container)
185

186 187
  def manage_afterAdd(self, item, container):
    self.subscribe()
188
    BaseTool.inheritedAttribute('manage_afterAdd')(self, item, container)
189

190
  security.declarePrivate('process_timer')
191
  def process_timer(self, interval, tick, prev="", next=""):
192
    """
Vincent Pelletier's avatar
Vincent Pelletier committed
193 194 195
      Call tic() every x seconds. x is defined in self.interval
      This method is called by TimerService in the interval given
      in zope.conf. The Default is every 5 seconds.
196
    """
197 198 199 200 201 202 203 204
    global last_tic
    last_tic_lock.acquire(1)
    try:
      if tick.timeTime() - last_tic >= self.interval:
        self.tic()
        last_tic = tick.timeTime()
    finally:
      last_tic_lock.release()
Sebastien Robin's avatar
Sebastien Robin committed
205