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