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

# Source Code for Module Products.ZenStatus.ping.CmdPingTask

      1  ##############################################################################
      2  #
      3  # Copyright (C) Zenoss, Inc. 2011, all rights reserved.
      4  #
      5  # This content is made available according to terms specified in
      6  # License.zenoss under the directory where your Zenoss product is installed.
      7  #
      8  ##############################################################################
      9
     10
     11  __doc__ = """CmdPingTask
     12
     13  Determines the availability of a IP addresses using command line ping.
     14
     15  """
     16
     17  import logging
     18  log = logging.getLogger("zen.zenping.cmdping")
     19
     20  from twisted.python.failure import Failure
     21  from twisted.internet import defer, utils
     22  import time
     23
     24  import Globals
     25  from zope import interface
     26  from zope import component
     27
     28  from zenoss.protocols.protobufs.zep_pb2 import SEVERITY_CLEAR
     29
     30  from Products.ZenCollector import interfaces
     31  from Products.ZenCollector.tasks import TaskStates, BaseTask
     32
     33  from Products.ZenUtils.Utils import unused
     34  from Products.ZenCollector.services.config import DeviceProxy
     35  unused(DeviceProxy)
     36
     37  from Products.ZenEvents.ZenEventClasses import Status_Ping
     38  from Products.ZenEvents import Event
     39  from Products import ZenStatus
     40
     41  from PingResult import PingResult
     42  _PING = None
     43  _PING6 = None
     44  _PING_ARG_TEMPLATE = None
     45  _OK = 0
     46
     47 -def _detectPing():
     48      import subprocess
     49      global _PING, _PING6, _PING_ARG_TEMPLATE
     50      try:
     51          _PING = subprocess.check_output(['which', 'ping']).strip()
     52      except subprocess.CalledProcessError:
     53          log.error('no command line ping detected')
     54          import sys
     55          sys.exit(1)
     56      try:
     57          _PING6 = subprocess.check_output(['which', 'ping6']).strip()
     58      except subprocess.CalledProcessError:
     59         log.info('ping6 not found in path')
     60
     61      _PING_ARG_TEMPLATE = '%(ping)s -n -c 1 -t %(ttl)d -w %(timeout)f %(ip)s'
     62      import platform
     63      system = platform.system()
     64      if system in ('Mac OS X', 'Darwin'):
     65         log.info('Mac OS X detected; adjusting ping args.')
     66         _PING_ARG_TEMPLATE = '%(ping)s -n -c 1 -m %(ttl)d -t %(timeout)f %(ip)s'
     67      elif system != 'Linux':
     68         log.info('CmdPing has not been tested on %r; assuming that Linux ping args work.')
     69
     70  _detectPing()
     71
     72 -def _getPingCmd(version=6, **kwargs):
     73      args = kwargs.copy()
     74      if version == 6:
     75          args['ping'] = _PING6
     76      else:
     77          args['ping'] = _PING
     78
     79      cmd_str = _PING_ARG_TEMPLATE % args
     80      cmd_list = cmd_str.split(' ')
     81      return (cmd_list[0], cmd_list[1:])
     82
     83
     84 -class CmdPingCollectionPreferences(ZenStatus.PingCollectionPreferences):
     85      """
     86      This required to be a ping backend; use default implementation.
     87      """
     88      pass
     89
     90 -class CmdPingTaskFactory(object):
     91      """
     92      A Factory to create command line PingTasks.
     93      """
     94      interface.implements(ZenStatus.interfaces.IPingTaskFactory)
     95
     96 -    def __init__(self):
     97          self.reset()
     98
     99 -    def build(self):
    100          task = CmdPingTask(
    101              self.name,
    102              self.configId,
    103              self.interval,
    104              self.config,
    105          )
    106          return task
    107
    108 -    def reset(self):
    109          self.name = None
    110          self.configId = None
    111          self.interval = None
    112          self.config = None
    113
    114 -class CmdPingTask(ZenStatus.PingTask):
    115      interface.implements(ZenStatus.interfaces.IPingTask)
    116
    117 -    def doTask(self):
    118          """
    119          Contact to one device and return a deferred which gathers data from
    120          the device.
    121
    122          @return: A task to ping the device and any of its interfaces.
    123          @rtype: Twisted deferred object
    124          """
    125          self.resetPingResult()
    126          return self._pingIp()
    127
    128      @defer.inlineCallbacks
    129 -    def _pingIp(self):
    130
    131          maxTries = self.config.tries
    132          attempts = 0
    133          exitCode = -1
    134          timestamp = None
    135          while attempts < maxTries:
    136              attempts += 1
    137              cmd, args = _getPingCmd(ip=self.config.ip, version=self.config.ipVersion, ttl=64, timeout=1.5)
    138              log.debug("%s %s", cmd, " ".join(args))
    139              timestamp = time.time()
    140              out, err, exitCode = yield utils.getProcessOutputAndValue(cmd, args)
    141              pingResult = PingResult(self.config.ip, exitCode, out, timestamp)
    142              self.logPingResult(pingResult)
    143              if not self.config.points and exitCode == 0:
    144                  # if there are no datapoints to store
    145                  # and there is at least 1 ping up, then go on
    146                  break
    147
    148          if self.isUp:
    149              log.debug("%s is up!", self.config.ip)
    150              self.sendPingUp()
    151          else:
    152              log.debug("%s is down", self.config.ip)
    153              self.sendPingDown()
    154          self.storeResults()
    155