#!/usr/bin/bash

# This script uses the pbench-server.cfg file just installed, to
# figure out what tasks to add to the pbench crontab on this
# machine. After creating the crontab, it does *not* activate it: that
# is a separate manual step.

prog=$(basename ${0})

if [[ -z "${1}" ]]; then
    printf -- "[%s] ERROR: missing crontab path directory argument\n" "${prog}" >&2
    exit 1
fi
crontabpath="${1}"

mkdir -p ${crontabpath}
chmod 755 ${crontabpath}
if [[ ${?} -ne 0 ]]; then
    printf -- "[%s] ERROR: failed to properly create crontab path, '%s'\n" "${prog}" "${crontabpath}" >&2
    exit 1
fi

crontab="${crontabpath}/crontab"
> ${crontab}

if [ ! -f "$_PBENCH_SERVER_CONFIG" ] ;then
    echo "Config file $_PBENCH_SERVER_CONFIG does not exist"
    exit 2
fi

bindir=$(pbench-config script-dir pbench-server)
if [ -z "$bindir" ] ;then
    echo "No 'script-dir' setting in [pbench-server] section of config file $_PBENCH_SERVER_CONFIG"
    exit 3
fi

# what roles does this server play?
roles=$(pbench-config -l roles pbench-server)
if [ -z "$roles" ] ;then
    echo "No 'roles' setting in [pbench-server] section of config file $_PBENCH_SERVER_CONFIG"
    exit 3
fi

# the hostname of the host we are installing in.
hostname=$(hostname -f)

# In some cases, the host specified in the config file
# is different from what hostname -f returns. In such
# cases, we also have a "real" name in the config file
# that *should* match what hostname -f returns, otherwise
# the sanity check below will just skip all the roles for
# the host, leaving us with an empty crontab. If you do
# get an empty crontab, this is a good thing to check.
realhost=$(pbench-config realhost pbench-server)

function crontab_header() {
    local mailfrom mailto

    echo "_PBENCH_SERVER_CONFIG=$_PBENCH_SERVER_CONFIG" >> $crontab
    echo "PYTHONPATH=$(pbench-config lib-dir pbench-server)" >> $crontab

    mailto=$(pbench-config mailto pbench-server)
    if [ -z "$mailto" ] ;then
        echo "No 'mailto' specified in [pbench-server] section of the config file $_PBENCH_SERVER_CONFIG"
    else
        echo "MAILTO=$mailto" >> $crontab
    fi
    mailfrom=$(pbench-config mailfrom pbench-server)
    if [ -z "$mailfrom" ] ;then
        echo "No 'mailfrom' specified in [pbench-server] section of the config file $_PBENCH_SERVER_CONFIG"
    else
        echo "MAILFROM=$mailfrom" >> $crontab
    fi
}

function crontab_normal() {
    local role=$1

    tasks=$(pbench-config -l tasks $role)
    if [ -z "$tasks" ] ;then
        echo "No 'tasks' specified in [$role] section of the config file $_PBENCH_SERVER_CONFIG"
    else
        for task in $tasks ;do
            crontabline=$(pbench-config crontab $task)
            if [ -z "$tasks" ] ;then
                echo "No 'crontab' specified in [$task] section of the config file $_PBENCH_SERVER_CONFIG"
            else
                echo "$crontabline" >> $crontab
            fi
        done
    fi
}

# This function expands a crontab template from a task in the config file
# with values from a specific section that specifies replacements.
# E.g. the crontab option in the task [pbench-sync] might have this
# value:
#   * * * * * flock -n %(deploy-lock-dir)s/$SATELLITE_LOCK %(deploy-script-dir)s/pbench-sync-satellite\
#                    $SATELLITE_PREFIX $SATELLITE_HOST $SATELLITE_ARCHIVE
# The placeholders (the $-prefixed names) are replaced from the section
# that is passed in as the first argument. E.g if the section is "satellite-testing"
# and the [satellite-testing] section looks like this:
#
# [satellite-testing]
# satellite-host = dhcp31-38.example.com
# satellite-prefix = TESTING
# satellite-lock = pbench-sync-satellite-%(satellite-prefix)s.lock
# satellite-archive = /pbench/archive/fs-version-001
# satellite-opt = /opt/pbench-server
#
# the (admittedly obscure) last line substitutes for $SATELLITE_HOST the
# value of satellite-host in the section and similarly for all the other
# options in the section.
#
function crontab_with_substitutions() {
    local section=$1
    local task=$2

    crontabline=$(pbench-config crontab $task)
    if [ -z "$crontabline" ] ;then
        echo "No 'crontab' specified in [$task] section of the config file $_PBENCH_SERVER_CONFIG"
    else
        echo "$crontabline" |
                sed "s;\$SATELLITE_CONFIG;$section;g" |
                sed "$(pbench-config -a $section | grep = | awk -F' = ' '{gsub(/-/, "_", $1); printf "s;$%s;%s;g\n", toupper($1) , $2;}')" >> $crontab
    fi
}

# produce the header
crontab_header

for role in $roles ;do

    host=$(pbench-config host $role)
    # Sanity test: either host or realhost (from the config file)
    # *must* match the hostname of the host where this is being
    # installed, otherwise this role is irrelevant for this host
    # and we skip it.
    if [ "$host" != "$hostname" -a "$realhost" != "$hostname" ] ;then
        continue
    fi
    case $role in
        pbench-sync-satellites)
            satellites=$(pbench-config -l satellites $role)
            tasks=$(pbench-config -l tasks $role)
            for satellite in $satellites ;do
                for task in $tasks; do
                    crontab_with_substitutions $satellite $task
                done
            done
            ;;
        pbench-prep)
            versions=$(pbench-config -l pbench-move-results-receive-versions pbench-server)
            tasks=$(pbench-config -l tasks $role)
            for version in $versions ;do
                for task in $tasks; do
                    crontab_with_substitutions prep-shim-$version $task
                done
            done
            ;;
        *)
            crontab_normal $role
            ;;
    esac
done

chmod 644 $crontab

# create the lock directory that the cron entries will use
lockdir=$(pbench-config lock-dir pbench-server)
mkdir -p ${lockdir}
chmod 755 ${lockdir}

user=$(pbench-config user pbench-server)
if [ -z "$user" ] ;then
    echo "user is undefined in section \"pbench-server\" of config file."
    exit 5
fi

group=$(pbench-config group pbench-server)
if [ -z "$group" ] ;then
    echo "group is undefined in section \"pbench-server\" of config file."
    exit 5
fi

chown $user.$group ${crontab}
chown -R $user.$group ${lockdir}

exit 0
