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

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