FAQ | This is a LIVE service | Changelog

Commit 3d245d54 authored by Dr Adam Thorn's avatar Dr Adam Thorn
Browse files

Add script to move a backup to another server

i.e. send the ZFS, update db records and copy the config files. The
sql inserts should broadly mirror those done when setting up a new
backup, though with field values matching those in the source database
rather than just using the defaults.

This script has so only been tested for the case of moving a "simple"
backup where a host has a single backup task and no special config.
It's quite likely there'll be bugs to fix for other cases that
we'll find in due course.
parent 56a40eed
#!/bin/bash
# To move a machine onto a new ZFS
# Load some settings
. /etc/default/zfs-backup
# To move a machine from one zpool to another
function dosql_local() {
SQL="$1"
psql -A -t -c "$SQL"
}
function dosql_remote() {
SQL="$1"
psql -A -h $NEW_SERVER -t -c "$SQL"
}
function cmd_remote() {
CMD="$1"
ssh root@$NEW_SERVER $CMD
}
function create_host_record() {
FQDN=$1
# NB we start with offline=t,disabled=t whilst we migrate the backup.
HOSTID=`dosql_remote "
insert into host (hostname, offline, disabled) values ('$FQDN',true,true);
select host_id from host where hostname='$FQDN';"`
echo $HOSTID
}
function backuptask() {
HOSTID=$1
TASKNAME="$2"
TARGET=$3
SOURCEDIR=$4
SOFT=$5
HARD=$5
if [ -z "$SOFT" ]; then
SOFT=14400
fi
if [ -z "$HARD" ]; then
HARD=86400
fi
BTID=`dosql_remote "
insert into backup_task(host_id,backup_task_name,timeout_soft,timeout_hard,zfs_target,backup_type_id) values
($HOSTID,'$TASKNAME',$SOFT,$HARD,'$TARGET',3);
insert into zfs_rsync_detail (backup_task_id,directory_source) values
((select backup_task_id from backup_task where zfs_target='$TARGET' and host_id=$HOSTID),'$SOURCEDIR');
select backup_task_id from backup_task natural join host natural join zfs_rsync_detail where hostname='$FQDN' and directory_source='$SOURCEDIR' and backup_type_id=3;"`
echo $BTID
}
function configure_pruning() {
CURRENT_TASK_ID=$1
NEW_TASK_ID=$2
PRUNING_IDS=$(dosql_local "select zfs_pruning_id from zfs_pruning where backup_task_id=$CURRENT_TASK_ID")
for PRUNING_ID in $PRUNING_IDS; do
PRUNING_AGE=$(dosql_local "select zfs_pruning_age from zfs_pruning where zfs_pruning_id=$PRUNING_ID")
PRUNING_COUNT=$(dosql_local "select zfs_pruning_count from zfs_pruning where zfs_pruning_id=$PRUNING_ID")
FLAGNAME=$(dosql_local "select flagname from zfs_pruning where zfs_pruning_id=$PRUNING_ID")
dosql_remote "insert into zfs_pruning (backup_task_id, zfs_pruning_age,zfs_pruning_count,flagname) values
($NEW_TASK_ID, $PRUNING_AGE, $PRUNING_COUNT, '$FLAGNAME')"
done
}
if [ $# -lt 2 ] ; then
echo Usage: $0 backup_target_fqdn new_backup_server [zpool_name]
echo Moves the named machine to a new server
exit 1
fi
HN=$1
# Find FQDN for $HN
FQDN=`getent hosts $HN | awk ' { print $2 } '`
NEW_SERVER=$2
ZPOOL_TARGET=$3
# Which zfs is it already on?
echo Finding source ZFS for $FQDN
SOURCES=`zfs list -H -o name | grep -v zroot | grep /$FQDN$ | sed "sZ/'$FQDN$'ZZ" | wc -l `
#echo Found $SOURCES possibilities
if [ $SOURCES != 1 ] ;then
echo Found more than one possible ZFS for $HN
exit 2
fi
if ! grep -q ^$NEW_SERVER: $PGPASSFILE ; then
echo $NEW_SERVER not found in $PGPASSFILE \(use fqdn?\)
exit 5
fi
SOURCE=`zfs list -H -o name | grep -v zroot | grep /$FQDN$ | sed "sZ/$FQDN\\$ZZ"`
# Which target is it?
if [ -z "$ZPOOL_TARGET" ] ; then
echo Finding a target ZFS automatically
ZPOOL=$(cmd_remote "zfs list -H -oname -S avail -d0 | grep -v zroot | head -n1")
ZPOOL_TARGET=$ZPOOL
fi
if ! ssh root@$NEW_SERVER zpool list $ZPOOL_TARGET &>/dev/null ; then
echo $ZPOOL_TARGET does not exist on $NEW_SERVER
exit 3
fi
echo moving $FQDN from $SOURCE to $ZPOOL_TARGET on $NEW_SERVER
set -e
RUNNING=`dosql_local "select count(*) from backup_log natural join backup_task natural join host where hostname='$FQDN' and ended_processing is null and started_processing is not null"`
RUNNING=`echo $RUNNING` # chomp
#echo RUNNING $RUNNING
if ! [ "$RUNNING" = 0 ] ; then
echo $FQDN has a job running
exit 3
fi
# Disable this host locally
dosql_local "update host set disabled='t' where hostname='$FQDN';"
# De-queue jobs for this host
dosql_local "delete from backup_log where backup_task_id in (select backup_task_id from backup_task natural join host where hostname='$FQDN') and ended_processing is null and started_processing is null;"
# Move ZFS
NOW=$(date +%s)
zfs snapshot -r $SOURCE/$FQDN@$NOW
zfs hold zfs-moving $SOURCE/$FQDN@$NOW
SIZE=`zfs list -H -o used $SOURCE/$FQDN`
echo Sending ZFS [ $SIZE]
zfs send -R $SOURCE/$FQDN@$NOW | mbuffer | ssh root@$NEW_SERVER zfs receive $ZPOOL_TARGET/$FQDN
CURRENT_HOST_ID=$(dosql_local "select host_id from host where hostname='$FQDN'")
NEW_HOST_ID=$(create_host_record $FQDN)
# get current tasks
TASK_IDS=$(dosql_local "select backup_task_id from backup_task where host_id='$CURRENT_HOST_ID'")
# create new tasks
for TASK_ID in $TASK_IDS; do
echo got task $TASK_ID
SOURCEDIR=$(dosql_local "select directory_source from zfs_rsync_detail where backup_task_id='$TASK_ID'")
SOFT=$(dosql_local "select timeout_soft from backup_task where backup_task_id='$TASK_ID'")
HARD=$(dosql_local "select timeout_hard from backup_task where backup_task_id='$TASK_ID'")
CURRENT_ZFS_TARGET=$(dosql_local "select zfs_target from backup_task where backup_task_id='$TASK_ID'")
NEW_ZFS_TARGET=${ZPOOL_TARGET}/$(echo $CURRENT_ZFS_TARGET | cut -d '/' -f 2-)
NEW_TASK_ID=$(backuptask $NEW_HOST_ID "$TASKNAME" $NEW_ZFS_TARGET $SOURCEDIR $SOFT $HARD)
configure_pruning $TASK_ID $NEW_TASK_ID
scp /etc/chem-zfs-backup-server/zfs-rsync.d/${FQDN}_${SOURCEDIR//\//.} $NEW_SERVER:/etc/chem-zfs-backup-server/zfs-rsync.d
done
dosql_remote "update host set disabled='f',offline='f' where host_id=$NEW_HOST_ID"
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment