diff options
Diffstat (limited to 'third_party/Python/module/pexpect-2.4/examples/hive.py')
| -rw-r--r-- | third_party/Python/module/pexpect-2.4/examples/hive.py | 472 |
1 files changed, 0 insertions, 472 deletions
diff --git a/third_party/Python/module/pexpect-2.4/examples/hive.py b/third_party/Python/module/pexpect-2.4/examples/hive.py deleted file mode 100644 index d2b13d4f081a..000000000000 --- a/third_party/Python/module/pexpect-2.4/examples/hive.py +++ /dev/null @@ -1,472 +0,0 @@ -#!/usr/bin/env python - -"""hive -- Hive Shell - -This lets you ssh to a group of servers and control them as if they were one. -Each command you enter is sent to each host in parallel. The response of each -host is collected and printed. In normal synchronous mode Hive will wait for -each host to return the shell command line prompt. The shell prompt is used to -sync output. - -Example: - - $ hive.py --sameuser --samepass host1.example.com host2.example.net - username: myusername - password: - connecting to host1.example.com - OK - connecting to host2.example.net - OK - targetting hosts: 192.168.1.104 192.168.1.107 - CMD (? for help) > uptime - ======================================================================= - host1.example.com - ----------------------------------------------------------------------- - uptime - 23:49:55 up 74 days, 5:14, 2 users, load average: 0.15, 0.05, 0.01 - ======================================================================= - host2.example.net - ----------------------------------------------------------------------- - uptime - 23:53:02 up 1 day, 13:36, 2 users, load average: 0.50, 0.40, 0.46 - ======================================================================= - -Other Usage Examples: - -1. You will be asked for your username and password for each host. - - hive.py host1 host2 host3 ... hostN - -2. You will be asked once for your username and password. - This will be used for each host. - - hive.py --sameuser --samepass host1 host2 host3 ... hostN - -3. Give a username and password on the command-line: - - hive.py user1:pass2@host1 user2:pass2@host2 ... userN:passN@hostN - -You can use an extended host notation to specify username, password, and host -instead of entering auth information interactively. Where you would enter a -host name use this format: - - username:password@host - -This assumes that ':' is not part of the password. If your password contains a -':' then you can use '\\:' to indicate a ':' and '\\\\' to indicate a single -'\\'. Remember that this information will appear in the process listing. Anyone -on your machine can see this auth information. This is not secure. - -This is a crude script that begs to be multithreaded. But it serves its -purpose. - -Noah Spurrier - -$Id: hive.py 509 2008-01-05 21:27:47Z noah $ -""" - -# TODO add feature to support username:password@host combination -# TODO add feature to log each host output in separate file - -import sys -import os -import re -import optparse -import traceback -import types -import time -import getpass -import pexpect -import pxssh -import readline -import atexit - -#histfile = os.path.join(os.environ["HOME"], ".hive_history") -# try: -# readline.read_history_file(histfile) -# except IOError: -# pass -#atexit.register(readline.write_history_file, histfile) - -CMD_HELP = """Hive commands are preceded by a colon : (just think of vi). - -:target name1 name2 name3 ... - - set list of hosts to target commands - -:target all - - reset list of hosts to target all hosts in the hive. - -:to name command - - send a command line to the named host. This is similar to :target, but - sends only one command and does not change the list of targets for future - commands. - -:sync - - set mode to wait for shell prompts after commands are run. This is the - default. When Hive first logs into a host it sets a special shell prompt - pattern that it can later look for to synchronize output of the hosts. If - you 'su' to another user then it can upset the synchronization. If you need - to run something like 'su' then use the following pattern: - - CMD (? for help) > :async - CMD (? for help) > sudo su - root - CMD (? for help) > :prompt - CMD (? for help) > :sync - -:async - - set mode to not expect command line prompts (see :sync). Afterwards - commands are send to target hosts, but their responses are not read back - until :sync is run. This is useful to run before commands that will not - return with the special shell prompt pattern that Hive uses to synchronize. - -:refresh - - refresh the display. This shows the last few lines of output from all hosts. - This is similar to resync, but does not expect the promt. This is useful - for seeing what hosts are doing during long running commands. - -:resync - - This is similar to :sync, but it does not change the mode. It looks for the - prompt and thus consumes all input from all targetted hosts. - -:prompt - - force each host to reset command line prompt to the special pattern used to - synchronize all the hosts. This is useful if you 'su' to a different user - where Hive would not know the prompt to match. - -:send my text - - This will send the 'my text' wihtout a line feed to the targetted hosts. - This output of the hosts is not automatically synchronized. - -:control X - - This will send the given control character to the targetted hosts. - For example, ":control c" will send ASCII 3. - -:exit - - This will exit the hive shell. - -""" - - -def login(args, cli_username=None, cli_password=None): - - # I have to keep a separate list of host names because Python dicts are not ordered. - # I want to keep the same order as in the args list. - host_names = [] - hive_connect_info = {} - hive = {} - # build up the list of connection information (hostname, username, - # password, port) - for host_connect_string in args: - hcd = parse_host_connect_string(host_connect_string) - hostname = hcd['hostname'] - port = hcd['port'] - if port == '': - port = None - if len(hcd['username']) > 0: - username = hcd['username'] - elif cli_username is not None: - username = cli_username - else: - username = raw_input('%s username: ' % hostname) - if len(hcd['password']) > 0: - password = hcd['password'] - elif cli_password is not None: - password = cli_password - else: - password = getpass.getpass('%s password: ' % hostname) - host_names.append(hostname) - hive_connect_info[hostname] = (hostname, username, password, port) - # build up the list of hive connections using the connection information. - for hostname in host_names: - print 'connecting to', hostname - try: - fout = file("log_" + hostname, "w") - hive[hostname] = pxssh.pxssh() - hive[hostname].login(*hive_connect_info[hostname]) - print hive[hostname].before - hive[hostname].logfile = fout - print '- OK' - except Exception as e: - print '- ERROR', - print str(e) - print 'Skipping', hostname - hive[hostname] = None - return host_names, hive - - -def main(): - - global options, args, CMD_HELP - - if options.sameuser: - cli_username = raw_input('username: ') - else: - cli_username = None - - if options.samepass: - cli_password = getpass.getpass('password: ') - else: - cli_password = None - - host_names, hive = login(args, cli_username, cli_password) - - synchronous_mode = True - target_hostnames = host_names[:] - print 'targetting hosts:', ' '.join(target_hostnames) - while True: - cmd = raw_input('CMD (? for help) > ') - cmd = cmd.strip() - if cmd == '?' or cmd == ':help' or cmd == ':h': - print CMD_HELP - continue - elif cmd == ':refresh': - refresh(hive, target_hostnames, timeout=0.5) - for hostname in target_hostnames: - if hive[hostname] is None: - print '/=============================================================================' - print '| ' + hostname + ' is DEAD' - print '\\-----------------------------------------------------------------------------' - else: - print '/=============================================================================' - print '| ' + hostname - print '\\-----------------------------------------------------------------------------' - print hive[hostname].before - print '==============================================================================' - continue - elif cmd == ':resync': - resync(hive, target_hostnames, timeout=0.5) - for hostname in target_hostnames: - if hive[hostname] is None: - print '/=============================================================================' - print '| ' + hostname + ' is DEAD' - print '\\-----------------------------------------------------------------------------' - else: - print '/=============================================================================' - print '| ' + hostname - print '\\-----------------------------------------------------------------------------' - print hive[hostname].before - print '==============================================================================' - continue - elif cmd == ':sync': - synchronous_mode = True - resync(hive, target_hostnames, timeout=0.5) - continue - elif cmd == ':async': - synchronous_mode = False - continue - elif cmd == ':prompt': - for hostname in target_hostnames: - try: - if hive[hostname] is not None: - hive[hostname].set_unique_prompt() - except Exception as e: - print "Had trouble communicating with %s, so removing it from the target list." % hostname - print str(e) - hive[hostname] = None - continue - elif cmd[:5] == ':send': - cmd, txt = cmd.split(None, 1) - for hostname in target_hostnames: - try: - if hive[hostname] is not None: - hive[hostname].send(txt) - except Exception as e: - print "Had trouble communicating with %s, so removing it from the target list." % hostname - print str(e) - hive[hostname] = None - continue - elif cmd[:3] == ':to': - cmd, hostname, txt = cmd.split(None, 2) - if hive[hostname] is None: - print '/=============================================================================' - print '| ' + hostname + ' is DEAD' - print '\\-----------------------------------------------------------------------------' - continue - try: - hive[hostname].sendline(txt) - hive[hostname].prompt(timeout=2) - print '/=============================================================================' - print '| ' + hostname - print '\\-----------------------------------------------------------------------------' - print hive[hostname].before - except Exception as e: - print "Had trouble communicating with %s, so removing it from the target list." % hostname - print str(e) - hive[hostname] = None - continue - elif cmd[:7] == ':expect': - cmd, pattern = cmd.split(None, 1) - print 'looking for', pattern - try: - for hostname in target_hostnames: - if hive[hostname] is not None: - hive[hostname].expect(pattern) - print hive[hostname].before - except Exception as e: - print "Had trouble communicating with %s, so removing it from the target list." % hostname - print str(e) - hive[hostname] = None - continue - elif cmd[:7] == ':target': - target_hostnames = cmd.split()[1:] - if len(target_hostnames) == 0 or target_hostnames[0] == all: - target_hostnames = host_names[:] - print 'targetting hosts:', ' '.join(target_hostnames) - continue - elif cmd == ':exit' or cmd == ':q' or cmd == ':quit': - break - elif cmd[:8] == ':control' or cmd[:5] == ':ctrl': - cmd, c = cmd.split(None, 1) - if ord(c) - 96 < 0 or ord(c) - 96 > 255: - print '/=============================================================================' - print '| Invalid character. Must be [a-zA-Z], @, [, ], \\, ^, _, or ?' - print '\\-----------------------------------------------------------------------------' - continue - for hostname in target_hostnames: - try: - if hive[hostname] is not None: - hive[hostname].sendcontrol(c) - except Exception as e: - print "Had trouble communicating with %s, so removing it from the target list." % hostname - print str(e) - hive[hostname] = None - continue - elif cmd == ':esc': - for hostname in target_hostnames: - if hive[hostname] is not None: - hive[hostname].send(chr(27)) - continue - # - # Run the command on all targets in parallel - # - for hostname in target_hostnames: - try: - if hive[hostname] is not None: - hive[hostname].sendline(cmd) - except Exception as e: - print "Had trouble communicating with %s, so removing it from the target list." % hostname - print str(e) - hive[hostname] = None - - # - # print the response for each targeted host. - # - if synchronous_mode: - for hostname in target_hostnames: - try: - if hive[hostname] is None: - print '/=============================================================================' - print '| ' + hostname + ' is DEAD' - print '\\-----------------------------------------------------------------------------' - else: - hive[hostname].prompt(timeout=2) - print '/=============================================================================' - print '| ' + hostname - print '\\-----------------------------------------------------------------------------' - print hive[hostname].before - except Exception as e: - print "Had trouble communicating with %s, so removing it from the target list." % hostname - print str(e) - hive[hostname] = None - print '==============================================================================' - - -def refresh(hive, hive_names, timeout=0.5): - """This waits for the TIMEOUT on each host. - """ - - # TODO This is ideal for threading. - for hostname in hive_names: - hive[hostname].expect([pexpect.TIMEOUT, pexpect.EOF], timeout=timeout) - - -def resync(hive, hive_names, timeout=2, max_attempts=5): - """This waits for the shell prompt for each host in an effort to try to get - them all to the same state. The timeout is set low so that hosts that are - already at the prompt will not slow things down too much. If a prompt match - is made for a hosts then keep asking until it stops matching. This is a - best effort to consume all input if it printed more than one prompt. It's - kind of kludgy. Note that this will always introduce a delay equal to the - timeout for each machine. So for 10 machines with a 2 second delay you will - get AT LEAST a 20 second delay if not more. """ - - # TODO This is ideal for threading. - for hostname in hive_names: - for attempts in xrange(0, max_attempts): - if not hive[hostname].prompt(timeout=timeout): - break - - -def parse_host_connect_string(hcs): - """This parses a host connection string in the form - username:password@hostname:port. All fields are options expcet hostname. A - dictionary is returned with all four keys. Keys that were not included are - set to empty strings ''. Note that if your password has the '@' character - then you must backslash escape it. """ - - if '@' in hcs: - p = re.compile( - r'(?P<username>[^@:]*)(:?)(?P<password>.*)(?!\\)@(?P<hostname>[^:]*):?(?P<port>[0-9]*)') - else: - p = re.compile( - r'(?P<username>)(?P<password>)(?P<hostname>[^:]*):?(?P<port>[0-9]*)') - m = p.search(hcs) - d = m.groupdict() - d['password'] = d['password'].replace('\\@', '@') - return d - -if __name__ == '__main__': - try: - start_time = time.time() - parser = optparse.OptionParser( - formatter=optparse.TitledHelpFormatter(), - usage=globals()['__doc__'], - version='$Id: hive.py 509 2008-01-05 21:27:47Z noah $', - conflict_handler="resolve") - parser.add_option( - '-v', - '--verbose', - action='store_true', - default=False, - help='verbose output') - parser.add_option( - '--samepass', - action='store_true', - default=False, - help='Use same password for each login.') - parser.add_option( - '--sameuser', - action='store_true', - default=False, - help='Use same username for each login.') - (options, args) = parser.parse_args() - if len(args) < 1: - parser.error('missing argument') - if options.verbose: - print time.asctime() - main() - if options.verbose: - print time.asctime() - if options.verbose: - print 'TOTAL TIME IN MINUTES:', - if options.verbose: - print (time.time() - start_time) / 60.0 - sys.exit(0) - except KeyboardInterrupt as e: # Ctrl-C - raise e - except SystemExit as e: # sys.exit() - raise e - except Exception as e: - print 'ERROR, UNEXPECTED EXCEPTION' - print str(e) - traceback.print_exc() - os._exit(1) |
