#!/bin/bash # Author: Alan Pippin # Description: This script "restores" or sends a local filesystem to a remote zfs pool. # Usage: zfs-restore # source our configuration config="${0%/*}/zfs-scripts.conf" [ -e "${config}.dist" ] && . ${config}.dist [ -e "${config}" ] && . ${config} # command line arg parsing src_pool=$1 src_fs=$2 dst_pool=$3 dst_fs=$4 dst_hostname=$5 if [[ -z "$SCRIPT_UNDER_TEST" ]]; then exec >> $logdir/zfs-restore.log 2>&1 fi fatal_and_exit() { echo -e 2>&1 "$1" exit 1 } trap fatal_and_exit INT # Make sure we have valid arguments if [[ -z "$src_pool" ]] || [[ -z "$src_fs" ]] || [[ -z "$dst_pool" ]] || [[ -z "$dst_fs" ]] || [[ -z "$dst_hostname" ]]; then fatal_and_exit "Usage: $0 " fi date=`date` echo "$date ZFS restore started: $src_pool/$src_fs -> $dst_hostname:$dst_pool/$dst_fs" # Make sure the src pool and src filesystem exist, or print some errors zpool list -H "$src_pool" >/dev/null 2>&1 if [ $? != 0 ]; then fatal_and_exit "-E- The src pool, '$src_pool' doesn't seem to exist." fi zfs list "$src_pool/$src_fs" >/dev/null 2>&1 if [ $? != 0 ]; then fatal_and_exit "-E- The src filesystem for the src pool, '$src_pool/$src_fs' doesn't seem to exist." fi # Obtain the zpool guid for the src pool src_pool_guid=`zpool get guid $src_pool 2>&1 | grep $src_pool | awk '{ print $3 }'` zpool get guid $src_pool > /dev/null 2>&1 if [ $? != 0 ]; then fatal_and_exit "-E- Unable to extract the guid for the src pool: $src_pool" $mailto fi # Setup our backup marker names last_backup_marker=${src_fs}@previous-backup-${src_pool_guid} # Check to make sure the src fs exists $zfs list -t snapshot "$src_pool/$last_backup_marker" > /dev/null 2>&1 if [ $? != 0 ]; then fatal_and_exit "-E- The src snapshot '$src_pool/$last_backup_marker' does not exist. Unable to continue." fi # Check to make sure the dst pool exists ssh $dst_hostname "$zfs list ${dst_pool}" > /dev/null 2>&1 if [ $? != 0 ]; then fatal_and_exit "-E- The destination pool '$dst_pool' does not exist. Create the pool '$dst_pool' and try again." fi # Check to make sure the dst filesystem does not exist ssh $dst_hostname "$zfs list ${dst_pool}/${dst_fs}" > /dev/null 2>&1 if [ $? == 0 ]; then fatal_and_exit "-E- The destination pool/filesystem '$dst_pool/$dst_fs' already exists. Destroy the filesystem '$dst_fs' and try again." fi # Now send the src filesystem if [[ -n "$SCRIPT_UNDER_TEST" ]]; then echo "$zfs send -R $src_pool/$last_backup_marker | ssh $dst_hostname $zfs recv -dv $dst_pool" else if [[ $throttle_enable == 1 && -e $throttle ]]; then $zfs send -R "$src_pool/$last_backup_marker" | $throttle $throttle_opt | ssh $dst_hostname "$zfs recv -dv $dst_pool" else $zfs send -R "$src_pool/$last_backup_marker" | ssh $dst_hostname "$zfs recv -dv $dst_pool" fi fi # Now rename the dst filesystem (move it into place) if [[ -n "$SCRIPT_UNDER_TEST" ]]; then echo "$dst_hostname $zfs rename $dst_pool/$src_fs $dst_pool/$dst_fs" else ssh $dst_hostname "$zfs rename $dst_pool/$src_fs $dst_pool/$dst_fs" fi # All done! date=`date` echo "$date ZFS restore completed: $src_pool/$src_fs -> $dst_hostname:$dst_pool/$dst_fs"