#!/bin/bash
#
# Sipwise NGCP parallel SCP wrapper.
#

set -e

SELF=${0##*/}
DEBUG=${NGCP_DEBUG:-false}

debug () {
  if "${DEBUG}" ; then
    echo "[${SELF}]: $*"
  fi
}

usage () {
  cat <<HELP
Usage: ${SELF} [<options>] <hosts> <src-files> <dst-files>

Options:
  -l, --user=USER        User name.
  -p, --par=PAR          Max number of parallel threads.
  -o, --outdir=OUTDIR    Output directory for stdout files.
  -e, --errdir=ERRDIR    Output directory for stderr files.
  -t, --timeout=TIMEOUT  Timeout (secs) (0 = no timeout) per host.
  -O, --options=OPTIONS  SSH options.
  -x, --extra-args=ARGS  Extra command-line arguments, with processing for
                           spaces, quotes, and backslashes.
  -X, --extra-arg=ARG    Extra command-line argument.
  -r, --recursive        Recursively copy directories.
  -v, --verbose          Turn on warning and diagnostic messages.
      --help             Show this help message and exit.

<hosts> supports hostnames, or the following aliases:
  self - this node
  peer - the peer for this node
  pair - this node and its peer
  neighbours - all nodes in the cluster except for self
  all - all nodes in the cluster
HELP
}

if [ -r /etc/default/ngcp-roles ] ; then
  # shellcheck disable=SC1091
  . /etc/default/ngcp-roles
else
  NGCP_SSHD=$(awk '/Port/ { print $2 }' /etc/ssh/sshd_config)
fi

# Defaults.
PSCP_OPTS=()
PSCP_HOST=
PSCP_SRC=
PSCP_DST=
PSCP_PORT="${NGCP_SSHD:-22}"

# Parse wrapper options.
while [[ $# -gt 0 ]]
do
  optname="$1"
  shift

  case "${optname}" in
    -[lptoexXO]|--user|--par|--timeout|--outdir|--errdir|--extra-args|--extra-arg|--options)
      PSCP_OPTS+=("${optname}" "$1")
      shift
      ;;
    -[lptoexXO]*|--user=*|--par=*|--timeout=*|--outdir=*|--errdir=*|--extra-args=*|--extra-arg=*|--options=*)
      PSCP_OPTS+=("${optname}")
      ;;
    -[rv]|--recursive|--verbose)
      PSCP_OPTS+=("${optname}")
      ;;
    -?|--help)
      usage
      exit 0
      ;;
    *)
      if [[ $# -ne 2 ]]
      then
        usage 2>&1
        exit 1
      fi
      PSCP_HOST="${optname}"
      PSCP_SRC="$1"
      PSCP_DST="$2"
      break
      ;;
  esac
done

# Handle host aliases.
PSCP_HOSTS=()
for host in ${PSCP_HOST}
do
  case ${host} in
    self)
      PSCP_HOSTS+=("${NGCP_HOSTNAME_PSSH}")
      ;;
    peer)
      PSCP_HOSTS+=("${NGCP_PEERNAME_PSSH}")
      ;;
    pair)
      PSCP_HOSTS+=("${NGCP_HOSTNAME_PSSH}" "${NGCP_PEERNAME_PSSH}")
      ;;
    all)
      # shellcheck disable=SC2206
      PSCP_HOSTS+=(${NGCP_HOSTS_PSSH})
      ;;
    neighbours)
      # shellcheck disable=SC2206
      PSCP_HOSTS+=(${NGCP_NEIGHBOURS_PSSH})
      ;;
    *)
      PSCP_HOSTS+=("${host}:${PSCP_PORT}")
      ;;
  esac
done

if [ ${#PSCP_HOSTS[@]} -eq 0 ]
then
  echo "[${SELF}] No hosts specified, skipping."
  exit 0
fi

PSCP=(parallel-scp)
PSCP+=(-O "BatchMode=yes")
PSCP+=("${PSCP_OPTS[@]}")
PSCP+=(-H "${PSCP_HOSTS[*]}")
PSCP+=("${PSCP_SRC[*]}")
PSCP+=("${PSCP_DST[*]}")

debug "${PSCP[*]}"
"${PSCP[@]}"
