#!/bin/sh

# ClonePanel - Manages duplicate accounts on two or more webservers,
# including snapshot backups, monitoring and failover dns.
# Copyright (C)2006 Chris Cheers, Internet Lynx.
# Contact chris[at]clonepanel[dot]com.
# Internet Lynx, PO Box 7117, Mannering Park, NSW 2259, Australia

# 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 2
# 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, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

Version=0.33
# restoreclean -h for built-in documentation

set -u
# Be strict about variable declaration

unset PATH
#avoid use of $PATH - limit script to system commands we choose

PROGRAM_DIR=$(/bin/echo $0 |/bin/sed -e "s/\/[a-zA-Z0-9_]*$//")
# Extract the working directory from command line
# NB - if your system doesn't have echo and sed in these locations
# then this line will need to be changed in all shell scripts

# Standard include files:
. $PROGRAM_DIR/includes

# Built-in documentation:
function showdocs {
	$CAT <<-EODOC
		Restore files on a host server to a previously-stored snapshot
		./restore -u myuser -H myhost -s hourly|daily|weekly|monthly.[01234] [-a]
		The account must already be set up using setup_account

		Command line options: 
		-h		Print these instructions and exit
		-u user		CPanel username of the account
		-H host		Nickname of the server
		-s version	Which snapshot to restore - default is latest (hourly.0)
		-a		(optional) All files - ignore normal excludes (eg. config files). Use with care!

		Note - use restore to retrieve a single file or directory.
		Restoreclean will set up the host's public_html directory
		to exactly match the snapshot, deleting files not in the snapshot.
EODOC
	exit $DOC_REQUEST
}

function setup_mirror_dirs {
# define variables for web sync (we can't combine this with the earlier
# case because MIRROR_DIRS may be host dependent)
	EXCLUDES=$USER_DIR/$EXCLUDESFILE_WEB
	MIRROR_DIRS[0]=$MIRROR_DIR_WEB
	MIRROR_SS[0]=$MIRROR_SS_WEB
	if [ "`$LS $USER_DIR/$DATABASE_DIRNAME`" ]; then
		MIRROR_DIRS[1]=$DATABASE_STORENAME
		MIRROR_SS[1]=$DATABASE_STORENAME
	fi
        mirror_dir_count=${#MIRROR_DIRS[@]}
}


# Initialise own input variables:
user=''
compat=''
host=''
snap=''
allfiles='n'

# Start real script

# Check for help request and input variables in the command line options:
while getopts ":hu:s:H:a" opt
do
	case $opt in
		h)	showdocs
			;;
		u)	user=$OPTARG
			;;
		H)	host=$OPTARG
			;;
		s)	snap=$OPTARG
			;;
		a)	allfiles='y'
			;;
		*)	$ECHO "Unknown option. Use -h for instructions"
			exit $E_UNKNOWN_OPT
			;;
	esac
done
shift $(($OPTIND - 1))

OPTIND=1
# reset getopts for next time


if [ ! $user ]; then
	cecho -n -c $prompt "Enter account username: "
	read user
	if [ ! $user ]; then
		cecho -c $error "Username must be specified"
		exit $E_BLANK_INPUTS
	fi
fi

if [ ! $host ]; then
	cecho -n -c $prompt "Enter host name: "
	read host
	if [ ! $host ]; then
		cecho -c $error "Host name must be specified"
		exit $E_BLANK_INPUTS
	fi
fi

if [ ! "$snap" ]; then
	snap='hourly.0'
	cecho -c $warning "Warning - unspecified snapshot defaults to latest"
fi

# User-specific Include files (only after defining $user and $host):
config -u $user -t WEB -H $host

if [ ! -d $SNAPSHOT_SUBDIR/$snap ]; then
	cecho -c $error "Directory $snap does not exist in $SNAPSHOT_SUBDIR"
	exit $E_NO_SOURCE
fi


cecho -c $info "Phase A - Preparing directories" ;

if [ $dirpath ] ; then
# Specified directory / filename - check both exist
	if [ ! -d $SNAPSHOT_SUBDIR/$snap/$dirpath ]; then
		cecho -c $error "Directory $dirpath does not exist in $SNAPSHOT_SUBDIR/$snap"
		exit $E_NO_SOURCE
	fi
	if [ "$filename" ]; then
		if [ ! -f $SNAPSHOT_SUBDIR/$snap/$dirpath/$filename ]; then
			cecho -c $error "File $filename does not exist in $SNAPSHOT_SUBDIR/$snap/$dirpath"
			exit $E_NO_SOURCE
		fi
	fi
	eval remdir=\$"MIRROR_DIR_WEB"
	eval locdir=\$"MIRROR_SS_WEB"
	eval excfile=\$"EXCLUDESFILE_WEB"
	EXCLUDES=$USER_DIR/$excfile
# Standard excludes list will be removed later if -a specified
	MIRROR_DIRS=`$ECHO $dirpath| $SED -e "s/$locdir/$remdir/g"`
# eg. Substitute $MIRROR_SS_WEB (usually public_html) for $MIRROR_DIR_WEB
# (may be something else, eg. domain name on non-CPanel system) in dirpath
	MIRROR_SS=$dirpath
# dirpath by definition is in the local snapshot
	mirror_dir_count=1
else
	if [ "$filename" ]; then
		cecho -c $error "Source directory must be specified (-d) for single file restore"
		exit $E_NO_SOURCE
	fi
	setup_mirror_dirs
# Create the standard list of directories to backup / mirror
# (may depend on push host config)
fi

if [ "$allfiles" ]; then
# Ignore normal excludes (eg. config files)
	EXCLUDES=''
fi

#get host ip address from hosts file
if [ ! $A ]; then
	cecho -c $error "$Host $hostname_pull has no ip - check hosts file"
	exit $E_NO_PUSHTO_IP
fi

#finally get its remote directory (normally /home/username)
if [ ! $REMOTEHOST_HOME ]; then
	cecho -c $error "Host $host has no remote dir - check remote_dir file"
	exit $E_NO_PUSHTO_DIR
fi

cecho -c $info "Phase B - rsync 'push' to $host" ;

remote_ssh="$SSH -p $SSH_PORT -i $AUTH_DIR/$host";

# Step B1 - Pre-process
if [ $dirpath ]; then
	cecho -c $warning "Skipping pre-processing when restoring specified files / directories"
else
	$remote_ssh $user@$A "pre_process -f -t WEB -d PUSH"
	checkerror $? $E_PRE_PUSH_FAILED
fi

# Step B2 - Sync
for (( i = 0 ; i < $mirror_dir_count ; i++ ))
do
	dir=${MIRROR_DIRS[$i]}
	ssdir=${MIRROR_SS[$i]}
	$RSYNC	--bwlimit=$RSYNC_BWLIMIT		\
		-avz --delete				\
		--exclude-from="$EXCLUDES"		\
		-e "$remote_ssh"	 		\
		$SNAPSHOT_SUBDIR/$snap/$ssdir/$filename $REMOTEHOST_USERNAME@$A:$REMOTEHOST_HOME/$dir
	checkerror $? $E_RSYNC_PUSH_FAILED
done

# Step B3 - Post-process
$remote_ssh $REMOTEHOST_USERNAME@$A "post_process -f -t WEB -d PUSH"
checkerror $? $E_POST_PUSH_FAILED

cecho -c $ok "$($DATE) restore completed successfully"
















