FAQ | This is a LIVE service | Changelog

Skip to content
Snippets Groups Projects
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
No related branches found
No related tags found
No related merge requests found
#!/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"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment