#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: t; sh-basic-offset: 4; sh-indentation: 4; tab-width: 8 -*-

# base: contains the base functions and environment variables needed to use
#       the pbench-agent.

# pipeline status is set to the status of the last command that *failed*
# in the pipeline (or 0 if all succeed): this way "ssh foo | sed '...' "
# will catch any ssh failure
set -o pipefail

if command -v python3 > /dev/null 2>&1 ;then
    # All python programs/scripts have headers using "python3" by default.
    :
elif command -v scl_source > /dev/null 2>&1 ;then
    # If we don't have python3, but we do have SCL, we only support
    # Python 3.6.
    source scl_source enable rh-python36
else
    printf -- "${script_name}: python3 required, either directly or through SCL\n" >&2
    exit 1
fi

# very first thing to do is figure out which pbench we are
if [[ -z "$pbench_run" ]]; then
    pbench_run=$(getconf.py pbench_run pbench-agent)
    if [[ -z "$pbench_run" ]]; then
	pbench_run=/var/lib/pbench-agent
    fi
    export pbench_run
else
    if [[ ! -d $pbench_run ]]; then
        echo "[ERROR] the provided pbench run directory, ${pbench_run}, does not exist" >&2
        exit 1
    fi
fi

# the pbench temporary directory is always relative to the $pbench_run
# directory
pbench_tmp="$pbench_run/tmp"
mkdir -p $pbench_tmp
if [[ ! -d $pbench_tmp ]]; then
    echo "[ERROR] unable to create TMP dir, ${pbench_tmp}" >&2
    exit 1
fi
export pbench_tmp

# log file - N.B. not a directory
if [[ -z "$pbench_log" ]]; then
    pbench_log=$(getconf.py pbench_log pbench-agent)
    if [[ -z "$pbench_log" ]]; then
	pbench_log=$pbench_run/pbench.log
    fi
    export pbench_log
fi

if [[ -z "$pbench_install_dir" ]]; then
    pbench_install_dir=$(getconf.py install-dir pbench-agent)
    if [[ -z "$pbench_install_dir" ]]; then
	pbench_install_dir=/opt/pbench-agent
    fi
    if [[ ! -d $pbench_install_dir ]]; then
        echo "[ERROR] pbench installation directory, ${pbench_install_dir}, does not exist" >&2
        exit 1
    fi
    export pbench_install_dir
fi
pbench_bspp_dir=$pbench_install_dir/bench-scripts/postprocess
pbench_lib_dir=$pbench_install_dir/lib
export pbench_bspp_dir pbench_lib_dir

TS_FORMAT="%FT%H:%M:%S"

if [[ -z "${_PBENCH_UNIT_TESTS}" ]]; then
    function timestamp {
	# use ns in the timestamp
	echo "$(date --utc +"${TS_FORMAT}.%N")"
    }
else
    function timestamp {
	echo "1900-01-01T00:00:00.000000"
    }
fi

function log {
    echo "[info][$(timestamp)] $*" >> $pbench_log
}

function warn_log {
    local log_date=$(timestamp)
    echo "[warn][$log_date] $*" >&2
    echo "[warn][$log_date] $*" >> $pbench_log
}

function error_log {
    local log_date=$(timestamp)
    echo "[error][$log_date] $*" >&2
    echo "[error][$log_date] $*" >> $pbench_log
}

export _pbench_debug_mode=0

function debug_log {
    local log_date=$(timestamp)
    if [[ "${_pbench_debug_mode}" != "0" ]]; then
	echo "[debug][${log_date}] $*"
    fi
    echo "[debug][${log_date}] $*" >> ${pbench_log}
}


# Some standard global vars - try the config file first and fall back on hardwired defaults
# which are valid today.
if [[ -z "${_PBENCH_UNIT_TESTS}" ]]; then
    # date may be set "accidentally" so add a var with an unlikely name
    # to check whether we need to set it.
    if [[ -z "$date" || -z "$_PBENCH_DATE_SET" ]]; then
	# don't use ns in the date
	export date=$(date --utc +"${TS_FORMAT}")
	export _PBENCH_DATE_SET=1
    fi
    # don't use colons and dashes in the date suffix
    export date_suffix=$(date --date ${date} --utc +"%Y.%m.%dT%H.%M.%S")
    if [[ -z "${hostname}" ]]; then
        export hostname=$(hostname -s)
    fi
    if [[ -z "${full_hostname}" ]]; then
        export full_hostname=$(hostname)
    fi
