#!/bin/bash


export PRE=/usr/local

declare -A CONFIG
export CONFIG
ETC=/etc
export ETCDIR=$ETC/snapsched
export CFGFILE=$ETCDIR/config
export INTCRONFILE_BASE=snapsched
export CRONTAB=$ETC/cron.d/$INTCRONFILE_BASE
export CRONPROG=$PRE/lib/snapsched/scheduled
export TMPBASE=/tmp/ssched

exec 2>&1

# create the scheduled snapshots.  called by cron.

export OSILENT=

# load the library routines
. $PRE/lib/snapsched/snapsched-funcs

# first arg is snapshot source

NSRC="$1"
# one day, name of source (NSRC) and actual dir name (CONFIG["SSRC_$NSRC"])
# will be separate values
SSRC="$NSRC"
shift

# second arg is frequency
FREQ=$1
shift

declare -u freq

freq=$FREQ

# validate NSRC arg, and read in config file
# no usage message, since this is called by cron.  supposedly.
_ssched_validate_nsrc SSRC "" ||
	exit 1

SSRC=${CONFIG[SNAP_MOUNT_DIR]}/$SSRC

_ssched_set_verbosity

omsg "$freq snapshot job for '$NSRC' on `hostname` at `date '+%F %T'`"

case $FREQ in
	hourly)
		L=H
		DATESTR=`date +%Y-%m-%d`
		INTSTR=`date +%H`
		;;
	daily)
		L=D
		DATESTR=`date +%Y-%m`
		INTSTR=`date +%d`
		;;
	weekly)
		L=W
		DATESTR=`date +%Y-%m`
		INTSTR=`date +%W`
		;;
	monthly)
		L=M
		DATESTR=`date +%Y`
		INTSTR=`date +%m`
		;;
	*)
		omsg "$0: invalid freq argument '$FREQ'."
		exit 1
		;;
esac

MAX_SCNT=${CONFIG[SSRC_${NSRC}%${L}_MSC]}

if [ "$MAX_SCNT" -lt 1 ] ; then
	# max snapcount of 0 means no snapping
	exit 0
fi

SNAME="${DATESTR}_${INTSTR}"
TBASE="${CONFIG["SNAP_MOUNT_DIR"]}/${CONFIG["SNAP_BASE_DIR"]}/$NSRC/$FREQ"
TDIR="${TBASE}/$SNAME"

_ssched_mount_rootvol ${CONFIG[SNAP_MOUNT_DIR]} || {
	ES=$?
	omsg "Unable to mount root volume '${CONFIG[SNAP_MOUNT_DIR]}': $ES"
	if [ ! -d "${CONFIG[SNAP_MOUNT_DIR]}" ] ; then
		omsg "Directory  '${CONFIG[SNAP_MOUNT_DIR]}' does not exist."
	elif [ "$ES" -eq 4 ] ; then
		omsg "Perhaps it needs to be configured in /etc/fstab?  Snapsched requires that."
	fi
	exit 1
}

# make necessary directories, if any; check for existing with same name

if [ ! -d "$TBASE" ] ; then
	mkdir -p "$TBASE" || {
		omsg "Failed to create the snapsched storage directory ${TBASE}: $?"
		omsg "Cannot create snapshot '$FREQ/$SNAME'."
		_ssched_umount_rootvol ${CONFIG[SNAP_MOUNT_DIR]}
		exit 1
	}
fi

if [ -d "$TDIR" ] ; then
	omsg -e "\tFAIL: Snapshot target directory '$TDIR' already exists!"
	cd $TBASE
	omsg -e "\t`ls -ld $SNAME`"
	omsg "Cannot create snapshot '$FREQ/$SNAME'."
	exit 1
fi

# for now, delete oldest then make new snapshot
# should really delete in a loop until below MSC - recovery
# from oversnapping condition
SNAPNAMES=`echo ${TBASE}/*`
if [ "$SNAPNAMES" = "${TBASE}/*" ] ; then
	SNAPNAMES=
fi
if [ `wc -w <<<"$SNAPNAMES"` -ge "$MAX_SCNT" ] ; then

	# remove oldest first
	OLDSNAP=`\ls $TBASE | head -1`

	omsg "Deleting:"
	omsg -e "\tReached max snap count ($MAX_SCNT) for '$NSRC' '$FREQ', hence"

	MTMP=`_ssched_mktemp msc.snap.del.$NSRC.$FREQ.$OLDSNAP`

	#echo "btrfs sub del -c $TBASE/$OLDSNAP" | sed 's/^/\t/' > $MTMP
	btrfs sub del -c "$TBASE/$OLDSNAP" 2>&1 | sed 's/^/\t/' > $MTMP

	ES=${PIPESTATUS[0]}
	if [ "$ES" -ne 0 ] ; then
		omsg -e "\tFAILure deleting the oldest snapshot '$TBASE/$OLDSNAP': $ES"
		omsg < $MTMP
		_ssched_umount_rootvol ${CONFIG[SNAP_MOUNT_DIR]}
		_ssched_rmtemp $MTMP
		exit $ES
	fi
	omsg < $MTMP
	# output a blank line for formatting
	omsg ""
	_ssched_rmtemp $MTMP
fi

# snap it
omsg "Snapping: '${SSRC#${CONFIG[SNAP_MOUNT_DIR]}/}' -> '$FREQ/$SNAME'"

# pause databases
_ssched_pause_dbs $NSRC
PES=$?

MTMP=`_ssched_mktemp sub.snap.$NSRC.$FREQ.$SNAME`

btrfs sub snap -r "$SSRC" "$TDIR" 2>&1 | sed 's/^/\t/' >$MTMP

ES=${PIPESTATUS[0]}

# if [ "$PES" -eq 0 ] ; then
	# unpause databases
	_ssched_unpause_dbs $NSRC
# fi

if [ "$ES" -ne 0 ] ; then
	omsg "Some sort of failure creating snapshot '$FREQ/${DATESTR}_${INTSTR}'"
fi
omsg <$MTMP

_ssched_rmtemp $MTMP

_ssched_umount_rootvol ${CONFIG[SNAP_MOUNT_DIR]}

# do backups if this filesystem is configed for backup for at least this int

BINT="${CONFIG[SSRC_$NSRC%BACKUPINT]}"

if [ \( "$ES" -eq 0 \) -a "$BINT" ] ; then
	# bail here if this interval is less than the min backup interval
	if grep -qs "$FREQ" <<<"${LESSER_INTS[$BINT]}" ; then
		# don't fire backups on this interval
		exit $ES
	fi
	omsg -e "\n"
	omsg -n "Backup job for ${NSRC}: "
	echo "$PRE/lib/snapsched/snapback $NSRC" |
		at "now + 5 minutes" 2>&1 | grep -v /bin/sh | omsg
fi

exit $ES
