#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; sh-indentation: 4; tab-width: 8 -*-
script_path="$(dirname ${0})"
script_name="$(basename ${0})"
pbench_bin="$(realpath -e ${script_path}/..)"

# source the base script
. "${pbench_bin}"/base

_op=${script_name#pbench-}
_op=${_op%-results}
_op_pt="${_op}d"
if [[ "${_op}" == "copy" ]]; then
    _op_pt="copied"
fi

function usage() {
    printf -- "usage:\n%s [--help] --user=<user> [--controller=<controller>]" "${script_name}"
    printf -- " [--prefix=<path>] [--xz-single-threaded] [--show-server]\n"
    printf -- "\nThe '--user' option value is required if not provided by the\n"
    printf -- "'PBENCH_USER' environment variable; otherwise, the value provided\n"
    printf -- "on the command line will override any value provided by the\n"
    printf -- "environment.\n"
    printf -- "The '--controller' option may be used to override the value\n"
    printf -- "provided by the 'PBENCH_CONTROLLER' environment variable; if\n"
    printf -- "neither value is available, the result of 'hostname -f' is used.\n"
    printf -- "(If no value is available, the command will exit with an error.)\n"
    printf -- "\nThe '--prefix' option allows the user to specify an optional\n"
    printf -- "directory path hierarchy to be used when displaying the result\n"
    printf -- "tar balls on the pbench server.\n"
    printf -- "\nThe '--show-server' will not ${_op} any results, but resolve and\n"
    printf -- "then display the pbench server destination for results.\n"
    printf -- "\nThe '--xz-single-threaded' will force the use of a single\n"
    printf -- "thread for locally compressing the result tar balls.\n"
}

function missing_arg() {
    printf "\n${script_name}: ${1} is missing its argument\n\n" >&2
    usage >&2
    exit 1
}

# Process options and arguments
opts=$(getopt -q -o c:u:p:xSh --longoptions "controller:,user:,prefix:,xz-single-threaded,show-server,help" -n "getopt.sh" -- "${@}")
if [[ ${?} -ne 0 ]]; then
    printf "\n${script_name}: you specified an invalid option or an unexpected argument\n\n" >&2
    usage >&2
    exit 1
fi

user="${PBENCH_USER}"
controller="${PBENCH_CONTROLLER}"
prefix=""
xz_single_threaded=0
show_server=""
eval set -- "${opts}"
while true; do
    opt="${1}"
    shift
    case "${opt}" in
        -c|--controller)
            if [[ -n "${1}" ]]; then
                controller="${1}"
                shift
            else
                missing_arg "${opt}"
            fi
            ;;
        -u|--user)
            if [[ -n "${1}" ]]; then
                user="${1}"
                shift
            else
                missing_arg "${opt}"
            fi
            ;;
        -p|--prefix)
            if [[ -n "${1}" ]]; then
                prefix="${1}"
                shift
            else
                missing_arg "${opt}"
            fi
            ;;
        -x|--xz-single-threaded)
            xz_single_threaded=1
            ;;
        -S|--show-server)
            show_server="show"
            ;;
        -h|--help)
            usage
            exit 0
            ;;
        --)
            break
            ;;
        *)
            printf "\n${script_name}: you specified an invalid option or an unexpected argument\n\n" >&2
            usage >&2
            exit 1
    esac
done

if [[ -z "${controller}" ]]; then
    controller=${_pbench_full_hostname}
    if [[ -z "${controller}" ]]; then
        error_log "'--controller' is required, because no 'hostname' is configured"
        exit 1
    fi
fi
validate_hostname "${controller}" "controller"

if [[ -z "${user}" ]]; then
    error_log "Missing required 'user' value (provided either by the '--user' option or the 'PBENCH_USER' environment variable)"
    exit 1
fi

# Move into pbench run collection directory
cd ${pbench_run} >/dev/null
if [[ ${?} -ne 0 ]]; then
    error_log "ERROR: pbench local results directory does not exist: ${pbench_run}"
    exit 1
fi

tmp=${pbench_tmp}/${script_name}.${$}
trap "rm -rf ${tmp}" EXIT INT QUIT TERM

# Before we take any further actions, enumerate the results to be moved
mkdir ${tmp}
sts=${?}
if [[ ${sts} -ne 0 ]] ;then
    error_log "Failed: \"mkdir -p ${tmp}\", status ${sts}"
    exit 1
fi
/bin/ls -ort -d */ | awk '{print $8}' | grep -v "^tools-" | grep -v "^${tools_group_prefix}" | grep -v "^tmp/" > ${tmp}/results.lis
if [[ ! -s ${tmp}/results.lis ]]; then
    # Nothing to do
    exit 0
fi

if [[ ! -f "${pbench_bin}/id_rsa" ]]; then
    error_log "ERROR: ${pbench_bin}/id_rsa required for moving results to archive host"
    exit 1
fi

# ask the server where to send the tarballs
results_webserver=$(pbench-config pbench_web_server results)
if [[ -z "${results_webserver}" ]]; then
    error_log "ERROR: No web server host configured from which we can fetch the FQDN of the host to which we ${_op} results"
    debug_log "\"pbench_web_server\" variable \"results\" section not set"
    exit 1
fi

_info="$(yum info installed pbench-agent 2> /dev/null)"
ver=$(printf -- "%s" "${_info}" | grep Version | awk '{ print $3 }')
if [[ -z "${ver}" ]]; then
    ver="unknown"