else
    export date="1900-01-01T00:00:00"
    export date_suffix="1900.01.01T00.00.00"
    if [[ -z "${hostname}" ]]; then
        export hostname="testhost"
    fi
    if [[ -z "${full_hostname}" ]]; then
        export full_hostname="testhost.example.com"
    fi
fi

if [[ -z "$ssh_opts" ]]; then
    ssh_opts=$(getconf.py ssh_opts results)
    if [[ -z "$ssh_opts" ]]; then
        ssh_opts='-o StrictHostKeyChecking=no'
    fi
    export ssh_opts
fi

if [[ -z "$scp_opts" ]]; then
    scp_opts=$(getconf.py scp_opts results)
    if [[ -z "$scp_opts" ]]; then
        scp_opts='-o StrictHostKeyChecking=no'
    fi
    export scp_opts
fi

function is_redhat() {
    grep -q 'Red Hat' /etc/redhat-release
    return $?
}

function is_fedora() {
    grep -q 'Fedora' /etc/redhat-release
    return $?
}

function get_redhat_version() {
    cat /etc/redhat-release | awk '{ print $7 }'
}

if [[ -z "${_PBENCH_UNIT_TESTS}" ]]; then
    function check_enable_copr {
        local copr_user=$1
        local copr_name=$2

        if is_fedora ; then
  	    dnf copr enable ${copr_user}/${copr_name}
        else
  	    if is_redhat ; then
    	      	rhel_version=$(get_redhat_version)
    	      	rhel_major=${rhel_version%.*}
    	      	cd /etc/yum.repos.d/
    	      	local copr_url=https://copr.fedorainfracloud.org
    	      	local repo_file=${copr_user}-${copr_name}-epel-${rhel_major}.repo

    	      	[[ ! -f ${repo_file} ]] && wget -c ${copr_url}/coprs/${copr_user}/${copr_name}/repo/epel-${rhel_major}/${repo_file}
  	    else
  	        echo "Unsupported distribution"
  	    fi
        fi
    }
else
    function check_enable_copr {
	echo $1
	#$2 is the version which will vary
	return 0
    }
fi

function check_install_rpm {
    _n="${1}"
    _v="${2}"
    require-rpm "${_n}" "${_v}"
    local rc=${?}
    if [[ ! -z "${_v}" ]]; then
	_rpm="${_n}-${_v}"
    else
	_rpm="${_n}"
    fi
    if [[ ${rc} -ne 0 ]]; then
	error_log "[check_install_rpm] ${_rpm} is not installed"
    else
	debug_log "[check_install_rpm] ${_rpm} is installed"
    fi
    return ${rc}
}

function verify_tool_group {
    local group=$1
    if [[ -z "$group" ]]; then
	error_log "Bad argument to verify_tool_group"
	exit 1
    fi
    # Ensure we have a tools group directory to work with
    local tool_group_dir="$pbench_run/tools-$group"
    if [[ ! -d "$tool_group_dir" ]]; then
        printf -- "\t${script_name}: invalid --tool-group option (\"$group\"), directory not found: $tool_group_dir\n"
	return 1
    fi
    return 0
}

function verify_collect_sysinfo {
    local sysinfo=$1
    pbench-collect-sysinfo --sysinfo=$sysinfo --check
    local ret=$?
    if [[ $ret -ne 0 ]]; then
        printf -- "\t${script_name}: invalid --sysinfo option (\"$sysinfo\")\n"
    fi
    return $ret
}

function verify_common_bench_script_options {
    verify_tool_group "${1}"
    local ret_tg=${?}
    verify_collect_sysinfo "${2}"
    local ret_cs=${?}
    if [[ ${ret_tg} -ne 0 || ${ret_cs} -ne 0 ]]; then
        printf -- "\n"
        usage
        exit 1
    fi
}

# generate inventory file with controller and remotes
function generate_inventory {
	local component=$1
	if [[ $component == "stockpile" ]]; then
		echo "[stockpile]"
		echo $HOSTNAME
		echo "[all]"
		echo $HOSTNAME
		ls $tools_group_dir | awk -F@ '/^remote/ {print $2};'
	else
		echo "[controller]"
		echo $HOSTNAME
		echo "[remote]"
		ls $tools_group_dir | awk -F@ '/^remote/ {print $2};'
	fi
}

function resolve_benchmark_bin {
	# Encapsulation of method for resolving the actual benchmark
	# binary.
	which --skip-alias --skip-functions "${1}"
}

if [[ "${_PBENCH_UNIT_TESTS}" == 1 ]] ;then
    # For unit tests, we use a mock kill:
    # disable the built-in.
    enable -n kill
fi
