#!/usr/bin/env python
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
# 
#   http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

'''
gpssh -- ssh access to multiple hosts at once

Usage: gpssh [--version] [-?v] [-h host] [-f hostfile] [cmd]

          --version : print version information
          -?        : print this help screen
          -v        : verbose mode
          -e        : echo commands as they are executed
          -h host   : the host to connect to (multiple -h is okay)
          -f file   : a file listing all hosts to connect to
          -D        : do not filter multi-homed hosts 
          cmd       : the command to execute. If not present, 
                      go into interactive mode
'''
import os
import sys

progname = os.path.split(sys.argv[0])[-1]
sys.path.append(sys.path[0] + '/lib')

if sys.version_info < (2, 5, 0):
    sys.exit(
'''Error: %s is supported on Python versions 2.5 or greater
Please upgrade python installed on this machine.''' % progname)


import getopt
import atexit
import signal
import pexpect
import time
from gppylib.util import ssh_utils
from gppylib.gpparseopts import OptParser
from gppylib.gpcoverage import GpCoverage


#
# all the command line options
#
class __globals__:
    script_name = os.path.split(__file__)[-1]
    USER = os.environ.get('LOGNAME') or os.environ.get('USER')
    opt = {}
    opt['-v'] = False
    opt['-e'] = False
    opt['-h'] = []
    opt['-f'] = False
    opt['-D'] = False
    argcmd = None
    session = None


GV = __globals__()

################
def usage(exitarg):
    parser = OptParser()
    try:
        parser.print_help()
    except:
        print __doc__
    sys.exit(0)


#############
def print_version():
    print '%s version $Revision$' % GV.script_name
    sys.exit(0)

#############
def parseCommandLine():
    try:
        (options, args) = getopt.getopt(sys.argv[1:], '?evh:f:D:u:', ['version'])
    except Exception, e:
        usage('[ERROR] ' + str(e))

    for (switch, val) in options:
        if (switch == '-?'):              usage(0)
        elif (switch[1] in 'evD'):    GV.opt[switch] = True
        elif (switch[1] in 'f'):      GV.opt[switch] = val
        elif (switch == '-h'):        GV.opt[switch].append(val)
        elif (switch == '--version'): print_version()
        elif (switch[1] in 'u'):      GV.USER = val

    hf = (len(GV.opt['-h']) and 1 or 0) + (GV.opt['-f'] and 1 or 0)
    if hf != 1:
        usage('Error: please specify at least one of -h or -f args, but not both')

    if (len(args) >= 1):
        GV.argcmd = " ".join(args)
           
def sessionCleanup():
    while True:
        try:
            return_code = 0
            if GV.session: 
                if GV.session.verbose: print '\n[Cleanup...]'; 
                return_code = GV.session.close()
            GV.session = None
            return return_code
        except KeyboardInterrupt:
            pass

sigint_time = 0
def sigint_handle(signum, frame):
    global sigint_time
    now = time.time()
    if now - sigint_time >= 3: 
        sigint_time = now
        raise KeyboardInterrupt
    signal.signal(signal.SIGINT, signal.SIG_IGN)
    print '\n[Exiting...]'
    sys.exit(1)

def sighup_handle(signum, frame):
    sys.exit(1)

def interactive():
    try:
        import readline
        #Read in the saved command history, if any
        histfile = os.path.join(os.environ["HOME"], ".gshist")
        # Set the maximum number of commands to 100
        readline.set_history_length(500)
        try:
            readline.read_history_file(histfile)            
        except IOError:
            pass
        
        #MPP-4054 - let's check the permissons before we register
        try:
            f=open(histfile,'a')
            atexit.register(readline.write_history_file, histfile)
            f.close()                        
        except IOError:
            print "\n[WARN] Unable to write to gpssh history file: '%s'. Please check permissions." % histfile
        
            
    except Exception, e:
        print "Note: command history unsupported on this machine ..."

    atexit.register(sessionCleanup)
    signal.signal(signal.SIGINT, sigint_handle)
    signal.signal(signal.SIGHUP, sighup_handle)
    while True:
        try:
            if not GV.session:
                GV.session = ssh_utils.Session()
                GV.session.verbose=GV.opt['-v']
                GV.session.login(GV.opt['-h'], GV.USER)
                GV.session.echoCommand=GV.opt['-e']
            GV.session.cmdloop()
        except pexpect.EOF:
            print '\n[Unexpected EOF from some hosts...]'
            pass
        except ssh_utils.Session.SessionCmdExit:
                print ''
                break
        except ssh_utils.Session.SessionError, e:
                print 'Error: %s' % e
                pass
        except KeyboardInterrupt:
            print '\n[Interrupt...]'
            GV.session.reset()
            pass

#############
coverage = GpCoverage()
coverage.start()

try:
    parseCommandLine()              #Read options from the command line

    #Acquire the list of hosts from command line arguments
    hostlist = ssh_utils.HostList()
    for h in GV.opt['-h']:
        hostlist.add(h)
    if GV.opt['-f']:
        hostlist.parseFile(GV.opt['-f'])

    #Filter out non-unique hostnames unless the -D option is provided
    if not GV.opt['-D']:
        GV.opt['-h'] = hostlist.filterMultiHomedHosts()
    else:
        GV.opt['-h'] = hostlist.get()

    if len(GV.opt['-h']) == 0:
        usage('Error: missing hosts in -h and/or -f arguments')

    #If a single command was passed to us, implement a single command session
    if GV.argcmd:
            try:
                GV.session = ssh_utils.Session()
                GV.session.verbose=GV.opt['-v']
                GV.session.login(GV.opt['-h'], GV.USER)
                GV.session.echoCommand=GV.opt['-e']
                output=GV.session.executeCommand(GV.argcmd)
                GV.session.writeCommandOutput(output)
                if GV.session.verbose: print '[INFO] completed successfully'
                sys.stdout.flush()
            except ssh_utils.Session.SessionError, e:
                print 'Error: %s' % e
                pass

    else: #Otherwise, implement an interactive session
        interactive()
    
    return_code = sessionCleanup()
    sys.exit(return_code)

except KeyboardInterrupt:
    sessionCleanup()
    sys.exit('\nInterrupted...')
finally:
    coverage.stop()
    coverage.generate_report()
