#!/bin/sh
# bosco_add_host: Used to install ssh keys and blahp on remote hosts.

# 
# Arguments:
# add host: add host to cluster
#

# Bosco key location
bosco_key=$HOME/.ssh/bosco_key.rsa

# Bosco password location
PASSPHRASE_LOCATION=$HOME/.bosco/.pass

# Bosco cluster list location
CLUSTERLIST_LOCATION=$HOME/.bosco/.clusterlist

usage()
{
cat << EOM
usage: $0 command

commands:
 -l|--list          List the installed clusters
 -a|--add host      Install and add a cluster
 -r|--remove host   Remove the installed cluster
 -t|--test host     Test the installed cluster
 -h|--help          Show this help message

Where host is user@fqdn.example.com

EOM
}

list()
{
    # Check for the cluster_list file
    if [ -e $CLUSTERLIST_LOCATION ]; then
        cat $CLUSTERLIST_LOCATION
    else
        echo "No clusters configured"
    fi
}


start_ssh () {
    # Copy blahp
    PASSPHRASE=""
    if [ -f $PASSPHRASE_LOCATION ]; then
        PASSPHRASE=`cat $PASSPHRASE_LOCATION`
    fi
    
    # Start the ssh-agent
    eval `ssh-agent -s` > /dev/null
    
    # Create an ssh-agent session to handle the transfers
    # Copied from remote_gahp
    # create a temp file for the expect script
    SSH_ADD_SCRIPT=`mktemp`
    chmod 700 $SSH_ADD_SCRIPT
    
    # Create the expect script
    echo "#!/usr/bin/expect -f
        # get arguments
        set num_args [llength \$argv]
        set private_key_loc [lindex \$argv 0]
    
        # spawn ssh-add process
        spawn ssh-add $bosco_key
    
        set spawn_pid [exp_pid]
    
        # set timeout for expected input
        set timeout 5
    
        expect {
            # no passphrase required
            \"*Identity added*\" {
                exit 0
            }
            # sends passphrase
            \"*passphrase*\" {
                send -- \"$PASSPHRASE\r\"
            }
            # no ssh-agent running
            \"*authentication agent*\" {
                exit -1
            }
            # incorrect private key location
            timeout {
                exit -2
            }
        }
    
        expect {
            # all done
            eof {
                exit 0
            }
            # incorrect passphrase
            \"*passphrase*\" {
                exit -3
            }
            # timeout
            timeout {
                exit -4
            }
        }" > $SSH_ADD_SCRIPT
    
    
    # call the expect script to ssh-add identity
    $SSH_ADD_SCRIPT > /dev/null
    ADD_STATUS=$?
    
    # remove temporary script
    rm $SSH_ADD_SCRIPT
    
    # check if ssh-add failed
    if [ $ADD_STATUS != 0 ] ; then
        # ssh-add script not found
        if [ $ADD_STATUS == 1 ] ; then
            ADD_STATUS=-1
        fi
        eval `ssh-agent -sk`
        exit $ADD_STATUS
    fi
}    


stop_ssh () {
    # Shut down ssh-agent
    eval `ssh-agent -sk` > /dev/null
}

remove_cluster () {
    # $1 = cluster to remove
    remote_host=$1

    # First, check if the cluster is in the cluster list
    grep "$remote_host" $CLUSTERLIST_LOCATION >/dev/null
    if [ $? -eq 0 ]; then

        # Remove bosco from the remote cluster
        start_ssh
        ssh $1 "rm -rf bosco"
        stop_ssh

        # Remove the host from the cluster list
        sed "/\$$remote_host/d" $CLUSTERLIST > $CLUSTERLIST.tmp
        mv $CLUSTERLIST.tmp $CLUSTERLIST

    else
        echo "Unable to find cluster $remote_host in cluster list"
        exit 1
    fi
}


