← Back to team overview

mylvmbackup-discuss team mailing list archive

patches for backuptype=none and error handling

 

hi, I'd like to suggest the attached patch for inclusion in mylvmbackup.
it is relative to 0.13.  it does the following (from top to bottom):

      * make sure $PATH includes sbin
      * make sure $HOME is set (not always the case when launched
        (indirectly) from init, in my case, from Bacula)
      * count error messages logged, and never exit with status 0 if
        non-zero
      * move around cleanup for backuptype=none.  this means you can do
        "mylvmbackup --backuptype=none --keep_mount" to take a snapshot,
        and "mylvmbackup --backuptype=none" to release it.  the
        shuffling is necessary to handle the case where mylvmbackup dies
        suddenly.
      * simple typo for $pidfile -- probably fixed in trunk, I didn't
        check...
      * cleanup handles the case where the snapshot was created and
        mounted in a different run
      * fix a potential endless loop if the logerr hook contains errors.


-- 
thanks,
Kjetil T. Homme
Redpill Linpro - Changing the game

--- mylvmbackup.pl.in	2009-09-05 15:44:09.000000000 +0200
+++ /srv/nfs/ms/home/kjetilho/svn/puppet/modules/mysql/files/mylvmbackup/mylvmbackup.pl	2010-12-14 17:12:44.979678793 +0100
@@ -37,6 +37,9 @@
 my $configfile = "/etc/mylvmbackup.conf";
 my $configfile2 = "";
 
+$ENV{PATH} .= ":/usr/sbin:/usr/bin:/sbin:/bin";
+$ENV{HOME} ||= (getpwuid($<))[7];
+
 my $TMP= ($ENV{TMPDIR} || "/tmp");
 
 my $backupdir;
@@ -87,6 +90,7 @@
 my $syslog_socktype;
 my $syslog_facility;
 my $syslog_remotehost;
+my $errors=0;
 
 # Load defaults into variables
 load_defaults();
@@ -140,7 +144,7 @@
 # No .tar.gz on the end!
 my $archivename  = $backupdir.'/'.$fullprefix;
 
-my $mounted = 0;
+my $mounted;
 my $snapshot_created = 0;
 
 # Check for the backupdir, it must exist, and it must be readable/writable
@@ -160,6 +164,22 @@
 my $posmountdir = $mountdir;
 $posmountdir .= '-pos'; # Notice that we do not add a slash.
 
+if ($backuptype eq 'none' && !$keep_mount && !$keep_snapshot)
+{
+  cleanup();
+  exit ($errors ? 1 : 0);
+}
+
+# Make sure mountdir doesn't already exist
+if (glob "$mountdir/*") {
+  # First try to cleanup after a failed previous run
+  cleanup();
+  if (glob "$mountdir/*") {
+    log_msg ("Please make sure Temp dir ($mountdir) is empty.", LOG_ERR); 
+    exit(1);
+  }
+}
+
 my $pos_filename = $posmountdir.'/'.$fullprefix.'.pos';
 my $pos_tempfile_fh;
 my $pos_tempfile;
@@ -176,14 +196,6 @@
 # Check it again for existence and read/write.
 check_dir($mountdir, 'mountdir');
 
-# Now make sure it's empty
-my @mountdir_content = glob "$mountdir/*" ;
-unless ( scalar(@mountdir_content) eq 0)
-{
-	log_msg ("Please make sure Temp dir ($mountdir) is empty.", LOG_ERR); 
-	exit(1);
-};
-
 # Figure out our DSN string
 my $dsn = "DBI:mysql:database=mysql;mysql_read_default_group=client";
 
@@ -253,13 +265,10 @@
       run_hook("backupfailure");
     }
   }    
-} else {
-  cleanup();
-  exit 1;
 }
 
 cleanup();
-exit 0;
+exit ($errors ? 1 : 0);
 
 # Please keep all 3 functions in the same order: load_config, load_args, load_defaults 
 sub load_config 
@@ -420,7 +429,7 @@
   $suffix='_mysql';
   $datefmt='%Y%m%d_%H%M%S';
   $innodb_recover=0;
-  $pidfile = '$TMP/mylvmbackup_recoverserver.pid';
+  $pidfile = "$TMP/mylvmbackup_recoverserver.pid";
   $skip_flush_tables=0;
   $extra_flush_tables=0;
   $skip_mycnf=0;
@@ -637,6 +646,9 @@
   my $msg = shift;
   my $syslog_level = shift;
 
+  # Make sure we never exit successfully if LOG_ERR occurs
+  ++$errors if $syslog_level eq LOG_ERR;
+
   # Only log errors and warnings if quiet option is set
   return if ($quiet) and ($syslog_level eq LOG_INFO);
 
@@ -695,15 +707,32 @@
 {
   run_hook("precleanup");
   log_msg ("Cleaning up...", LOG_INFO);
+
+  unless (defined $mounted) {
+    my $mapper_name = "$vgname/$backuplv";
+    $mapper_name =~ s:-:--:g;
+    $mapper_name =~ s:/:-:g;
+    $mapper_name = "mapper/$mapper_name";
+    if (open(my $mountfd, "$mount|")) {
+      while (<$mountfd>) {
+        if (m:^/dev/($vgname/$backuplv|$mapper_name)\s:) {
+          log_msg ("found mounted LV", LOG_INFO);
+          $mounted = 1;
+        }
+      }
+      close($mountfd);
+    }
+  }
+
   unless ($keep_mount) {
     run_command("Unmounting $mountdir","$umount $mountdir") if ($mounted);
-    unlink $pos_filename if (-f $pos_filename);
-    unlink $mycnf_filename if (-f $mycnf_filename);
+    unlink $pos_filename if defined $pos_filename && -f $pos_filename;
+    unlink $mycnf_filename if defined $mycnf_filename && -f $mycnf_filename;
     if ($posmountdir) {
       rmdir $mountdir;
       rmdir $posmountdir;
     }
-    unlink $pos_tempfile if (-f $pos_tempfile);
+    unlink $pos_tempfile if defined $pos_tempfile && -f $pos_tempfile;
   } else {
     log_msg("Not removing mount as requested by configuration", LOG_INFO);
   }
@@ -714,9 +743,6 @@
     foreach my $lvs_info (@lvs_info) {
         log_msg ($lvs_info, LOG_INFO);
     }
-  }
-  if ($snapshot_created)
-  {
     unless ($keep_snapshot || $keep_mount) {
       run_command("Removing snapshot", "$lvremove -f /dev/$vgname/$backuplv");
     } else {
@@ -888,6 +914,9 @@
   my $hookfile = $hooksdir."/".$hookname;
   $hookarg="" unless ($hookarg);
 
+  # Avoid loops
+  my $log_err = ($hookname eq "precleanup" || $hookname eq "logerr") ?
+      LOG_WARNING : LOG_ERR;
   eval "use $hookname";
   if($@)
   {
@@ -901,7 +930,7 @@
       if ( $? >> 8 != 0)
       {
         log_msg (sprintf("Hook $hookname failed with nonzero exit value %d", $? >> 8),
-               $hookname eq "precleanup" ? LOG_WARNING : LOG_ERR);
+               $log_err);
       }
     }
   } else {
@@ -909,7 +938,7 @@
     my $ret = $hookname->execute(($dbh ? $dbh->clone() : undef), $hookarg);
     if(!$ret)
     {
-      log_msg ("Perl module '$hookname' did not return a true result: " . $hookname->errmsg(), LOG_ERR);
+      log_msg ("Perl module '$hookname' did not return a true result: " . $hookname->errmsg(), $log_err);
     }
   }
 }

Follow ups