346 |
346 |
|
347 |
347 |
|
348 |
348 |
def HostWorker(logdir, username, password, use_agent, hostname,
|
349 |
|
executable, command, filelist):
|
|
349 |
executable, exec_args, command, filelist):
|
350 |
350 |
"""Per-host worker.
|
351 |
351 |
|
352 |
352 |
This function does not return - it's the main code of the childs,
|
... | ... | |
359 |
359 |
@param use_agent: whether we should instead use an agent
|
360 |
360 |
@param hostname: the hostname to connect to
|
361 |
361 |
@param executable: the executable to upload, if not None
|
|
362 |
@param exec_args: Additional arguments for executable
|
362 |
363 |
@param command: the command to run
|
363 |
364 |
@param filelist: auxiliary files to upload
|
364 |
365 |
|
... | ... | |
375 |
376 |
print " %s: uploading files" % hostname
|
376 |
377 |
upload_dir = UploadFiles(connection, executable,
|
377 |
378 |
filelist, logfile)
|
378 |
|
command = "cd %s && ./%s" % (upload_dir, os.path.basename(executable))
|
|
379 |
command = ("cd %s && ./%s %s" %
|
|
380 |
(upload_dir, os.path.basename(executable), exec_args))
|
379 |
381 |
print " %s: executing remote command" % hostname
|
380 |
382 |
cmd_result = RunRemoteCommand(connection, command, logfile)
|
381 |
383 |
if cmd_result is True:
|
... | ... | |
411 |
413 |
|
412 |
414 |
|
413 |
415 |
def LaunchWorker(child_pids, logdir, username, password, use_agent, hostname,
|
414 |
|
executable, command, filelist):
|
|
416 |
executable, exec_args, command, filelist):
|
415 |
417 |
"""Launch the per-host worker.
|
416 |
418 |
|
417 |
419 |
Arguments are the same as for HostWorker, except for child_pids,
|
... | ... | |
425 |
427 |
child_pids[pid] = hostname
|
426 |
428 |
else:
|
427 |
429 |
HostWorker(logdir, username, password, use_agent, hostname,
|
428 |
|
executable, command, filelist)
|
|
430 |
executable, exec_args, command, filelist)
|
429 |
431 |
|
430 |
432 |
|
431 |
433 |
def ParseOptions():
|
... | ... | |
452 |
454 |
help="comma-separated list of hosts or single hostname",)
|
453 |
455 |
parser.add_option("-a", dest="auxfiles", action="append", default=[],
|
454 |
456 |
help="optional auxiliary file to upload"
|
455 |
|
" (can be given multiple times",
|
|
457 |
" (can be given multiple times)",
|
456 |
458 |
metavar="FILE")
|
457 |
459 |
parser.add_option("-c", dest="command", default=None,
|
458 |
460 |
help="shell command to run on remote host(s)")
|
... | ... | |
466 |
468 |
" using an agent)")
|
467 |
469 |
parser.add_option("-A", dest="use_agent", default=False, action="store_true",
|
468 |
470 |
help="instead of password, use keys from an SSH agent")
|
|
471 |
parser.add_option("--args", dest="exec_args", default=None,
|
|
472 |
help="Arguments to be passed to executable (-x)")
|
469 |
473 |
|
470 |
474 |
opts, args = parser.parse_args()
|
471 |
475 |
|
... | ... | |
473 |
477 |
parser.error("Options -x and -c conflict with each other")
|
474 |
478 |
if not (opts.executable or opts.command):
|
475 |
479 |
parser.error("One of -x and -c must be given")
|
|
480 |
if opts.command and opts.exec_args:
|
|
481 |
parser.error("Can't specify arguments when using custom command")
|
476 |
482 |
if not opts.logdir:
|
477 |
483 |
parser.error("Option -l is required")
|
478 |
484 |
if opts.hostfile and opts.hostlist:
|
... | ... | |
483 |
489 |
parser.error("This program doesn't take any arguments, passed in: %s" %
|
484 |
490 |
", ".join(args))
|
485 |
491 |
|
486 |
|
return (opts.logdir, opts.executable, opts.hostfile, opts.hostlist,
|
|
492 |
return (opts.logdir, opts.executable, opts.exec_args,
|
|
493 |
opts.hostfile, opts.hostlist,
|
487 |
494 |
opts.command, opts.use_agent, opts.auxfiles, opts.username,
|
488 |
495 |
opts.password, opts.batch_size)
|
489 |
496 |
|
490 |
497 |
|
491 |
498 |
def main():
|
492 |
499 |
"""main."""
|
493 |
|
(logdir, executable, hostfile, hostlist,
|
|
500 |
(logdir, executable, exec_args, hostfile, hostlist,
|
494 |
501 |
command, use_agent, auxfiles, username,
|
495 |
502 |
password, batch_size) = ParseOptions()
|
496 |
503 |
|
... | ... | |
535 |
542 |
child_pids = {}
|
536 |
543 |
for hostname in batch:
|
537 |
544 |
LaunchWorker(child_pids, logdir, username, password, use_agent, hostname,
|
538 |
|
executable, command, filelist)
|
|
545 |
executable, exec_args, command, filelist)
|
539 |
546 |
|
540 |
547 |
while child_pids:
|
541 |
548 |
pid, status = os.wait()
|
... | ... | |
547 |
554 |
failures += 1
|
548 |
555 |
if hosts:
|
549 |
556 |
LaunchWorker(child_pids, logdir, username, password, use_agent,
|
550 |
|
hosts.pop(0), executable, command, filelist)
|
|
557 |
hosts.pop(0), executable, exec_args, command, filelist)
|
551 |
558 |
|
552 |
559 |
print
|
553 |
560 |
print "All done, %s successful and %s failed hosts" % (successes, failures)
|