#! /bin/sh
#
# Copyright © 2012, 2014, 2017 Richard Kettlewell.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
set -e

CLIENTS="deodand wampoon"
WORK=${PWD}/systest.work
TOOLS=${PWD}/tools
SCRIPTS=${PWD}/scripts
RSBACKUP=${PWD}/src/rsbackup

x() {
  echo "EXEC:" "$@" >&2
  "$@"
}

vg() {
  case "$1" in
  deodand )
    echo deodand2
    ;;
  wampoon | fanticule )
    echo "$1"
    ;;
  * )
    echo ""
    ;;
  esac
}

# Clean up leftovers
clean() {
  for client in ${CLIENTS}; do
    vg=`vg $client`
    x ssh ${client} "umount /rsbackup || true"
    if [ "$vg" != "" ]; then
      x ssh ${client} "umount /var/lib/rsbackup/snapshots/rsbackup || true"
      x ssh ${client} "dd conv=nocreat if=/dev/zero of=/dev/${vg}/rsbackup || true"
      x ssh ${client} "lvremove -f ${vg}/rsbackup.snap || true"
      x ssh ${client} "lvremove -f ${vg}/rsbackup || true"
      x ssh ${client} "rmdir /rsbackup /var/lib/rsbackup/snapshots/rsbackup /var/lib/rsbackup/snapshots || true"
    else
      x ssh ${client} "rm -rf /rsbackup"
    fi
  done
  rm -rf ${WORK}
}

# Create subject volumes etc
setup() {
  echo "Creating directories"
  mkdir -p ${WORK} ${WORK}/logs
  mkdir -m 0700 -p ${WORK}/store
  echo dummy > ${WORK}/store/device-id
  echo "Creating config"
  cat > ${WORK}/config <<EOF
store ${WORK}/store
device dummy
logs ${WORK}/logs
lock ${WORK}/lock
pre-volume-hook ${TOOLS}/rsbackup-snapshot-hook
post-volume-hook ${TOOLS}/rsbackup-snapshot-hook
backup-job-timeout 60
hook-timeout 60
host-check command ${SCRIPTS}/host-check
EOF
  for client in ${CLIENTS}; do
    hostname=${client}
    if [ ${client} = $(uname -n) ]; then
      hostname=localhost
    fi
    cat >> ${WORK}/config <<EOF
host ${client}
  hostname ${hostname}
  volume rsbackup /rsbackup
EOF
  done
  echo "Generated config file:"
  cat ${WORK}/config
  echo
  for client in ${CLIENTS}; do
    vg=`vg $client`
    if [ "$vg" != "" ]; then
      x ssh ${client} "lvcreate -L 256M -n rsbackup ${vg}"
      x ssh ${client} "mkfs -q -t ext3 /dev/${vg}/rsbackup"
      x ssh ${client} "mkdir -p /rsbackup"
      x ssh ${client} "mkdir -p /rsbackup /var/lib/rsbackup/snapshots /var/lib/rsbackup/snapshots/rsbackup"
      x ssh ${client} "mount /dev/${vg}/rsbackup /rsbackup"
    else
      x ssh ${client} "mkdir -p /rsbackup"
    fi
    x scp -qr . ${client}:/rsbackup/.
  done
}

clean_host_checks() {
  for client in ${CLIENTS}; do
    rm -f ${client}.fail ${client}.ran
  done
}

host_checks_ran() {
  for client in ${CLIENTS}; do
    if [ $client = deodand ]; then
      continue
    fi
    if [ ! -e ${client}.ran ]; then
      echo >&2 "ERROR: host check for ${client} did not run"
      exit 1
    fi
  done
}

backup_present() {
  if [ -d ${WORK}/store/$1/rsbackup/$(date +%F) ]; then
    :
  else
    echo >&2 "ERROR: backup for $1 missing"
    exit 1
  fi
}

backup_absent() {
  if [ -d ${WORK}/store/$1/rsbackup/$(date +%F) ]; then
    echo >&2 "ERROR: backup for $1 unexpectedly present"
    exit 1
  fi
}

backup() {
  clean_host_checks
  x touch wampoon.fail
  x ${RSBACKUP} --backup --verbose --config ${WORK}/config
  host_checks_ran
  backup_present deodand
  backup_absent wampoon
  x rm -f wampoon.fail
  x ${RSBACKUP} --backup --verbose --config ${WORK}/config
  host_checks_ran
  backup_present deodand
  backup_present wampoon
  clean_host_checks
}

verify() {
  for client in ${CLIENTS}; do
    echo "Verifying ${client}"
    diff -rqN --exclude systest.work . ${WORK}/store/${client}/rsbackup/$(date +%F)/.
  done
}

actions="clean setup backup verify clean"

while [ $# -gt 0 ]; do
  case "$1" in
  --clean )
    actions="clean"
    ;;
  --leave )
    actions="clean setup backup verify"
    ;;
  --help )
    cat <<EOF
Usage:
  systest [OPTIONS]
Options:
  --clean          Clean up leftovers from failed tests
  --leave          Don't clean up at end
  --help           Display usage message
EOF
    exit 0
    ;;
  * )
    echo "ERROR: unknown option '$1'" >&2
    exit 1
    ;;
  esac
  shift
done

for action in $actions; do
  echo "ACTION: $action"
  $action
  echo
done
