#!/usr/bin/env sh nodes_file="nodes.txt" ### nodes.txt # # # # ... datasets_file="datasets.txt" ### datasets.txt # # / # / # / # # ... list_active_datasets() { zfs list | tail -n +2 | cut -d' ' -f1|grep ${BR_ROOT} } read_datasets() { while read BR_REMOTE_ADDR BR_REMOTE_PORT BR_REMOTE_ROOT BR_REMOTE_USER; do case $BR_REMOTE_ADDR in \#*) continue;; esac if [ $BR_TEST_MODE = "TRUE" ]; then echo zfs send -R ${BR_ROOT}@${BR_NEW_SNAPSHOT} echo ssh -i ~/.ssh/id_rsa -o port=${BR_REMOTE_PORT} \ ${BR_REMOTE_USER}@${BR_REMOTE_ADDR} \ zfs receive -vu ${BR_REMOTE_ROOT} else zfs send -R ${BR_ROOT}@${BR_NEW_SNAPSHOT} | ssh -i ~/.ssh/id_rsa -o port=${BR_REMOTE_PORT} \ ${BR_REMOTE_USER}@${BR_REMOTE_ADDR} \ zfs receive -dvu ${BR_REMOTE_ROOT} fi done < ${datasets_file} } # compare_datasets() create_datasets() { # should compare_datasets and only create missing or possibly error. for dataset in `cat ${datasets_file}`; do zfs create -p ${BR_ROOT}/$dataset done } get_latest_snapshot() { zfs list -t snapshot | grep ${BR_ROOT} | tail -n1 | cut -d'@' -f2 | cut -d' ' -f 1 } setup_aggregator() { zfs allow -u ${BR_USER} send,snapshot,hold ${BR_ROOT} create_datasets } setup_mirror() { zfs create -p $BR_ROOT create_datasets zfs allow -u ${BR_USER} send,snapshot,hold ${BR_ROOT} zfs allow -u ${BR_USER} \ compression,mountpoint,receive,create,mount ${BR_ROOT} } create_snapshot() { id="`date -I`-`date +%s`" if [ $BR_TEST_MODE = "TRUE" ]; then echo zfs snapshot -r ${BR_ROOT}@${id} else zfs snapshot -r ${BR_ROOT}@${id} fi } send_single_snapshot() { BR_NEW_SNAPSHOT=`get_latest_snapshot` tail -n +2 ${nodes_file} > sendnodes.tmp while read BR_REMOTE_ADDR BR_REMOTE_PORT BR_REMOTE_ROOT BR_REMOTE_USER; do case $BR_REMOTE_ADDR in \#*) continue;; esac if [ $BR_TEST_MODE = "TRUE" ]; then echo zfs send -R ${BR_ROOT}@${BR_NEW_SNAPSHOT} echo ssh -i ~/.ssh/id_rsa -o port=${BR_REMOTE_PORT} \ ${BR_REMOTE_USER}@${BR_REMOTE_ADDR} \ zfs receive -vu ${BR_REMOTE_ROOT} else zfs send -R ${BR_ROOT}@${BR_NEW_SNAPSHOT} | ssh -i ~/.ssh/id_rsa -o port=${BR_REMOTE_PORT} \ ${BR_REMOTE_USER}@${BR_REMOTE_ADDR} \ zfs receive -dvu ${BR_REMOTE_ROOT} fi done < sendnodes.tmp rm sendnodes.tmp if [ $BR_TEST_MODE = "TRUE" ]; then : else echo $BR_NEW_SNAPSHOT > "old-snapshot.txt" fi } send_incremental_snapshot() { BR_NEW_SNAPSHOT=`get_latest_snapshot` echo Will send $BR_NEW_SNAPSHOT #while read BR_REMOTE_ADDR BR_REMOTE_PORT BR_REMOTE_ROOT BR_REMOTE_USER; do # zfs send -R -i `cat old-snapshot.txt` ${BR_ROOT}@${BR_NEW_SNAPSHOT} | # ssh -i ~/.ssh/id_rsa -o port=${BR_REMOTE_PORT} \ # ${BR_REMOTE_USER}@${BR_REMOTE_ADDR} \ # zfs receive -dvu ${BR_REMOTE_ROOT}@${BR_NEW_SNAPSHOT} #done echo $BR_NEW_SNAPSHOT > "old-snapshot.txt" } ################################### MAIN #################################### ### Options set -- `getopt "tl:" "$@"` || { echo "Usage: `basename $0` [-tl] [command]" 1>&2 exit 1 } BR_TEST_MODE=FALSE while :; do case "$1" in -t) BR_TEST_MODE=TRUE echo Test mode. ;; --) shift; break ;; esac shift done read BR_HOST BR_PORT BR_ROOT BR_USER < ${nodes_file} if [ ! -f ${nodes_file} ]; then echo "No nodes specified."; exit 2; fi ### Command case "$1" in list) list_active_datasets ;; create) create_snapshot ;; setup-mirror) setup_mirror ;; send) if [ -f "old-snapshot.txt" ]; then send_incremental_snapshot else send_single_snapshot fi ;; esac