]> gitweb.fluxo.info Git - puppet-backup.git/commitdiff
Updating rsync handler from upstream rsync handler development
authorSilvio Rhatto <rhatto@riseup.net>
Fri, 11 May 2012 00:33:14 +0000 (21:33 -0300)
committerSilvio Rhatto <rhatto@riseup.net>
Fri, 11 May 2012 00:33:14 +0000 (21:33 -0300)
files/handlers/rsync

index e098a84cbfb9b18249a64767404096574ac65f8f..01a2987ab9a197c6401c4d3554a7fffecbfc93cb 100644 (file)
@@ -39,7 +39,6 @@
 #   keepdaily = for long storage format, specify the number of daily backup increments
 #   keepweekly = for long storage format, specify the number of weekly backup increments
 #   keepmonthly = for long storage format, specify the number of monthly backup increments
-#   lockfile = lockfile to be kept during backup execution
 #   nicelevel = rsync command nice level
 #   enable_mv_timestamp_bug = set to "yes" if your system isnt handling timestamps correctly
 #   tmp = temp folder
@@ -60,7 +59,7 @@
 #   exclude_vserver = vserver-name (valid only if vservers = yes on backupninja.conf)
 #   numericids = when set to 1, use numeric ids instead of user/group mappings on rsync
 #   compress = if set to 1, compress data on rsync (remote source only)
-#   bandwidthlimit = set a badnwidth limit in KB/s (remote source only)
+#   bandwidthlimit = set a bandwidth limit in KB/s (remote source only)
 #   remote_rsync = remote rsync program (remote source only)
 #   id_file = ssh key file (remote source only)
 #   batch = set to "yes" to rsync use a batch file as source
@@ -79,7 +78,7 @@
 #   port = remote port number (remote destination only)
 #   user = remote user name (remote destination only)
 #   id_file = ssh key file (remote destination only)
-#   bandwidthlimit = set a badnwidth limit in KB/s (remote destination only)
+#   bandwidthlimit = set a bandwidth limit in KB/s (remote destination only)
 #   remote_rsync = remote rsync program (remote dest only)
 #   batch = set to "yes" to rsync write a batch file from the changes
 #   batchbase = folder where the batch file should be written
