#!/bin/bash

set -euxo pipefail

# run an mmapply policy across the cluster via slurm

############################################################
# Default Values                                           #
############################################################

outdir="/data/rc/gpfs-policy/data"
policy_file="./policy-def/list-path-external"
output_log_prefix=""
dry_run=false

############################################################
# Help                                                     #
############################################################

usage()
{
>&2 cat << EOF
Usage: $0 [ -h ] [ -o | --outdir ] [ -f | --output-prefix ] [ -P | --policy-file] device
EOF
exit 1
}

help()
{
>&2 cat << EOF
Runs mmapplypolicy on the specified device/fileset. The policy file dictates the actions performed including list, delete, add, etc. This is most often called by the submit-pol-job wrapper instead of invoked directly

Usage: $0 [ -h ] [ -o | --outdir ] [ -f | --output-prefix ] [ -P | --policy-file ] device

options:
    -h|--help           Print this Help.
    --dry-run           Do not run the policy command or any command that modifies any files or directories such as 
                            mkdir

Required:
    device              GPFS fileset/directory apply the policy to. Can be 
                            specified as either the name of the fileset or the 
                            full path to the directory 
                            (Examples: scratch, /data/user/[username])

Path:   
    -o|--outdir         Parent directory to save policy output to 
                            (default: /data/rc/gpfs-policy/data)
    -f|--output-prefix  Prefix of the policy output file. Appended with a metadata string containing the policy name, 
                            job ID, and date

Policy Options:
    -P|--policy-file    Path to policy file to apply to the given GPFS device
EOF
exit 0
}

args=$(getopt -a -o ho:f:P: --long help,outdir:,output-prefix:,policy-file:,dry-run -- "$@")

if [[ $? -gt 0 ]]; then
  usage
fi

eval set -- ${args}

while :
do
  case $1 in
    -h | --help)            help                    ;;
    -o | --outdir)          outdir=$2               ; shift 2 ;;
    -f | --output-prefix)   output_log_prefix=$2    ; shift 2 ;;
    -P | --policy-file)     policy_file=$2          ; shift 2 ;;
    --dry-run)              dry_run=true            ; shift 1 ;;
    --) shift; break ;;
    *) >&2 echo Unsupported option: $1
       usage ;;
  esac
done

if [[ $# -eq 0 ]]; then
  usage
fi

device="$1"

# Ensure device is specified
if [[ -z "${device}" ]]; then
    echo "Error: Specify either the name of a fileset or a directory path"
    usage
fi

# set default output_log_prefix if not specified in the arguments
if [[ -z "${output_log_prefix}" ]]; then
    modified_device=$(echo "${device}" | sed -e 's|^/||' -e 's|/$||' -e 's|/|-|g')
    output_log_prefix="list-policy_${modified_device}"
fi

# create temporary working directory for list aggregation
tmpglobal="${outdir}/slurm-tmp-${SLURM_JOBID}"
tmpscratch="${outdir}/slurm-tmp-${SLURM_JOBID}"

nodes=$(scontrol show hostnames "${SLURM_JOB_NODELIST}" | tr '\n' ',' | sed -e 's/,$//')
cores="${SLURM_CPUS_PER_TASK}"

DATESTR=$(date +'%Y-%m-%dT%H:%M:%S')

policy=$(basename ${policy_file})
filetag="${policy}_slurm-${SLURM_JOBID}_${DATESTR}"

cmd="mmapplypolicy ${device} -I defer \
  -P ${policy_file} \
  -g ${tmpglobal} \
  -s ${tmpscratch} \
  -f ${outdir}/list-${SLURM_JOBID} \
  -M FILEPATH=${device} \
  -M JOBID=${SLURM_JOBID} \
  -M LIST_OUTPUT_FILE=${output_log_prefix} \
  -N ${nodes} -n ${cores} -m ${cores}"

if [[ ! ${dry_run} ]]; then
    mkdir -p ${tmpglobal}
    
    # run policy command
    ${cmd}

    log_name="${output_log_prefix}_${filetag}"
    log_dir="${outdir}/${log_name}"

    mkdir -p ${log_dir}/raw
    chmod 1770 ${log_dir}

    # tag output file with run metadata
    raw_log_file=$(find ${outdir} -maxdepth 1 -name "list-${SLURM_JOBID}*" -type f | head -1)
    if [[ "$raw_log_file" != "" ]]; then
        mv -n ${raw_log_file} ${log_dir}/raw/${log_name}
        gzip ${log_dir}/raw/${log_name}

        chmod 440 ${log_dir}/raw/${log_name}.gz
        chmod 550 ${log_dir}/raw
    fi

    chown -R ${USER}:atlab ${log_dir}
    
    rmdir ${tmpglobal}
fi

