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

Source Code for Module Products.DataCollector.CollectorClient

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