Package Products :: Package DataCollector :: Module CollectorClient |
[hide private]
[frames] | no frames]

# Source Code for Module Products.DataCollector.CollectorClient

      1  ##############################################################################
      2  #
      3  # Copyright (C) Zenoss, Inc. 2007, 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__="""CollectorClient
     12
     13  Base class for client collectors
     14
     15  zCommandLoginTries - number of times to attempt to login
     16  zCommandPathList - list of paths to check for a command
     17  zCommandExistanceCheck - shell command issued to look for an executable
     18                          must echo succ if the executable is found
     19                          default: test -f executable
     20
     21  """
     22
     23  import os, sys
     24  import logging
     25  log = logging.getLogger("zen.CmdClient")
     26
     27  from twisted.internet import protocol
     28
     29  from BaseClient import BaseClient
     30
     31 -class CollectorClient(BaseClient, protocol.ClientFactory):
     32      """
     33      Data collector client class to be subclassed by different types
     34      collector protocols
     35      """
     36
     37      maintainConnection = False
     38      cmdindex = 0
     39
     40 -    def __init__(self, hostname, ip, port, plugins=None, options=None,
     41                      device=None, datacollector=None, alog=None):
     42          """
     43          Gather our required zProperties
     44
     45          @param hostname: name of the remote device
     46          @type hostname: string
     47          @param ip: IP address of the remote device
     48          @type ip: string
     49          @param port: IP port number to listen on
     50          @type port: integer
     51          @param plugins: plugins to run
     52          @type plugins: list
     53          @param options: optparse options
     54          @type options: optparse options object
     55          @param device: DMD device object
     56          @type device: device object
     57          @param datacollector: datacollector
     58          @type datacollector: datacollector object
     59          @param alog: Python logging class object
     60          @type alog: Python logging class object
     61          """
     62          BaseClient.__init__(self, device, datacollector)
     63          from Products.ZenUtils.Utils import unused
     64          unused(alog)
     65          self.hostname = hostname
     66          self.ip = ip
     67          self.port = port
     68          plugins = plugins or []
     69          self.cmdmap = {}
     70          self._commands = []
     71          for plugin in plugins:
     72              self.cmdmap[plugin.command] = plugin
     73              self._commands.append(plugin.command)
     74          self.results = []
     75          self.protocol = None
     76
     77          if options:
     78              defaultUsername = options.username
     79              defaultPassword = options.password
     80              defaultLoginTries = options.loginTries
     81              defaultLoginTimeout = options.loginTimeout
     82              defaultCommandTimeout = options.commandTimeout
     83              defaultKeyPath = options.keyPath
     84              defaultConcurrentSessions = options.concurrentSessions
     85              defaultSearchPath = options.searchPath
     86              defaultExistanceTest = options.existenceTest
     87
     88          if device: # if we are in Zope look for parameters in the acquisition path
     89              self.username = getattr(device,
     90                          'zCommandUsername', defaultUsername)
     91              self.password = getattr(device,
     92                          'zCommandPassword', defaultPassword)
     93              self.loginTries = getattr(device,
     94                          'zCommandLoginTries', defaultLoginTries)
     95              self.loginTimeout = getattr(device,
     96                          'zCommandLoginTimeout', defaultLoginTimeout)
     97              self.commandTimeout = getattr(device,
     98                          'zCommandCommandTimeout', defaultCommandTimeout)
     99              self.keyPath = getattr(device,
    100                          'zKeyPath', defaultKeyPath)
    101              self.concurrentSessions = getattr(device,
    102                          'zSshConcurrentSessions', defaultConcurrentSessions)
    103              self.port = getattr(device, 'zCommandPort', self.port)
    104              self.searchPath = getattr(device,
    105                          'zCommandSearchPath', defaultSearchPath)
    106              self.existenceTest = getattr(device,
    107                          'zCommandExistanceTest', defaultExistanceTest)
    108          else:
    109              self.username = defaultUsername
    110              self.password = defaultPassword
    111              self.loginTries = defaultLoginTries
    112              self.loginTimeout = defaultLoginTimeout
    113              self.commandTimeout = defaultCommandTimeout
    114              self.keyPath = defaultKeyPath
    115              self.concurrentSessions = defaultConcurrentSessions
    116              self.searchPath = defaultSearchPath
    117              self.existenceTest = defaultExistanceTest
    118
    119
    120 -    def addCommand(self, command):
    121          """
    122          Add a command to the list of commands to gather data
    123
    124          @param command: command
    125          @type command: string
    126          """
    127          if isinstance(command, basestring):
    128              self._commands.append(command)
    129          else:
    130              self._commands.extend(command)
    131
    132
    133 -    def addResult(self, command, data, exitCode):
    134          """
    135          Add a result pair to the results store
    136
    137          @param command: command
    138          @type command: string
    139          @param data: results of running the command
    140          @type data: string
    141          @param exitCode: exit code from executing the command
    142          @type exitCode: integer
    143          """
    144          plugin = self.cmdmap.get(command, None)
    145          self.results.append((plugin, data))
    146
    147
    148 -    def getCommands(self):
    149          """
    150          The commands which we will use to collect data
    151
    152          @return: commands
    153          @rtype: list of strings
    154          """
    155          return self._commands
    156
    157
    158 -    def getResults(self):
    159          """
    160          Return all of the results we have collected so far
    161
    162          @return: results
    163          @rtype: list of strings
    164          """
    165          return self.results
    166
    167
    168 -    def commandsFinished(self):
    169          """
    170          Called by protocol to see if all commands have been run
    171          """
    172          return len(self.results) == len(self._commands)
    173
    174
    175 -    def clientFinished(self):
    176          """
    177          Tell the datacollector that we are all done
    178          """
    179          log.info("command client finished collection for %s",self.hostname)
    180          self.cmdindex = 0
    181          if self.datacollector:
    182              self.datacollector.clientFinished(self)
    183
    184 -    def reinitialize(self):
    185          """
    186          Clear out all member variables that are collections to avoid memory
    187          leaks.
    188          """
    189          self.cmdmap = {}
    190          self._commands = []
    191          self.results = []
    192
    193
    194 -def buildOptions(parser=None, usage=None):
    195      """
    196      Build a list of command-line options we will accept
    197
    198      @param parser: optparse parser
    199      @type parser: optparse object
    200      @param usage: description of how to use the program
    201      @type usage: string
    202      @return: optparse parser
    203      @rtype: optparse object
    204      """
    205
    206
    207      #Default option values
    208      defaultUsername = os.environ.get('USER', '')
    209      defaultPassword = ""
    210      defaultLoginTries = 1
    211      defaultLoginTimeout = 10
    212      defaultCommandTimeout = 10
    213      defaultKeyPath = '~/.ssh/id_dsa'
    214      defaultConcurrentSessions = 10
    215      defaultSearchPath = []
    216      defaultExistanceTest = 'test -f %s'
    217
    218      if not usage:
    219          usage = "%prog [options] hostname[:port] command"
    220
    221      if not parser:
    222          from optparse import OptionParser
    223          parser = OptionParser(usage=usage, )
    224
    225      parser.add_option('-u', '--user',
    226                  dest='username',
    227                  default=defaultUsername,
    228                  help='Login username')
    229      parser.add_option('-P', '--password',
    230                  dest='password',
    231                  default=defaultPassword,
    232                  help='Login password')
    233      parser.add_option('-t', '--loginTries',
    234                  dest='loginTries',
    235                  default=defaultLoginTries,
    236                  type = 'int',
    237                  help='Number of times to attempt to login')
    238      parser.add_option('-L', '--loginTimeout',
    239                  dest='loginTimeout',
    240                  type = 'float',
    241                  default = defaultLoginTimeout,
    242                  help='Timeout period (secs) to find login expect statments')
    243      parser.add_option('-T', '--commandTimeout',
    244                  dest='commandTimeout',
    245                  type = 'float',
    246                  default = defaultCommandTimeout,
    247                  help='Timeout period (secs) after issuing a command')
    248      parser.add_option('-K', '--keyPath',
    249                  dest='keyPath',
    250                  default = defaultKeyPath,
    251                  help='Path to use when looking for SSH keys')
    252      parser.add_option('-S', '--concurrentSessions',
    253                  dest='concurrentSessions',
    254                  type='int',
    255                  default = defaultConcurrentSessions,
    256                  help='Allowable number of concurrent SSH sessions')
    257      parser.add_option('-s', '--searchPath',
    258                  dest='searchPath',
    259                  default=defaultSearchPath,
    260                  help='Path to use when looking for commands')
    261      parser.add_option('-e', '--existenceTest',
    262                  dest='existenceTest',
    263                  default=defaultExistanceTest,
    264                  help='How to check if a command is available or not')
    265      if not parser.has_option('-v'):
    266          parser.add_option('-v', '--logseverity',
    267                      dest='logseverity',
    268                      default=logging.INFO,
    269                      type='int',
    270                      help='Logging severity threshold')
    271      return parser
    272
    273
    274 -def parseOptions(parser, port):
    275      """
    276      Command-line option parser
    277
    278      @param parser: optparse parser
    279      @type parser: optparse object
    280      @param port: IP port number to listen on
    281      @type port: integer
    282      @return: parsed options
    283      @rtype: object
    284      """
    285      options, args = parser.parse_args()
    286      if len(args) < 2:
    287          parser.print_help()
    288          sys.exit(1)
    289      if args[0].find(':') > -1:
    290          hostname,port = args[0].rsplit(':', 1)
    291      else:
    292          hostname = args[0]
    293      options.hostname = hostname
    294      options.port = port
    295      options.commands = args[1:]
    296      return options
    297