test_cluster () {
    remote_host=$1

    # First, check if the cluster is in the clusterlist
    grep "$remote_host" $CLUSTERLIST_LOCATION
    if [ $? -ne 0 ]; then
        echo "Unable to find $remote_host in list of installed clusters."
        echo "Available clusters:"
        list
        exit 1
    fi

    # Check if passwordless ssh works
    echo -n "Testing ssh to $1..."
    start_ssh
    # Get the pwd from the remote cluster, for use later in the submission file
    default_pwd=`ssh $1 "pwd"`
    ssh_exit=$?
    stop_ssh
    if [ $ssh_exit -ne 0 ]; then
        echo "Failed to run simple ssh on remote cluster."
        echo "Passwordless ssh to $1 is not working."
        exit 1
    else
        echo "Passed!"
    fi
    
    # Test condor submission
    echo -n "Testing bosco submission..."
    submit_dir=`mktemp -d`
    submit_file=$submit_dir/condor.submit
    log_file=$submit_dir/logfile
    cat > $submit_file << End_of_Submit
universe = grid
grid_resource = pbs $remote_host
output = /dev/null
error = /dev/null
transfer_executable=false
executable = /bin/hostname
log = $log_file
skip_filechecks = true
+remote_iwd="$default_pwd"
queue
End_of_Submit

    submit_out=`condor_submit $submit_file 2>&1 `
    if [ $? -ne 0 ]; then
        echo "Failed"
        echo $submit_out
        rm -rf $submit_dir
        exit 1
    else
        echo "Passed!"
    fi

    # Check if there is anything in the user log
    echo -n "Checking for submission to remote pbs cluster (could take ~30 seconds)..."
    counter=5
    submit_found=0
    while [ $counter -gt 0 ]
    do
        grep_out=`grep -A 2 -e "^027.*" $log_file`
        if [ $? -eq 0 ]; then
            submit_found=1
            break
        fi
        sleep 10
        counter=$(( $counter - 1 ))
    done
    
    if [ $submit_found -eq 1 ]; then
        echo "Passed!"
        echo "Execution on the remote cluster could take a while...Exiting"
    else
        echo "Failed"
        echo "Showing last 5 lines of logs:"
        gridmanager_log=`condor_config_val GRIDMANAGER_LOG`
        if [ -r $gridmanager_log ]; then
            tail -5 $gridmanager_log
        else
            echo "Failed to open gridmanager log for reading"
        fi
    fi

    rm -rf $submit_dir

}



# The getopt command line.  Using -a for alternate (allow options with only 1 '-')
TEMP=`getopt -a -o a:lt:r:h --longoptions add:,list,test:,remove:help  -n 'bosco_cluster' -- "$@"`

if [ $? != 0 ]; then usage; echo "Terminating..." >&2; exit 1; fi

eval set -- "$TEMP"

while true; do
    case "$1" in
        -h|--help) usage; exit 1; shift ;;
        -a|--add) remote_host=$2; shift 2; break ;;
        -l|--list) list; exit 0 ;;
        -t|--test) test_cluster $2;  shift 2; exit 0 ;;
        -r|--remove) remove_cluster $2; shift 2; exit 0;;
        
        --) echo "No command found" >&2; usage; exit 1;;
        *) echo "Unknown option"; exit 1;;
    esac
done


################################################################
# The rest of the file covers the 'add' cluster functionality.
################################################################

# If the key doesn't exist, create it
if [ ! -e $bosco_key ]; then
    # Read in password for bosco key
    stty -echo
    read -p "Enter password for bosco ssh key: " PASSPHRASE; echo
    stty echo

    # Output the password to a specially crafted file
    mkdir -p $HOME/.bosco
    echo $PASSPHRASE > $PASSPHRASE_LOCATION
    chmod go-rwx $PASSPHRASE_LOCATION
    
    ssh-keygen -q -t rsa -f $bosco_key -P $PASSPHRASE > /dev/null
    if [ $? -ne 0 ]; then
        echo "Error running keygen" >&2
        exit 1
    fi
fi


# Transfer the public key to the remote host
# ssh-copy-id is available on el5 from openssh-clients
echo "Enter password to copy ssh keys to $remote_host:"
ssh-copy-id -i $bosco_key $remote_host > /dev/null

start_ssh

# First, find the blahp
glite_location=`condor_config_val GLITE_LOCATION`
release_dir=`condor_config_val RELEASE_DIR`

echo "Installing BOSCO on $remote_host..."

# Make the necessary remote directories
ssh $remote_host "mkdir -p bosco/glite/lib"

# Copy over blahp
rsync -aq $glite_location/[^l]* $remote_host:bosco/glite/
if [ -d $release_dir/lib64 ] ; then
    libdir=lib64
else
    libdir=lib
fi
rsync -aq  $release_dir/$libdir/libclassad.so* $remote_host:bosco/glite/lib/
rsync -aq  $release_dir/$libdir/condor $remote_host:bosco/glite/lib/

# Add the cluster to the cluster list
echo $remote_host >> $CLUSTERLIST_LOCATION

echo "Installation complete"

stop_ssh
