diff options
Diffstat (limited to 'handlers/rdiff.in')
-rw-r--r-- | handlers/rdiff.in | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/handlers/rdiff.in b/handlers/rdiff.in new file mode 100644 index 0000000..0f93429 --- /dev/null +++ b/handlers/rdiff.in @@ -0,0 +1,257 @@ +# -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*- +# +# rdiff-backup handler script for backupninja +# requires rdiff-backup +# + +### FUNCTIONS ### + +function test_connection() { + # given a user and host, + # tests the connection. + # if user or host is missing, returns 0 + # (ie, assume it's a local connection). + if [ $# -lt 2 ]; then + debug "(local is assumed to be a good connection)" + return 0 + fi + local user=$1 + local host=$2 + debug "ssh $sshoptions -o PasswordAuthentication=no $host -l $user 'echo -n 1'" + local ret=`ssh $sshoptions -o PasswordAuthentication=no $host -l $user 'echo -n host is alive'` + if echo $ret | grep "host is alive"; then + debug "Connected to $host as $user successfully" + else + fatal "Can't connect to $host as $user." + fi +} + +function get_version() { + # given no arguments, returns the local version. + # given a user and host, returns the remote version. + # if user or host is missing, returns the local version. + if [ "$#" -lt 2 ]; then + debug "$RDIFFBACKUP -V" + echo `$RDIFFBACKUP -V` + else + local user=$1 + local host=$2 + debug "ssh $sshoptions $host -l $user '$RDIFFBACKUP -V'" + echo `ssh $sshoptions $host -l $user "$RDIFFBACKUP -V | grep rdiff-backup"` + fi +} + +function check_consistency() { + local section=$1 + local type=$2 + local user=$3 + local host=$4 + if [ "$type" == "local" ]; then + if [ "$user" != "" ]; then + warning "User should not be specified for local $section." + fi + if [ "$host" != "" ]; then + warning "Host should not be specified for local $section." + fi + fi + if [ "$type" == "remote" ]; then + if [ "$user" == "" ]; then + fatal "User must be specified for remote $section." + fi + if [ "host" == "" ]; then + fatal "Host must be specifed for remote $section." + fi + fi +} + +function check_cstream() { + local cstream=$1 + if [ ! -x $cstream ]; then + fatal "Can't find your cstream binary (trying: $cstream). If you use bwlimit you must have cstream installed." + fi +} + +### GET CONFIG ### + +getconf options +getconf testconnect yes +getconf nicelevel 0 +getconf bwlimit +getconf ignore_version no + +setsection source +getconf type; sourcetype=$type +getconf user; sourceuser=$user +getconf host; sourcehost=$host +check_consistency "source" "$type" "$user" "$host" +getconf label +getconf keep 60 +getconf include +getconf vsnames all +getconf vsinclude +getconf exclude + +setsection dest +getconf directory; destdir=$directory +# strip trailing / +destdir=${destdir%/} +getconf type; desttype=$type +getconf user; destuser=$user +getconf host; desthost=$host +getconf sshoptions +check_consistency "destination" "$type" "$user" "$host" + +if [ -n "$sshoptions" ] && echo $options | grep -qv "remote-schema"; then + options="$options --remote-schema 'ssh -C $sshoptions %s rdiff-backup --server'" +fi + +### CHECK CONFIG ### + +# If vservers are configured, check that the ones listed in $vsnames do exist. +local usevserver=no +if [ $vservers_are_available = yes ]; then + if [ "$vsnames" = all ]; then + vsnames="$found_vservers" + else + if ! vservers_exist "$vsnames" ; then + fatal "At least one of the vservers listed in vsnames ($vsnames) does not exist." + fi + fi + if [ -n "$vsinclude" ]; then + info "Using vservers '$vsnames'" + usevserver=yes + fi +else + [ -z "$vsinclude" ] || warning 'vservers support disabled in backupninja.conf, vsincludes configuration lines will be ignored' +fi + +# check the connection at the source and destination +[ -n "$test" ] || test=0 +if [ "$testconnect" = "yes" ] || [ "${test}" -eq 1 ]; then + test_connection $sourceuser $sourcehost + test_connection $destuser $desthost +fi + +if [ "$ignore_version" != "yes" ]; then + # see that rdiff-backup has the same version at the source and destination + sourceversion=`get_version $sourceuser $sourcehost` + destversion=`get_version $destuser $desthost` + if [ "$sourceversion" != "$destversion" ]; then + fatal "rdiff-backup does not have the same version at the source and at the destination." + fi +fi + +# source specific checks +case $sourcetype in + remote ) execstr_sourcepart="$sourceuser@$sourcehost::/" ;; + local ) execstr_sourcepart="/" ;; + * ) fatal "sourcetype '$sourcetype' is neither local nor remote" ;; +esac + +# destination specific checks +[ "$destdir" != "" ] || fatal "Destination directory not set" +case $desttype in + remote ) execstr_destpart="$destuser@$desthost::$destdir/$label" ;; + local ) execstr_destpart="$destdir/$label" ;; + * ) fatal "desttype '$desttype' is neither local nor remote" ;; +esac + +### REMOVE OLD BACKUPS ### + +if [ "$keep" != yes ]; then + + if [ "`echo $keep | tr -d 0-9`" == "" ]; then + # add D if no other date unit is specified + keep="${keep}D" + fi + + removestr="$RDIFFBACKUP $options --force --remove-older-than $keep " + if [ "$desttype" == "remote" ]; then + removestr="${removestr}${destuser}@${desthost}::" + fi + removestr="${removestr}${destdir}/${label}"; + + debug "$removestr" + if [ $test = 0 ]; then + output="`su -c "$removestr" 2>&1`" + if [ $? = 0 ]; then + debug $output + info "Removing backups older than $keep days succeeded." + else + warning $output + warning "Failed removing backups older than $keep." + fi + fi + +fi + +# Add cstream + +if [ ! -z $bwlimit ]; then + check_cstream $CSTREAM; + if [ "$desttype" = "remote" ]; then + RDIFFBACKUP="$RDIFFBACKUP --remote-schema 'cstream -t $bwlimit | ssh %s \''rdiff-backup --server\'''" + elif [ "$sourcetype" = "remote" ]; then + RDIFFBACKUP="$RDIFFBACKUP --remote-schema 'ssh %s \''rdiff-backup --server\'' | cstream -t $bwlimit'" + else + fatal "You specified a bandwidth limit but neither your source nor destination types are remote." + fi +fi + +### EXECUTE ### + +execstr="$RDIFFBACKUP $options --print-statistics " + +set -o noglob + +symlinks_warning="Maybe you have mixed symlinks and '*' in this statement, which is not supported." + +# TODO: order the includes and excludes +# excludes +for i in $exclude; do + str="${i//__star__/*}" + execstr="${execstr}--exclude '$str' " +done +# includes +for i in $include; do + [ "$i" != "/" ] || fatal "Sorry, you cannot use 'include = /'" + str="${i//__star__/*}" + execstr="${execstr}--include '$str' " +done + +# vsinclude +if [ $usevserver = yes ]; then + for vserver in $vsnames; do + for vi in $vsinclude; do + str="${vi//__star__/*}" + str="$VROOTDIR/$vserver$str" + if [ -n "$str" ]; then + execstr="${execstr}--include '$str' " + else + warning "vsinclude statement '${vi//__star__/*}' will be ignored for VServer $vserver. $symlinks_warning" + fi + done + done +fi + +set +o noglob + +# exclude everything else +[ "$include" != "" -o "$vsinclude" != "" ] && execstr="${execstr}--exclude '/*' " + +# include client-part and server-part +execstr="${execstr}$execstr_sourcepart $execstr_destpart" + +debug "$execstr" +if [ $test = 0 ]; then + output=`nice -n $nicelevel su -c "$execstr" 2>&1` + if [ $? = 0 ]; then + debug $output + info "Successfully finished backing up source $label" + else + warning $output + warning "Failed backup up source $label" + fi +fi + +return 0 |