#! /bin/sh
#
# $Id: laptop_data_backup.sh,v 1.12 2010/09/16 17:53:52 jes91 Exp $

# Many people like to keep all 4 tardis related files together in one
# directory which is NOT their home directory.  This rude hack allows this
# to happen while maintaining backward compatibility (mostly!).
SCRIPT_DIR=$(dirname "$(expr "$0" : / >/dev/null || { echo $(pwd)/; } )$0")
[ -e "${SCRIPT_DIR}/tardis.conf" ] && HOME="${SCRIPT_DIR}"

EDITME="script $0"

# Rather than editing this script you can put the CRSID= and
# TARDIS_TAG= entries into a file $HOME/tardis.conf which this script
# reads in.
TARDIS_CF="$HOME/tardis.conf"
if [ -f "$TARDIS_CF" ]; then
    EDITME="config $TARDIS_CF"
    . $TARDIS_CF
fi

#
# Your DAMTP login, which is normally your CRSID (e.g. what you will
# use to login to Hermes etc).
if [ -z "${CRSID}" ]; then
    CRSID=""
fi
# e.g. CRSID="mr349"

#
# This will be part of the base-path for the backups of this machine,
# so pick something like the computer name (unless you want to back up
# 2 machines which have the same name in which case ensure that it is
# unique!  It may only contain ASCII letters, numbers plus any of _,
# -. %, @, =, + or .  and should not start with - or .
#
# If the hostname changes then the backups will not be stored in the
# same place so do not use `hostname` if the hostname is set using
# DHCP or may vary for other reasons.
#
if [ -z "${TARDIS_TAG}" ]; then
    TARDIS_TAG=""
fi
# e.g. TARDIS_TAG="womble" or perhaps TARDIS_TAG=`hostname`
#

#
# The home directory path on your computer (for storing the tardis
# config files).
#
LOCAL_HOME_DIR="$HOME"
#
# Normally this will be sufficient.  If $HOME is wrong you can set
# this manually e.g. LOCAL_HOME_DIR="/Users/xyy29" try echo $HOME in a
# shell.  On MacOSX for a login name of fred this will probably be
# something like /Users/fred while Linux systems might use /home/fred

#
# If the rsync to be used by this code is not on the default PATH,
# then add it in here.  Note that on some/many systems cron jobs are
# run with just a basic default PATH so won't pick up settings from
# your shell initialization files.
#
RSYNC_PATH=/usr/local/bin
PATH="$RSYNC_PATH:$PATH"

# Note about rsync versions.  This code was written for use with rsync
# version 3.0.5 and will also be fine with newer versions.  If your
# rsync is significantly older then there may be missing functionality
# which can cause problems and will certainly affect performance.  We
# can provide pre-compiled rsync binaries for most common OSX/Linux
# systems if you don't have an up-to-date version.

### You probably don't need to edit anything below this point, but
### feel free to read and/or comment on the rest of the script.

#
# Which server to use (tardis.damtp.cam.ac.uk is the only one at the
# moment)
#
TARDISHOST="tardis.damtp.cam.ac.uk"

#
# A file containing the directories to be backed up (one per line)
# Note that these must contain the *full* paths to the directories
# to be backed up.
# Any directory mentioned in here MUST exist or the backups will fail!
#
TARDIS_DIRS_FILE="${LOCAL_HOME_DIR}/tardis_backups.txt"

#
# Set of exclude patterns (things not to back up), download from
# example and edit.  See the rsync manual for details.
#
TARDIS_EXCLUDE_PATTERNS="${LOCAL_HOME_DIR}/tardis_excludes.txt"

# Location of the tardis ssh private key
TARDIS_KEY="${LOCAL_HOME_DIR}/.ssh/id_rsa_tardis"

# check that CRSID is set
if [ -z "${CRSID}" ]; then
    cat <<EOF
You must edit the $EDITME to set CRSID to your DAMTP login name,$(expr "$EDITME" : script >/dev/null && echo -e "\nor (better) download and edit tardis.conf and place it alongside this script,")
i.e., this is the login name you use when logging on to the DAMTP
machines and will usually be the same as you use on Hermes etc.  This
may not be the same as your local login name.  Quitting!
EOF
    exit 1
fi

# Check that the file of directories exists
if [ ! -e ${TARDIS_DIRS_FILE} ]; then
    echo "Tardis directory sources file ${TARDIS_DIRS_FILE} is missing:"
    echo "Please create the file ${TARDIS_DIRS_FILE}"
    echo "as a list of files and directories to backup."
    echo "Quitting!"
    exit 1
fi

# and that the exclude patterns file exists
if [ ! -e ${TARDIS_EXCLUDE_PATTERNS} ]; then
    cat <<EOF
Tardis exclude patterns file ${TARDIS_EXCLUDE_PATTERNS} is missing.
Try downloading the example file from:

  http://www.damtp.cam.ac.uk/internal/computing/backups/laptops/

and edit as needed.  Quitting!
EOF
    exit 1
fi

# the tag must also be set 
if [ -z "${TARDIS_TAG}" ]; then
    echo "You must set TARDIS_TAG first.  Edit the $EDITME"
    exit 1
else
    # give up and use perl for the test - hope they have it!
    if perl -e "if ('$TARDIS_TAG' =~ /([^\w\-_\%\@\=\+\.]|^[\.\-])/) { exit 1}"; then
	echo "Tardis tag '${TARDIS_TAG}' looks valid"
    else
	cat <<EOF

The value of TARDIS_TAG contains characters which are not valid.
Currently it is set to:

  '${TARDIS_TAG}'

please edit the tag so that it only contains character from:

  A-Z a-z 0-9 - _ % @ = + .

