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

# Source Code for Module Products.ZenStatus.zenstatus

      1  #! /usr/bin/env python
      2  # -*- coding: utf-8 -*-
      3  # ##########################################################################
      4  #
      5  # This program is part of Zenoss Core, an open source monitoring platform.
      6  # Copyright (C) 2010 Zenoss Inc.
      7  #
      8  # This program is free software; you can redistribute it and/or modify it
      9  # under the terms of the GNU General Public License version 2 or (at your
     10  # option) any later version as published by the Free Software Foundation.
     11  #
     12  # For complete information please visit: http://www.zenoss.com/oss/
     13  #
     14  # ##########################################################################
     15  __doc__ = """zenstatus
     16
     17  Check the TCP/IP connectivity of IP services.
     18  UDP is specifically not supported.
     19  """
     20
     21  import logging
     22
     23  from twisted.internet import defer
     24
     25  import Globals
     26  import zope.component
     27  import zope.interface
     28  from Products.ZenStatus.ZenTcpClient import ZenTcpClient
     29  from Products.ZenCollector.daemon import CollectorDaemon
     30  from Products.ZenCollector.interfaces import ICollectorPreferences,\
     31                                               IEventService,\
     32                                               IScheduledTask
     33  from Products.ZenCollector.tasks import SimpleTaskFactory,\
     34                                          SubConfigurationTaskSplitter,\
     35                                          TaskStates, \
     36                                          BaseTask
     37
     38
     39  # We retrieve our configuration data remotely via a Twisted PerspectiveBroker
     40  # connection. To do so, we need to import the class that will be used by the
     41  # configuration service to send the data over, i.e. DeviceProxy.
     42  from Products.ZenUtils.Utils import unused
     43  from Products.ZenCollector.services.config import DeviceProxy
     44  from Products.ZenHub.services.ZenStatusConfig import ServiceProxy
     45  unused(ServiceProxy)
     46  unused(DeviceProxy)
     47
     48  #
     49  # creating a logging context for this module to use
     50  #
     51  log = logging.getLogger("zen.zenstatus")
     52
     53
     54 -class ServiceTaskSplitter(SubConfigurationTaskSplitter):
     55      subconfigName = 'components'
     56 -    def makeConfigKey(self, config, subconfig):
     57          return (config.id, config.configCycleInterval, subconfig.component)
     58
     59
     60  # Create an implementation of the ICollectorPreferences interface so that the
     61  # ZenCollector framework can configure itself from our preferences.
     62 -class ZenStatusPreferences(object):
     63      zope.interface.implements(ICollectorPreferences)
     64
     65 -    def __init__(self):
     66          """
     67          Construct a new ZenStatusPreferences instance and provide default
     68          values for needed attributes.
     69          """
     70          self.collectorName = "zenstatus"
     71          self.defaultRRDCreateCommand = None
     72          self.cycleInterval = 60  # seconds
     73          self.configCycleInterval = 20  # minutes
     74          self.statusCycleInterval = 60
     75          self.options = None
     76
     77          # the configurationService attribute is the fully qualified class-name
     78          # of our configuration service that runs within ZenHub
     79          self.configurationService = 'Products.ZenHub.services.ZenStatusConfig'
     80
     81 -    def buildOptions(self, parser):
     82          """
     83          add any zenstatus specific command line options here
     84          """
     85          pass
     86
     87 -    def postStartup(self):
     88          """
     89          process any zenstatus specific command line options here
     90          """
     91          pass
     92
     93
     94 -class ZenStatusTask(BaseTask):
     95      zope.interface.implements(IScheduledTask)
     96
     97 -    def __init__(self,
     98                   name,
     99                   configId,
    100                   scheduleIntervalSeconds,
    101                   taskConfig):
    102          """
    103          Construct a new task for checking the status
    104
    105          @param deviceId: the Zenoss deviceId to watch
    106          @type deviceId: string
    107          @param taskName: the unique identifier for this task
    108          @type taskName: string
    109          @param scheduleIntervalSeconds: the interval at which this task will be
    110                 collected
    111          @type scheduleIntervalSeconds: int
    112          @param taskConfig: the configuration for this task
    113          """
    114          super(ZenStatusTask, self).__init__(
    115                   name, configId,
    116                   scheduleIntervalSeconds, taskConfig
    117                 )
    118
    119          self.name = name
    120          self.configId = configId
    121          self.interval = scheduleIntervalSeconds
    122          self.state = TaskStates.STATE_IDLE
    123          self.log = log
    124          self.cfg = taskConfig.components[0]
    125          self._devId = self.cfg.device
    126          self._eventService = zope.component.queryUtility(IEventService)
    127          self._preferences = zope.component.queryUtility(ICollectorPreferences,
    128                                                          "zenstatus")
    129
    130 -    def _scan_device(self, ip_address):
    131          log.debug("Scanning device %s (%s) port %s",
    132                    self._devId, ip_address, self.cfg.port)
    133          job = ZenTcpClient(self.cfg, self.cfg.status)
    134          return job.start(ip_address)
    135
    136 -    def doTask(self):
    137          d = self._scan_device(self.cfg.ip)
    138          if self.cfg.ip != self.cfg.deviceManageIp:
    139              d.addCallbacks(self.processTestWithRetry, self.handleExceptions)
    140          else:
    141              d.addCallback(self.processTest)
    142              d.addErrback(self.handleExceptions)
    143          return d
    144
    145 -    def processTestWithRetry(self, result):
    146          """
    147          Test a connection to a device.
    148
    149          @parameter result: device and TCP service to test
    150          @type result: ZenTcpClient object
    151          """
    152          evt = result.getEvent()
    153          if evt:
    154              if evt['severity'] != 0:
    155                  d = self._scan_device(self.cfg.deviceManageIp)
    156                  d.addCallback(self.processTest)
    157                  d.addErrback(self.handleExceptions)
    158                  return d
    159              self._eventService.sendEvent(evt)
    160          return defer.succeed("Connected")
    161
    162 -    def processTest(self, result):
    163          evt = result.getEvent()
    164          if evt:
    165              self._eventService.sendEvent(evt)
    166              if evt['severity'] != 0:
    167                  return defer.succeed("Failed")
    168
    169          return defer.succeed("Connected")
    170
    171 -    def handleExceptions(self, reason):
    172          """
    173          Log internal exceptions that have occurred
    174          from testing TCP services
    175
    176          @param reason: error message
    177          @type reason: Twisted error instance
    178          """
    179          msg = reason.getErrorMessage()
    180          evt = dict(device=self._preferences.options.monitor,
    181                     summary=msg,
    182                     severity=4,  # error
    183                     component='zenstatus',
    184                     traceback=reason.getTraceback())
    185          self._eventService.sendEvent(evt)
    186          return defer.succeed("Failed due to internal error")
    187
    188 -    def cleanup(self):
    189          pass
    190
    191
    192  #
    193  # Collector Daemon Main entry point
    194  #
    195  if __name__ == '__main__':
    196      myPreferences = ZenStatusPreferences()
    197      myTaskFactory = SimpleTaskFactory(ZenStatusTask)
    198      myTaskSplitter = ServiceTaskSplitter(myTaskFactory)
    199      daemon = CollectorDaemon(myPreferences, myTaskSplitter)
    200      daemon.run()
    201