fi
rel=$(printf -- "%s" "${_info}" | grep Release | awk '{ print $3 }')
if [[ -z "${rel}" ]]; then
    rel="unknown"
fi
# User-Agent HTTP header: <pbench-agent-ver-rel>:<FQDN>:<${USER}>:${controller}:${user}:<name of this script>""
user_agent="pbench-agent-${ver}-${rel}:${_pbench_full_hostname}:${USER}:${controller}:${user}:${script_name}"

results_host_info_url=$(pbench-config host_info_url results)
results_host_info=$(curl -s -A "${user_agent}" -L "${results_host_info_url}")
if [[ -z "${results_host_info}" ]]; then
    error_log "ERROR: unable to determine results host info from ${results_host_info_url}"
    debug_log "the curl -A \"${user_agent}\" -L \"${results_host_info_url}\" command failed for some unknown reason"
    exit 1
fi

#
# The results host info should be in the form:
#
#     <results_user>@<results_host(FQDN)>:<results_path>
#
# if the host is up and running, ready to receive results.
#
# If the target host is not ready, then it will provide a one line message of the following form:
#
#     MESSAGE===<text to be display to the user>
#
sysmsg=${results_host_info%%===*}
if [[ "${sysmsg}" = "MESSAGE" ]]; then
    printf -- "*** Message from sysadmins of ${results_webserver}:\n"
    printf -- "***\n*** ${results_host_info##*===}\n"
    printf -- "***\n*** No local actions taken.\n"
    exit 1
fi
results_repo=${results_host_info%%:*}
results_user=${results_repo%%@*}
if [[ -z "${results_user}" ]]; then
    debug_log "Defaulting to \"pbench\" for the \"results_user\""
    results_user="pbench"
    results_host="${results_repo}"
    # Reconstruct the expected results_repo
    results_repo=${results_user}@${results_host}
fi

results_path_prefix=${results_host_info##*:}
if [[ -z "${results_path_prefix}" ]]; then
    error_log "ERROR: fetch results host info did not contain a path prefix: ${results_host_info}"
    debug_log "expected the results_host_info to have the form: <results_user>@<results_host(FQDN)>:<results_path_prefix>"
    exit 1
fi

if [[ ! -z "${show_server}" ]] ;then
    printf -- "${results_repo}\n"
    exit 0
fi

# ssh probe test
ssh -n -i ${pbench_bin}/id_rsa ${ssh_opts} ${results_repo} exit
sts=${?}
if [[ ${sts} -eq 255 ]]; then
    error_log "ERROR: ssh command, \"ssh -n -i ${pbench_bin}/id_rsa ${ssh_opts} ${results_repo} exit\", failed"
    exit 1
elif [[ ${sts} -ne 0 ]]; then
    error_log "ERROR: 'exit' command unexpectedly failed on host ${results_repo} with '${sts}'"
    debug_log "ssh command: \"ssh -n -i ${pbench_bin}/id_rsa ${ssh_opts} ${results_repo} exit\""
    exit 1
fi

let runs_copied=0
let failures=0

mkdir ${tmp}/${controller}
sts=${?}
if [[ ${sts} -ne 0 ]] ;then
    error_log "Failed: \"mkdir -p ${tmp}/${controller}\", status ${sts}"
    exit 1
fi
# We can now start copying tarballs to the server

# Move into pbench run collection directory
pushd ${pbench_run} >/dev/null

while read -r dir; do
    # Before the loop we have created a temp directory, $tmp/$controller, to
    # contain the tarball and the md5 file (as ${tb}.tar.xz.md5.check); pass
    # that information on to pbench-make-result-tb.
    result_dir=$(basename ${dir})
    if [[ -n "${prefix}" ]]; then
        prefix_arg=" --prefix ${prefix}"
    else
        prefix_arg=""
    fi
    result_tb_name=$(pbench-make-result-tb --result-dir "${result_dir}" --target-dir "${tmp}/${controller}" --user ${user}${prefix_arg} --xz-single-threaded "${xz_single_threaded}")
    if [[ ${?} -ne 0 ]]; then
        # Messaging already handled by pbench-make-result-tb
        continue
    fi
    if [[ -z "${result_tb_name}" ]]; then
        # Messaging already handled by pbench-make-result-tb
        continue
    fi
    pbench-copy-result-tb ${result_tb_name} ${results_repo} ${results_path_prefix}
    sts=${?}
    rm ${result_tb_name} ${result_tb_name}.md5.check
    if [[ ${?} -ne 0 ]]; then
        error_log "UNEXPECTED ERROR: rm failed to remove ${result_tb_name} and its .md5.check file"
        exit 1
    fi
    if [[ ${sts} -ne 0 ]]; then
        let failures=failures+1
        continue
    fi

    if [[ "${_op}" == "move" ]]; then
        rm -r ${result_dir}
        if [[ ${?} -ne 0 ]]; then
            error_log "UNEXPECTED ERROR: rm failed to remove the ${result_dir} directory hierarchy"
            exit 1
        fi
    else
        touch ${result_dir}.copied
        if [[ ${?} -ne 0 ]]; then
            error_log "UNEXPECTED ERROR: touch failed to ${result_dir}.copied"
            exit 1
        fi
    fi
    let runs_copied=runs_copied+1
done < ${tmp}/results.lis

let anything=runs_copied+failures
if [[ $anything -gt 0 ]]; then
    debug_log "successfully ${_op_pt} $runs_copied runs, encountered $failures failures"
fi
exit $failures
