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 as published by 
  8  # 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 type(command) == type(''): 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 if os.environ.has_key('USER'): 212 defaultUsername = os.environ['USER'] 213 else: 214 defaultUsername = "" 215 defaultPassword = "" 216 defaultLoginTries = 1 217 defaultLoginTimeout = 10 218 defaultCommandTimeout = 10 219 defaultKeyPath = '~/.ssh/id_dsa' 220 defaultConcurrentSessions = 10 221 defaultSearchPath = [] 222 defaultExistanceTest = 'test -f %s' 223 224 if not usage: 225 usage = "%prog [options] hostname[:port] command" 226 227 if not parser: 228 from optparse import OptionParser 229 parser = OptionParser(usage=usage, ) 230 231 parser.add_option('-u', '--user', 232 dest='username', 233 default=defaultUsername, 234 help='Login username') 235 parser.add_option('-P', '--password', 236 dest='password', 237 default=defaultPassword, 238 help='Login password') 239 parser.add_option('-t', '--loginTries', 240 dest='loginTries', 241 default=defaultLoginTries, 242 type = 'int', 243 help='Number of times to attempt to login') 244 parser.add_option('-L', '--loginTimeout', 245 dest='loginTimeout', 246 type = 'float', 247 default = defaultLoginTimeout, 248 help='Timeout period (secs) to find login expect statments') 249 parser.add_option('-T', '--commandTimeout', 250 dest='commandTimeout', 251 type = 'float', 252 default = defaultCommandTimeout, 253 help='Timeout period (secs) after issuing a command') 254 parser.add_option('-K', '--keyPath', 255 dest='keyPath', 256 default = defaultKeyPath, 257 help='Path to use when looking for SSH keys') 258 parser.add_option('-S', '--concurrentSessions', 259 dest='concurrentSessions', 260 default = defaultConcurrentSessions, 261 help='Allowable number of concurrent SSH sessions') 262 parser.add_option('-s', '--searchPath', 263 dest='searchPath', 264 default=defaultSearchPath, 265 help='Path to use when looking for commands') 266 parser.add_option('-e', '--existenceTest', 267 dest='existenceTest', 268 default=defaultExistanceTest, 269 help='How to check if a command is available or not') 270 if not parser.has_option('-v'): 271 parser.add_option('-v', '--logseverity', 272 dest='logseverity', 273 default=logging.INFO, 274 type='int', 275 help='Logging severity threshold') 276 return parser
277 278
279 -def parseOptions(parser, port):
280 """ 281 Command-line option parser 282 283 @param parser: optparse parser 284 @type parser: optparse object 285 @param port: IP port number to listen on 286 @type port: integer 287 @return: parsed options 288 @rtype: object 289 """ 290 options, args = parser.parse_args() 291 if len(args) < 2: 292 parser.print_help() 293 sys.exit(1) 294 if args[0].find(':') > -1: 295 hostname,port = args[0].split(':') 296 else: 297 hostname = args[0] 298 options.hostname = hostname 299 options.port = port 300 options.commands = args[1:] 301 return options
302