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

# Source Code for Module Products.ZenEvents.UpdateCheck

      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  __doc__='''UpdateCheck
     15
     16  '''
     17
     18  import Globals
     19  import transaction
     20  from Products.ZenUtils.Version import Version
     21  from Products.ZenEvents import Event
     22  from Products.ZenEvents.ZenEventClasses import Status_Update
     23  from Products.Zuul import getFacade
     24  from zenoss.protocols.services.zep import ZepConnectionError
     25  import urllib
     26  import string
     27  import time
     28  import logging
     29
     30  logger = logging.getLogger('zen.UpdateCheck')
     31
     32  URL = 'http://update.zenoss.org/cgi-bin/version'
     33
     34  DAY_SECONDS = 60*60*24
     35  HOUR_SECONDS = 60*60
     36
     37 -def parseVersion(s):
     38      if s is None: return s
     39      v = Version.parse('Zenoss ' + s)
     40      v.revision = None
     41      return v
     42
     43 -class UpdateCheck:
     44
     45 -    def getUpdate(self, dmd, manual, product=None):
     46          """
     47          Send a GET request to dev.zenoss.org giving some parameters about this
     48          Zenoss installation and getting back the version number for the
     49          most recent product release.  The product can be passed in the product
     50          parameter, but if product is None then the code will attempt to
     51          figure out which product is currently running and use that.
     52          """
     53          if not product:
     54              product = dmd.getProductName()
     55          available = None
     56          args = {}
     57          args['pr'] = product
     58          args['sk'] = dmd.uuid or "NOT ACTIVATED"
     59          args['ac'] = (manual and '0') or '1'
     60          args['zv'] = dmd.About.getZenossVersion().long()
     61          args['pv'] = dmd.About.getPythonVersion().long()
     62          args['mv'] = dmd.About.getMySQLVersion().long()
     63          args['os'] = dmd.About.getOSVersion().long()
     64          args['osv'] = dmd.About.getOSVersion().full()
     65          #args['rv'] = Products.ZenUtils.Version.getZenossRevision()
     66          args['rv'] = 'bad bad bad'
     67          args['up'] = time.time() - dmd.getPhysicalRoot().Control_Panel.process_start
     68
     69          # If they have not opted-out and this is not a manual check then
     70          # gather usage numbers and include in request
     71          if not manual and dmd.reportMetricsOptIn:
     72              args['nd'] = dmd.Devices.countDevices()
     73              args['nu'] = len(dmd.ZenUsers.objectIds())
     74              args['nm'] = dmd.Events.countInstances()
     75
     76              numEvents = 0
     77              try:
     78                  zep = getFacade('zep')
     79                  numEvents = zep.countEventsSince(time.time() - 24 * 60 * 60)
     80              except ZepConnectionError:
     81                  logger.warning("ZEP not running - failed to retrieve event count")
     82
     83              args['ne'] = numEvents
     84
     85              numProducts = 0
     86              manufacturers = dmd.Manufacturers.objectValues(spec='Manufacturer')
     87              for m in manufacturers:
     88                  numProducts += m.products.countObjects()
     89              args['np'] = numProducts
     90              args['nr'] = dmd.Reports.countReports()
     91              args['nt'] = dmd.Devices.rrdTemplates.countObjects()
     92              args['ns'] = dmd.Systems.countChildren()
     93              args['ng'] = dmd.Groups.countChildren()
     94              args['nl'] = dmd.Locations.countChildren()
     95
     96          query = urllib.urlencode(args.items())
     97          for line in urllib.urlopen(URL + '?' + query):
     98              # skip blank lines and http gunk
     99              if line.strip() and line[0] not in '<' + string.whitespace:
    100                  try:
    101                      available = parseVersion(line.strip())
    102                      break
    103                  except ValueError:
    104                      pass
    105          return available
    106
    107 -    def check(self, dmd, zem, manual=False):
    108          "call home with version information"
    109          if not manual:
    110              if time.time() - dmd.lastVersionCheck < DAY_SECONDS \
    111                or time.time() - dmd.lastVersionCheckAttempt < 2 * HOUR_SECONDS:
    112                  return
    113              if not dmd.versionCheckOptIn:
    114                  return
    115          now = long(time.time())
    116          dmd.lastVersionCheckAttempt = now
    117          if not manual:
    118              transaction.commit()
    119          try:
    120              available = self.getUpdate(dmd, manual)
    121          except IOError:
    122              available = None
    123          if not isinstance(available, Version):
    124              # We did not successfully get a version, don't continue
    125              return
    126          dmd.availableVersion = available.short()
    127          dmd.lastVersionCheck = now
    128          availableVersion = parseVersion(dmd.availableVersion)
    129          if (availableVersion is None
    130              or dmd.About.getZenossVersion() < availableVersion):
    131              if availableVersion != available:
    132                  import socket
    133                  summary = ('A new version of Zenoss (%s) has been released' %
    134                             available.short())
    135                  zem.sendEvent(Event.Event(device=socket.getfqdn(),
    136                                                eventClass=Status_Update,
    137                                                severity=Event.Info,
    138                                                summary=summary))
    139
    140          return True
    141
    142  if __name__ == "__main__":
    143      from Products.ZenUtils import ZCmdBase
    144 -    class zendmd(ZCmdBase.ZCmdBase):
    145          pass
    146      zendmd = zendmd()
    147      uc = UpdateCheck()
    148      uc.getUpdate = lambda *unused: parseVersion('0.24.0')
    149      uc.check(zendmd.dmd, zendmd.dmd.ZenEventManager, manual=True)
    150      transaction.commit()
    151