#!/bin/bash
#
# This script contains functions used to mount/umount session, runtime,
# and cache directories on a remote cluster front-end using SSHFS. It is
# supposed to be sourced from the a-rex init script.
#

mount_sshfs() {
    # Read from arc.conf
    REMOTE_HOST=`readconfigvar "$ARC_CONFIG" lrms/ssh remote_host`
    REMOTE_USER=`readconfigvar "$ARC_CONFIG" lrms/ssh remote_user`
    SSH_TIMEOUT=`readconfigvar "$ARC_CONFIG" lrms/ssh ssh_timeout`
    IDENTITY_FILE=`readconfigvar "$ARC_CONFIG" lrms/ssh private_key`
    GRIDMAP=`readconfigvar "$ARC_CONFIG" common/mapping gridmap`
    # Get user and group id and save to mapfiles
    user=`head -1 $GRIDMAP | sed 's/^"[^"]*" //'`
    IDMAPDIR=`mktemp -d`
    UIDF=${IDMAPDIR}/${user}.uidfile
    GIDF=${IDMAPDIR}/${user}.gidfile
    printf "%s:%s\n" "${user}" "`ssh -i ${IDENTITY_FILE} ${REMOTE_USER}@${REMOTE_HOST} "id -u"`" > ${UIDF}
    printf "%s:%s\n" "`id -g -n ${user}`" "`ssh -i ${IDENTITY_FILE} ${REMOTE_USER}@${REMOTE_HOST} "id -g"`" > ${GIDF}
    
    for MOUNTDIR in sessiondir runtimedir cachedir; do
        LOCALDIR=`readconfigvar "$ARC_CONFIG" arex ${MOUNTDIR}`
        REMOTEDIR=`readconfigvar "$ARC_CONFIG" lrms/ssh remote_${MOUNTDIR}`
        if [ -z ${REMOTEDIR} ]; then
            log_failure_msg "Directory attribute remote_${MOUNTDIR} not set in ${ARC_CONFIG}"
            RETVAL=1
            break
        fi

        if [ -z ${LOCALDIR} ]; then
            continue
        fi
        # Stat will fail if transport endpoints are not connected
        if [ "$(mount | grep ${LOCALDIR})" ] && [ "$(stat ${LOCALDIR} 2>/dev/null)" ]; then
            log_warning_msg "${LOCALDIR} is already mounted"
            continue
        fi

        # In case of bad disconnect, unmount before remount
        fusermount -u ${LOCALDIR} 2>/dev/null

        if [ "$(ls -A ${LOCALDIR})" ]; then
            log_failur_msg "Directory ${LOCALDIR} not empty."
            RETVAL=1
            break
        fi

        # The reconnect and ServerAliveInterval options should prevent
        # the "transport endpoint not connected" error from occuring
        SSHFS_OPTIONS="allow_other"
        SSHFS_OPTIONS="${SSHFS_OPTIONS},reconnect"
        SSHFS_OPTIONS="${SSHFS_OPTIONS},idmap=file"
        SSHFS_OPTIONS="${SSHFS_OPTIONS},uidfile=${UIDF}"
        SSHFS_OPTIONS="${SSHFS_OPTIONS},gidfile=${GIDF}"
        SSHFS_OPTIONS="${SSHFS_OPTIONS},ConnectTimeout=${SSH_TIMEOUT:-10}"
        SSHFS_OPTIONS="${SSHFS_OPTIONS},ServerAliveInterval=10"
        SSHFS_OPTIONS="${SSHFS_OPTIONS},IdentityFile=${IDENTITY_FILE}"
        sshfs -o ${SSHFS_OPTIONS} ${REMOTE_USER}@${REMOTE_HOST}:${REMOTEDIR} ${LOCALDIR} 2>&1>/dev/null
        RETVAL=$?
        if [ $RETVAL != 0 ]; then
            log_failure_msg "Unable to mount ${REMOTE_HOST}:${REMOTEDIR} (remote_${MOUNTDIR} attribute) directory"
            break
        fi
    done

    rm -rf ${IDMAPDIR}

    return $RETVAL
}

unmount_sshfs() {
    for MOUNTDIR in sessiondir runtimedir cachedir; do
        LOCALDIR=`readconfigvar "$ARC_CONFIG" arex ${MOUNTDIR}`
        REMOTEDIR=`readconfigvar "$ARC_CONFIG" lrms/ssh remote_${MOUNTDIR}`
        if [ ! -z ${REMOTEDIR} ] && [ "$(mount | grep ${LOCALDIR})" ]; then
            timeout 10 fusermount -u ${LOCALDIR} > /dev/null
            if [ $? != 0 ]; then
                log_failure_msg "sshfs ${MOUNTDIR} unmount - timeout"
                RETVAL=1
            fi
        fi
    done
}
