1
2
3
4
5
6
7
8
9
10
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
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:
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
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
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
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
172 """
173 Called by protocol to see if all commands have been run
174 """
175 return len(self.results) == len(self._commands)
176
177
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
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
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
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