Replaced slow pexpect with subprocess.popen which is fast. Implemented Results()...
[progcomp10.git] / src / link / pexpect / examples / hive.py
diff --git a/src/link/pexpect/examples/hive.py b/src/link/pexpect/examples/hive.py
deleted file mode 100755 (executable)
index fcb75bc..0000000
+++ /dev/null
@@ -1,437 +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, os, re, optparse, traceback, types, time, getpass
-import pexpect, pxssh
-import readline, 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, 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, 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, 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, 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, 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, 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, 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, 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, e: # Ctrl-C
-        raise e
-    except SystemExit, e: # sys.exit()
-        raise e
-    except Exception, e:
-        print 'ERROR, UNEXPECTED EXCEPTION'
-        print str(e)
-        traceback.print_exc()
-        os._exit(1)

UCC git Repository :: git.ucc.asn.au