@@ -125,11 +124,10 @@ function eval_config {
   getconf mountpoint
   getconf backupdir
   getconf format short
-  getconf days
+  getconf days 7
   getconf keepdaily 5
   getconf keepweekly 3
   getconf keepmonthly 1
-  getconf lockfile
   getconf nicelevel 0
   getconf enable_mv_timestamp_bug no
   getconf tmp /tmp
@@ -176,7 +174,7 @@ function eval_config {
   getconf include
   getconf exclude
   getconf exclude_vserver
-  getconf numericids
+  getconf numericids 0
   getconf compress 0
   
   # dest section
@@ -217,7 +215,7 @@ function eval_config {
     fi
   fi
 
-  getconf numericids
+  getconf numericids 0
   getconf compress 0
   
   # services section
@@ -230,19 +228,16 @@ function eval_config {
 
   if [ "$dest" != "local" ] && [ "$from" == "remote" ]; then
     fatal "When source is remote, destination should be local."
-    exit 1
   fi
 
   if [ "$from" != "local" ] && [ "$from" != "remote" ]; then
     fatal "Invalid source $from"
-    exit 1
   fi
 
   backupdir="$mountpoint/$backupdir"
 
   if [ "$dest" == "local" ] && [ ! -d "$backupdir" ]; then 
-    error "Backupdir $backupdir does not exist"
-    exit 1
+    fatal "Backupdir $backupdir does not exist"
   fi
 
   if [ ! -z "$log" ]; then
@@ -280,9 +275,7 @@ function eval_config {
     mv=move_files
   fi
 
-  for path in $exclude; do
-    excludes="$excludes --exclude=$path"
-  done
+  excludes=`echo "$exclude" | sed -e "s/^/--exclude='/g" -e "s/ /' --exclude='/g" -e "s/$/'/"`
 
   # Make sure we'll run bash at the destination
   ssh_cmd="$ssh_cmd /bin/bash"
@@ -376,7 +369,7 @@ function rotate_short_remote {
       echo "Debug: removing orphaned metadata \$file"
       rm -rf $metadata/\$file
     fi
-  done  
+  done
   ##### END REMOTE SCRIPT #######
 EOF
 ) | (while read a; do passthru $a; done)
@@ -397,8 +390,8 @@ function rotate_long {
   local metadata
 
   if [ ! -d "$backuproot" ]; then
-    echo "Debug: skipping rotate of $backuproot as it doesn't exist."
-    exit
+    warning "Skipping rotate of $backuproot as it doesn't exist."
+    return
   fi
 
   for rottype in daily weekly monthly; do
@@ -411,7 +404,7 @@ function rotate_long {
       echo "Debug: $dir.1 does not exist, skipping."
       continue 1
     elif [ ! -f $metadata.1/created ] && [ ! -f $metadata.1/rotated ]; then
-      echo "Warning: metadata does not exist for $dir.1. This backup may be only partially completed. Skipping rotation."
+      warning "Warning: metadata does not exist for $dir.1. This backup may be only partially completed. Skipping rotation."
       continue 1
     fi
     
@@ -427,11 +420,16 @@ function rotate_long {
         else
           created=0
         fi
+        # Validate created date
+        if [ -z "$created" ] || echo $created | grep -v -q -e '^[0-9]*$'; then
+           warning "Invalid metadata $created. Skipping rotation."
+           break
+        fi
         cutoff_time=$(( now - (seconds*(i-1)) ))
         if [ ! $created -gt $cutoff_time ]; then
           next=$(( i + 1 ))
           if [ ! -d $dir.$next ]; then
-            echo "Debug: $rottype.$i --> $rottype.$next"
+            debug "$rottype.$i --> $rottype.$next"
             $nice mv $dir.$i $dir.$next
             mkdir -p $metadata.$next
             date +%c%n%s > $metadata.$next/rotated
@@ -439,10 +437,10 @@ function rotate_long {
               $nice mv $metadata.$i/created $metadata.$next
             fi
           else
-            echo "Debug: skipping rotation of $dir.$i because $dir.$next already exists."
+            debug "skipping rotation of $dir.$i because $dir.$next already exists."
           fi
         else
-          echo "Debug: skipping rotation of $dir.$i because it was created" $(( (now-created)/86400)) "days ago ("$(( (now-cutoff_time)/86400))" needed)."
+          debug "skipping rotation of $dir.$i because it was created" $(( (now-created)/86400)) "days ago ("$(( (now-cutoff_time)/86400))" needed)."
         fi
       fi
     done
@@ -450,9 +448,11 @@ function rotate_long {
 
   max=$((keepdaily+1))
   if [ $keepweekly -gt 0 -a -d $backuproot/daily.$max -a ! -d $backuproot/weekly.1 ]; then
-    echo "Debug: daily.$max --> weekly.1"
+    debug "daily.$max --> weekly.1"
     $nice mv $backuproot/daily.$max $backuproot/weekly.1
     mkdir -p $backuproot/metadata/weekly.1
+    # Update increment folder date and setup metadata
+    $touch $backuproot/weekly.1
     date +%c%n%s > $backuproot/metadata/weekly.1/rotated
     #if [ -f $backuproot/metadata/daily.$max/created  ]; then
     #   $nice mv $backuproot/metadata/daily.$max/created $backuproot/metadata/weekly.1/
@@ -461,9 +461,11 @@ function rotate_long {
 
   max=$((keepweekly+1))
   if [ $keepmonthly -gt 0 -a -d $backuproot/weekly.$max -a ! -d $backuproot/monthly.1 ]; then
-    echo "Debug: weekly.$max --> monthly.1"
+    debug "weekly.$max --> monthly.1"
     $nice mv $backuproot/weekly.$max $backuproot/monthly.1
     mkdir -p $backuproot/metadata/monthly.1
+    # Update increment folder date and setup metadata
+    $touch $backuproot/monthly.1
     date +%c%n%s > $backuproot/metadata/monthly.1/rotated
     #if [ -f $backuproot/metadata/weekly.$max/created  ]; then
     #   $nice mv $backuproot/metadata/weekly.$max/created $backuproot/metadata/weekly.1/
@@ -479,10 +481,10 @@ function rotate_long {
     for (( i=$oldest; i >= $max; i-- )); do
       if [ -d $dir.$i ]; then
         if [ -d $backuproot/rotate.tmp ]; then
-          echo "Debug: removing rotate.tmp"
+          debug "removing rotate.tmp"
           $nice rm -rf $backuproot/rotate.tmp
         fi
-        echo "Debug: moving $rottype.$i to rotate.tmp"
+        debug "moving $rottype.$i to rotate.tmp"
         $nice mv $dir.$i $backuproot/rotate.tmp
       fi
     done
@@ -515,7 +517,7 @@ function rotate_long_remote {
   now=\`date +%s\`
 
   if [ ! -d "$backuproot" ]; then
-    echo "Debug: skipping rotate of $backuproot as it doesn't exist."
+    echo "Fatal: skipping rotate of $backuproot as it doesn't exist."
     exit
   fi
 
@@ -545,6 +547,11 @@ function rotate_long_remote {
         else
           created=0
         fi
+        # Validate created date
+        if [ -z "\$created" ] || echo \$created | grep -v -q -e '^[0-9]*$'; then
+           echo "Warning: Invalid metadata \$created. Skipping rotation."
+           break
+        fi
         cutoff_time=\$(( now - (seconds*(i-1)) ))
         if [ ! \$created -gt \$cutoff_time ]; then
           next=\$(( i + 1 ))
@@ -571,6 +578,8 @@ function rotate_long_remote {
     echo "Debug: daily.\$max --> weekly.1"
     $nice mv $backuproot/daily.\$max $backuproot/weekly.1
     mkdir -p $backuproot/metadata/weekly.1
+    # Update increment folder date and setup metadata
+    $touch $backuproot/weekly.1
     date +%c%n%s > $backuproot/metadata/weekly.1/rotated
     #if [ -f $backuproot/metadata/daily.\$max/created  ]; then
     #   $nice mv $backuproot/metadata/daily.\$max/created $backuproot/metadata/weekly.1/
@@ -582,6 +591,8 @@ function rotate_long_remote {
     echo "Debug: weekly.\$max --> monthly.1"
     $nice mv $backuproot/weekly.\$max $backuproot/monthly.1
     mkdir -p $backuproot/metadata/monthly.1
+    # Update increment folder date and setup metadata
+    $touch $backuproot/monthly.1
     date +%c%n%s > $backuproot/metadata/monthly.1/rotated
     #if [ -f $backuproot/metadata/weekly.\$max/created  ]; then
     #   $nice mv $backuproot/metadata/weekly.\$max/created $backuproot/metadata/weekly.1/
@@ -642,22 +653,19 @@ function setup_long_dirs {
     if [ -d $tmpdir ]; then
       mv $tmpdir $dir.1
       if [ $? == 1 ]; then
-        echo "Fatal: could mv $destdir/rotate.tmp $dir.1 on host $host"
-        exit 1
+        fatal "Could not move $tmpdir to $dir.1 on host $host"
       fi
     else
       mkdir --parents $dir.1
       if [ $? == 1 ]; then
-        echo "Fatal: could not create directory $dir.1 on host $host"
-        exit 1
+        fatal "Could not create directory $dir.1 on host $host"
       fi
     fi
     if [ -d $dir.2 ]; then
       echo "Debug: update links $backuptype.2 --> $backuptype.1"
       cp -alf $dir.2/. $dir.1
       #if [ $? == 1 ]; then
-      #  echo "Fatal: could not create hard links to $dir.1 on host $host"
-      #  exit 1
+      #  fatal "Could not create hard links to $dir.1 on host $host"
       #fi
     fi
   fi
@@ -758,7 +766,6 @@ function prepare_storage {
       btype=monthly
     else
       fatal "keeping no backups";
-      exit 1
     fi
 
     suffix="$btype.1"
@@ -777,7 +784,6 @@ function prepare_storage {
     suffix=""
   else
     fatal "Invalid backup format $format"
-    exit 1
   fi
 
 }
@@ -821,7 +827,6 @@ function set_batch_mode {
       batch_option="--read-batch=$batch_file"
     else
       fatal "Batch file not found: $batch_file"
-      exit 1
     fi
   elif [ "$batch" == "write" ]; then
     mkdir -p `dirname $batch_file`
@@ -838,7 +843,11 @@ function update_metadata {
   if [ "$dest" == "local" ]; then
     metadata="`dirname $dest_path`/metadata/`basename $dest_path`"
     mkdir -p $metadata
-    date +%c%n%s > $metadata/created
+    # Use the backup start time and not the time the backup was
+    # finished, otherwise daily rotations might not take place.
+    # If we used backup end time, in the next handler run
+    # we might not have $now - $created >= 24:00
+    echo "$starttime" > $metadata/created
     $touch $backupdir/$SECTION/$suffix
   else
     folder="`echo $dest_path | cut -d : -f 2`"
@@ -848,7 +857,11 @@ function update_metadata {
   $ssh_cmd <<EOF
     ##### BEGIN REMOTE SCRIPT #####
     mkdir -p $metadata
-    date +%c%n%s > $metadata/created
+    # Use the backup start time and not the time the backup was
+    # finished, otherwise daily rotations might not take place.
+    # If we used backup end time, in the next handler run
+    # we might not have $now - $created >= 24:00
+    echo "$starttime" > $metadata/created
     ##### END REMOTE SCRIPT #######
 EOF
 ) | (while read a; do passthru $a; done)
@@ -866,7 +879,6 @@ function test_connect {
 
   if [ -z "$host" ] || [ -z "$user" ]; then
     fatal "Remote host or user not set"
-    exit 1
   fi
 
   debug "$ssh_cmd 'echo -n 1'"
@@ -874,52 +886,12 @@ function test_connect {
 
   if [ "$result" != "1" ]; then
     fatal "Can't connect to $host as $user."
-    exit 1
   else
     debug "Connected to $host successfully"
   fi
 
 }
 
-function set_lockfile {
-
-  if [ ! -z "$lockfile" ]; then
-    mkdir -p `dirname $lockfile`
-    if ( set -o noclobber; echo "$$" > "$lockfile" ) &> /dev/null; then
-      trap 'unset_lockfile' INT TERM EXIT
-    else
-      fatal "Could not create lockfile $lockfile, exiting"
-    fi
-  fi
-
-}
-
-function unset_lockfile {
-
-  if [ ! -z "$lockfile" ]; then
-    $rm -f $lockfile || warning "Could not remove lockfile $lockfile"
-  fi
-
-}
-
-function check_lockfile {
-
-  local pid process
-
-  if [ ! -z "$lockfile" ] && [ -f "$lockfile" ]; then
-    pid="`cat $lockfile`"
-    process="`ps --no-headers -o comm $pid`"
-    if [ "$?" == "0" ] && [ "`ps --no-headers -o comm $$`" == "$process" ]; then
-      info "Another backup is running for $lockfile, skipping run"
-      exit
-    else
-      info "Found old lockfile $lockfile, removing it"
-      unset_lockfile  
-    fi
-  fi
-
-}
-
 function set_filelist {
 
   filelist_flag=""
@@ -940,7 +912,7 @@ function set_filelist {
 
 function set_rsync_options {
 
-  if [ ! -z "$numericids" ]; then
+  if [ "$numericids" != "0" ]; then
     rsync_options="$rsync_options --numeric-ids"
   fi
 
@@ -968,7 +940,6 @@ function set_rsync_options {
     if [ "$protocol" == "ssh" ]; then
       if [ ! -e "$id_file" ]; then
         fatal "SSH Identity file $id_file not found"
-        exit 1
       else
         debug RSYNC_RSH=\"$ssh_cmd_base\"
         echo RSYNC_RSH=\"$ssh_cmd_base\" >> $log
@@ -1023,8 +994,7 @@ function mount_rw {
       if [ -d "$mountpoint" ]; then
         mount -o remount,rw $mountpoint
         if (($?)); then
-          error "Could not mount $mountpoint"
-          exit 1
+          fatal "Could not mount $mountpoint"
         fi
       fi
     fi
@@ -1108,17 +1078,39 @@ function end_mux {
 
 }
 
+function set_pipefail {
+
+  # Save initial pipefail status for later restoration
+  if echo "$SHELLOPTS" | grep -q ":pipefail"; then
+     pipefail="-o"
+  else
+     pipefail="+o"
+  fi
+
+  # Ensure that a non-zero rsync exit status is caught by our handler
+  set -o pipefail
+
+}
+
+function restore_pipefail {
+
+  if [ ! -z "$pipefail" ]; then
+    set $pipefail pipefail
+  fi
+
+}
+
 # the backup procedure
 
 eval_config
-check_lockfile
-set_lockfile
 set_rsync_options
 start_mux
 stop_services
 mount_rw
+set_pipefail
 
-echo "Starting backup at `date`" >> $log
+starttime="`date +%c%n%s`"
+echo "Starting backup at `echo "$starttime" | head -n 1`" >> $log
 
 for SECTION in $include; do
 
@@ -1129,22 +1121,21 @@ for SECTION in $include; do
   set_dest
 
   info "Syncing $SECTION on $dest_path..."
-  debug $nice $rsync "${rsync_options[@]}" $filelist_flag $excludes $batch_option $orig $dest_path
-  $nice $rsync "${rsync_options[@]}" $filelist_flag $excludes $batch_option $orig $dest_path | tee -a $log
+  debug $nice $rsync "${rsync_options[@]}" $filelist_flag "$excludes" $batch_option $orig $dest_path
+  $nice $rsync "${rsync_options[@]}" $filelist_flag "$excludes" $batch_option $orig $dest_path | tee -a $log
 
   if [ "$?" != "0" ]; then
     fatal "Rsync error when trying to transfer $SECTION"
-    exit 1
   fi
 
   update_metadata
 
 done
 
+restore_pipefail
 mount_ro
 run_fsck
 start_services
-unset_lockfile
 end_mux
 
 echo "Finnishing backup at `date`" >> $log