Package Products :: Package ZenModel :: Module ZenStatus |
[hide private]
[frames] | no frames]

# Source Code for Module Products.ZenModel.ZenStatus

      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 or (at your
      8  # option) any later version as published by the Free Software Foundation.
      9  #
     10  # For complete information please visit: http://www.zenoss.com/oss/
     11  #
     12  ###########################################################################
     13
     14  from __future__ import division
     15
     16  __doc__="""ZenStatus
     17
     18  Track status information about some monitored object.
     19  if status = -1 the object has not been tested
     20  if status = -2 the object has failed a DNS lookup
     21  if status = 0 the object has passed its test
     22  if status > 0 the object has failed its test status times
     23
     24  This class should track availability as well!!!
     25
     26  $Id: ZenStatus.py,v 1.28 2004/05/11 22:59:23 edahl Exp $"""
     27
     28  import calendar
     29
     30  from Globals import Persistent
     31  from DateTime import DateTime
     32
     33  defaultColor = "#d02090"
     34
     35 -class ZenStatus(Persistent):
     36
     37      conversions = {
     38          -2 : "No DNS",
     39          -1 : "Not Tested",
     40           0 : "Up",
     41      }
     42
     43 -    def __init__(self, status=-1):
     44          self.status = status
     45
     46 -    def getStatus(self):
     47          """get objects current status this is the number of failure
     48          increments that have been called"""
     49          return self.status
     50
     51
     52 -    def getStatusString(self):
     53          """get status as a string will convert as per converstions"""
     54          return (self.conversions[self.status]
     55                      if self.status in self.conversions else self.status)
     56
     57
     58 -    def setStatus(self, status):
     59          self.status = int(status)
     60
     61 -    def incr(self):
     62          """increment the failure status"""
     63          self.status += 1
     64
     65 -    def reset(self):
     66          """reset status when failure is over"""
     67          self.status = 0
     68
     69 -    def color(self):
     70          """get the color to display in the gui"""
     71          retval = defaultColor
     72          if self.status == 0:
     73              retval="#00ff00"
     74          elif self.status == -2:
     75              retval = "#ff9900"
     76          elif self.status > 0:
     77              retval = "#ff0000"
     78          return retval
     79
     80
     81 -class ZenAvailability(ZenStatus):
     82
     83 -    def __init__(self, status=-1):
     84          ZenStatus.__init__(self, status)
     85          self.failstart = 0  # start of current failure as DateTime
     86          self.failincr = 0    # DateTime of last failure increment call
     87          self.todaydown = 0  # total downtime today in seconds
     88          self.yearlydata = {DateTime().year() : YearlyDownTime()}
     89
     90
     91 -    def incr(self):
     92          """increment the failure time of a monitored object
     93          if we are in a new day since last failure move old
     94          day data to yearly data and reset for todays availability
     95          this must be called once a day to work correctly!!!"""
     96          if self.failstart == 0:
     97              self.failstart = self.failincr = DateTime()
     98          if self.status < 0: self.status = 1
     99          delta = long((DateTime() - self.failincr) * 86400)
    100          if not self.failincr.isCurrentDay():
    101              yavail = self._getYearlyData(self.failstart.year())
    102              now = DateTime()
    103              newdaydown = long((now.earliestTime() - now) * 86400)
    104              yesterdaydown = self.todaydown + (delta - newdaydown)
    105              yavail.addDaily(yesterdaydown)
    106              self.todaydown = 0
    107              delta = newdaydown
    108          self.todaydown += delta
    109          self.status += delta
    110          self.failincr = DateTime()
    111
    112
    113 -    def reset(self):
    114          """reset the objects failure status"""
    115          self.status = 0
    116          self.failstart = 0
    117          self.failincr = 0
    118
    119
    120 -    def getStatusString(self):
    121          """current down time in days hours or seconds"""
    122          status = self.getStatus()
    123          if status in self.conversions:
    124              return self.conversions[status]
    125          dt = DateTime() - self.failstart
    126          days = int(dt)
    127          hours = int(dt * 24) % 24
    128          mins = int(dt * 24*60) % 60
    129          secs = round(dt * 86400) % 60
    130          return "%dd:%02dh:%02dm:%02ds" % (days, hours, mins, secs)
    131
    132
    133 -    def getStatus(self):
    134          """get current down time in seconds"""
    135          if self.status < 0: return self.status
    136          if self.failstart == 0: return 0
    137          return int(round((DateTime() - self.failstart) * 86400))
    138
    139
    140 -    def getAvailPercent(self, start, end=None):
    141          """get availability for a date range as a float between 100.0 and 0.0"""
    142          if self.status < 0: return -1
    143          if not end: end = DateTime()
    144          delta = long((end - start) * 86400.0)
    145          dt = self.getDownTime(start,end)
    146          if dt < 0: return dt
    147          return 100.0 - ((self.getDownTime(start, end) / delta)*100)
    148
    149
    150 -    def getAvailPercentString(self, start, end=None):
    151          """get availability for a date range as a string for display"""
    152          avail = self.getAvailPercent(start, end)
    153          if avail < 0: return "Unknown"
    154          return "%.3f%%" % self.getAvailPercent(start, end)
    155
    156
    157 -    def getAvail30(self):
    158          """get the 30 day rolling availability of this object"""
    159          return self.getAvailPercent(DateTime()-30)
    160
    161
    162 -    def getAvail30String(self):
    163          """get the 30 day rolling availability of this object"""
    164          return self.getAvailPercentString(DateTime()-30)
    165
    166
    167 -    def getDownTime(self, start, end=None):
    168          """calculate the down time in seconds using start and end DateTime
    169          if no end is passed the current time is assumed"""
    170          if not end: end = DateTime()
    171          syear = start.year()
    172          eyear = end.year()
    173          dt = -1
    174          if syear == eyear:
    175              dt = self._getDownTime(syear, start, end)
    176          else:
    177              dt = self._getDownTime(syear, start=start)
    178              for y in range(syear+1, eyear):
    179                  dt += self._getDownTime(y)
    180              dt += self._getDownTime(eyear, end=end)
    181          if end.isCurrentDay(): dt += self.todaydown
    182          return dt
    183
    184
    185 -    def _getDownTime(self, year, start=None, end=None):
    186          """check to see if we have year data for year and return it"""
    187          dt = -1
    188          if year in self.yearlydata:
    189              dt = self.yearlydata[year].getDownTime(start, end)
    190          return dt
    191
    192
    193 -    def _getYearlyData(self, year):
    194          """get or create a YearlyDownTime object"""
    195          if not year in self.yearlydata:
    196              self.yearlydata[year] = YearlyDownTime()
    197          return self.yearlydata[year]
    198
    199
    200 -class YearlyDownTime(Persistent):
    201      """this would take less space as a dict with but it would take longer
    202      to query not sure which is better going with faster and bigger :)"""
    203
    204 -    def __init__(self):
    205          days = 365
    206          if calendar.isleap(DateTime().parts()[0]): days += 1
    207          self.daysdown = map(lambda x: 0, range(days))
    208
    209
    210 -    def addDaily(self, dailydown):
    211          """add the daily down time for a day"""
    212          self.daysdown.insert(DateTime().dayOfYear()-1, dailydown)
    213          self._p_changed = 1
    214
    215
    216 -    def getDownTime(self, start=None, end=None):
    217          """get the down time in seconds over a date range, dates are DateTime"""
    218          if end == None:
    219              end = len(self.daysdown)
    220          elif isinstance(end, DateTime):
    221              end = end.dayOfYear()
    222          if start == None:
    223              start=1
    224          elif isinstance(start, DateTime):
    225              start = start.dayOfYear()
    226          start -= 1
    227          return sum(self.daysdown[start:end])
    228