ie no whitespace or other punctuation is allowed.  Also please don't
have the tag start with '-' or '.' to avoid confusion.  Quitting.

EOF
        exit 1
    fi
fi

#
# and the ssh private key must exist - if not give instructions on making it
# and pushing it to the server.
#
if [ ! -e ${TARDIS_KEY} ]; then
    #
    # If the TARDIS_KEY file is missing we should make one and try to
    # use addkey - but that will require a password so you should only
    # do it if running interactivly...
    #
    cat <<EOF
Tardis ssh key ${TARDIS_KEY} is missing.  Create with:

  ssh-keygen -t rsa -b 2048 -N '' -C "Tardis key for ${TARDIS_TAG}" -f ${TARDIS_KEY}

And then upload the public part to the server with something like:

  ssh ${CRSID}@${TARDISHOST} addkey "${TARDIS_TAG}" < ${TARDIS_KEY}.pub

Quitting.
EOF
    exit 1
fi

#
# The logfile is not deleted, so you will need to delete it
# manually from time to time (or cycle it e.g. with logrotate)
#
LOGFILE="/tmp/tardis-backup-${CRSID}"

echo "Logfile is ${LOGFILE}"

#
# Horrid old log cycling code based on one from Newsyslog (hey anyone
# else still remember that!)
#
dologmove() {
  LOG=$1
  COUNT=$2
  if [ -s ${LOG} ]; then
      # Copy old ones down
      while [ "$COUNT" != "0" ]; do
	  NCOUNT=$(expr $COUNT - 1)
	  if [ -f ${LOG}.${NCOUNT} ]; then
	      mv ${LOG}.${NCOUNT} ${LOG}.${COUNT}
	      chmod 600 ${LOG}.${COUNT}
	  fi
	  COUNT=$NCOUNT
      done
      mv ${LOG} ${LOG}.0
  fi
  touch ${LOG}
  chmod 600 ${LOG}
}

# Keep last 15 versions of the logs
dologmove ${LOGFILE} 15

# for debugging
#set -x

#
# Maybe we should set '-o userknownhostsfile' to point at a copy of
# the tardisk public-key...  Still this should be ok for most cases.
# Check the ssh manual for details of what the options are for.  You
# can set TARDIS_SSHOPT to easily add more options (e.g. -vvv) while
# testing.
#
SSH="ssh ${TARDIS_SSHOPT} -x2 -c arcfour -o PreferredAuthentications=publickey -i ${TARDIS_KEY}"

#
# Find the remote path to be used when using sftp to extract copies etc
#
RPATH=$($SSH ${CRSID}@${TARDISHOST} showpath "${TARDIS_TAG}" 2>>$LOGFILE)
if [ -z "${RPATH}" ]; then
    # If that failed then the rsync won't work...
    echo "Failed to ssh to $TARDISHOST to get path info. Quitting."
    exit 1
fi

echo "Backups for '$TARDIS_TAG' to ${CRSID}@${TARDISHOST}:${TARDIS_TAG} stored in $RPATH on server"

# Check the rsync manual for what these options are all for
RSYOPT="-aSHRrzx --omit-dir-times"

#
# Set ERSYOPT to any extra options to add e.g. -A for ACL or -X for
# xattr support.
#
# On MacOSX with a suitable version of rsync you _may_ want to try
# adding these to the options.  You need a specially patched version
# of rsync for these to work, see see
# http://www.bombich.com/mactips/rsync.html
#
#ERSYOPT="-NAX --fileflags"
#
# On Linux systems with ACL and XATTR support you may want to add
# these:
#
#ERSYOPT="-AX"
#
# Note that these extra options are just for preserving more
# information about the files, the contents, permissions, timestamps
# and ownerships will be saved anyway.
#
# For increased verbosity of output (e.g. if debugging) you can set
# -vv here to get rsync to log _every_ file it copies - note this will
# be _very_ long.
#
#ERSYOPT="-vv"
#
echo "rsync options: $RSYOPT $ERSYOPT"

# Try the rsync
if rsync $RSYOPT $ERSYOPT --log-file=${LOGFILE} -e "${SSH}" \
    --files-from="${TARDIS_DIRS_FILE}" \
    --exclude-from="${TARDIS_EXCLUDE_PATTERNS}" \
    / ${CRSID}@${TARDISHOST}:"${TARDIS_TAG}"
then
    echo "Backup was successful, getting quota:"

    QUOTA=$($SSH ${CRSID}@${TARDISHOST} quota 2>>$LOGFILE)
    if [ -z "${QUOTA}" ]; then
	echo "Failed to get your quota.  Oops - please report."
    else
	QP=$(perl -e "(\$u,\$l)=split(/ /, '$QUOTA'); printf \"Used: %.3f GiBytes  Quota-Limit:  %.3f GiBytes  Percentage used: %.1f%%\n\", \$u/(1024*1024), \$l/(1024*1024), 100.0* \$u/\$l;")
	cat <<EOF

Your usage/quota on the server is currently (RAW KiBytes=$QUOTA):

  $QP

EOF
        # Now try to get list of backups
        BLISTS=$($SSH ${CRSID}@${TARDISHOST} list "${TARDIS_TAG}" 2>>$LOGFILE | sed 's/^/  /g')
	if [ -z "${BLISTS}" ]; then
	    echo "Failed to get list of backups.  Oops - please report."
	else
	    cat <<EOF
Listing available backups for $TARDIS_TAG:

$BLISTS

EOF
	fi
    fi
else
    #
    # If there is a failure it is worth sending us the messages (and
    # edit ERSYOPT to include -vv to see what is going wrong)
    #
    echo "Backup failed: $?"
    exit 1
fi

