[mylvmbackup] [mylvmbackup 8/9] Add rsync backup type.

Finally, we can include support for using rsync to perform the backup.
This is very useful if you want to use mylvmbackup to create the initial state
for your slave servers.

---
 TODO                  |    7 +++++--
 man/mylvmbackup.1.txt |   28 +++++++++++++++++++++++-----
 mylvmbackup.conf      |    3 +++
 mylvmbackup.pl.in     |   40 ++++++++++++++++++++++++++++++++++++++--
 4 files changed, 69 insertions(+), 9 deletions(-)

diff --git a/TODO b/TODO
index 03b2d1b..49f2566 100644
--- a/TODO
+++ b/TODO
@@ -1,8 +1,9 @@
 mylvmbackup TODO list:
 
  - Document the new logging options in the man page and help output
- - Support other backup methods than tar by modularizing the backup part:
-     * rsync - http://rsync.samba.org/
+ - Modularize the backup portion
+ - Support other backup methods than tar after modularizing
+     * rsync - http://rsync.samba.org/ (already available as a hack)
      * rsnapshot - http://www.rsnapshot.org/
      * duplicity - http://duplicity.nongnu.org/
      * unison - http://www.cis.upenn.edu/~bcpierce/unison/
@@ -15,3 +16,5 @@ mylvmbackup TODO list:
  - Providing an option to shut down the server instead of using FLUSH TABLES
    WITH READ LOCK before taking the snapshot, for consistent InnoDB snapshots
    (e.g. on a replication slave)
+ - Allow running custom scripts before/after each phase: (flush, lvcreate,
+   mount, recover, backup, umount)
diff --git a/man/mylvmbackup.1.txt b/man/mylvmbackup.1.txt
index 0f40ce5..6eab116 100644
--- a/man/mylvmbackup.1.txt
+++ b/man/mylvmbackup.1.txt
@@ -25,9 +25,12 @@ The LVM snapshot is mounted to a temporary directory and all 
data is backed up
 using the 'tar' program. By default, the archive file is created using a name
 of the form 'backup-YYYYMMDD_hhmmss_mysql.tar.gz', where 'YYYY', 'MM', 'DD',
 'hh', 'mm', and 'ss' represent the year, month, day, hour, minute, and second
-of the time at which the backup occurred. The prefix 'backup' and the date
-format can be modified. The use of timestamped archive names allows you to run
-mylvmbackup many times without danger of overwriting old archives.
+of the time at which the backup occurred. The prefix 'backup', date format and
+file suffix may be modified. The use of timestamped archive names allows you
+to run mylvmbackup many times without danger of overwriting old archives.
+
+Alternatively, in place in 'tar', you may use 'rsync'. This process is nearly
+identical, with the exception that the file suffix is not used.
 
 GENERAL HINTS
 -------------
@@ -159,6 +162,10 @@ the leading dashes, of course).
   Specifies the size for the snapshot volume.
   The default is '5G' (5 gigabytes).
 
+--backuptype=string::
+  Specifies what type of backup to perform. The available options are 'tar'
+  and 'rsync'.
+
 --prefix=string::
   Prefix added to the backup file names. It is also appended to
   the name of the directory used to mount the snapshot volume.
@@ -198,12 +205,22 @@ the leading dashes, of course).
 
 --tarsuffixarg=string::
   Specifies the suffix arguments for the 'tar' program.
-  The default is ''.
+  The default is ''. 
+  To exclude a database, you would pass '--exclude dbname' here.
 
 --tarfilesuffix=string::
   Specifies the suffix for the tarball.
   The default is '.tar.gz'.
 
+--rsync=string::
+  Specifies the pathname for the 'rsync' program.
+  The default is 'rsync'.
+
+--rsyncarg=string::
+  Specifies the arguments for the 'rsync' program.
+  The default is '-avWP'. Should must ensure that the recursive option is
+  included either implicitly by '-a', or explicitly.
+
 --xfs::
   Use the 'nouuid' mount option to safely mount snapshot partitions that
   use the XFS file system.
@@ -254,10 +271,11 @@ It also requires several other external programs: GNU 
'tar' and 'gzip' to back
 up the data, LVM utilities ('lvcreate', 'lvremove' and 'lvs') to create and
 remove the LVM snapshot, and the system utilities 'mount' and 'umount'.
 
+'rsync' may be used in place of 'tar' and 'gzip'.
 
 SEE ALSO
 --------
-'mount(8)', 'tar(1)', 'lvcreate(8)', 'lvremove(8)', lvs(8)', 'umount(8)'
+'mount(8)', 'tar(1)', 'lvcreate(8)', 'lvremove(8)', lvs(8)', 'umount(8)', 
'rsync(1)'
 
 
 AUTHOR
diff --git a/mylvmbackup.conf b/mylvmbackup.conf
index 63944dc..9a36f69 100644
--- a/mylvmbackup.conf
+++ b/mylvmbackup.conf
@@ -42,15 +42,18 @@ lvcreate=/sbin/lvcreate
 lvremove=/sbin/lvremove
 mount=/bin/mount
 tar=/bin/tar
+rsync=/usr/bin/rsync
 umount=/bin/umount
 
 #
 # Other configuration options
 #
 [misc]
+backuptype=tar
 prefix=backup
 tararg=cvzf
 tarsuffixarg=
+rsyncarg=-avWP
 datefmt=%Y%m%d_%H%M%S
 innodb_recover=0
 pidfile=/var/tmp/mylvmbackup_recoverserver.pid
diff --git a/mylvmbackup.pl.in b/mylvmbackup.pl.in
index 9da1f85..4d171af 100755
--- a/mylvmbackup.pl.in
+++ b/mylvmbackup.pl.in
@@ -55,9 +55,12 @@ my $need_xfsworkaround;
 my $password;
 my $pidfile;
 my $port;
+my $backuptype;
 my $prefix;
 my $relpath;
 my $socket;
+my $rsync;
+my $rsyncarg;
 my $tar;
 my $tararg;
 my $tarsuffixarg;
@@ -203,7 +206,7 @@ log_msg ("Taking snapshot...", LOG_INFO);
 create_snapshot();
 
 log_msg ("Unlocking tables...", LOG_INFO);
-$dbh->do("unlock tables") 
+$dbh->do("UNLOCK TABLES") 
   or log_msg ($DBI::errstr, LOG_ERR) && die $DBI::errstr;
 
 log_msg ("Disconnecting from database...", LOG_INFO);
@@ -223,7 +226,8 @@ if ($snapshot_created)
     create_mycnf_file();
 
     log_msg ("Taking actual backup...", LOG_INFO);
-    do_backup_tar();
+    do_backup_tar() if ($backuptype eq 'tar');
+    do_backup_rsync() if ($backuptype eq 'rsync');
   }    
 }
 
@@ -251,12 +255,14 @@ sub load_config
   $lvsize=$cfg->val ('lvm', 'lvsize', $lvsize);
   $backuplv = $cfg->val ('lvm', 'backuplv', $backuplv);
   
+  $backuptype=$cfg->val ('misc', 'backuptype', $backuptype);
   $prefix=$cfg->val ('misc', 'prefix', $prefix);
   $datefmt=$cfg->val ('misc', 'datefmt', $datefmt);
   $innodb_recover=$cfg->val ('misc', 'innodb_recover', $innodb_recover);
   $pidfile=$cfg->val ('misc', 'pidfile', $pidfile);
   $skip_flush_tables=$cfg->val ('misc', 'skip_flush_tables', 
$skip_flush_tables);
   $extra_flush_tables=$cfg->val ('misc', 'extra_flush_tables', 
$extra_flush_tables);
+  $rsyncarg=$cfg->val ('misc', 'rsyncarg', $rsyncarg);
   $tararg=$cfg->val ('misc', 'tararg', $tararg);
   $tarsuffixarg=$cfg->val ('misc', 'tarsuffixarg', $tarsuffixarg);
   $tarfilesuffix = $cfg->val ('misc', 'tarfilesuffix', $tarfilesuffix);
@@ -272,6 +278,7 @@ sub load_config
   $mount=$cfg->val ('tools', 'mount', $mount);
   $umount=$cfg->val ('tools', 'umount', $umount);
   $tar=$cfg->val ('tools', 'tar', $tar);
+  $rsync=$cfg->val ('tools', 'rsync', $rsync);
 
   $log_method = $cfg->val('logging', 'log_method', $log_method);
   $syslog_socktype = $cfg->val ('logging', 'syslog_socktype', 
$syslog_socktype);
@@ -303,6 +310,7 @@ sub load_args
     "backuplv=s" => \$backuplv,
 
 # misc
+    "backuptype=s" => \$backuptype,
     "prefix=s" => \$prefix,
     "datefmt=s" => \$datefmt,
     "innodb_recover" => \&innodb_recover,
@@ -312,6 +320,7 @@ sub load_args
     "tararg=s" => \$tararg,
     "tarsuffixarg=s" => \$tarsuffixarg,
     "tarfilesuffix=s" => \$tarfilesuffix,
+    "rsyncarg=s" => \$rsyncarg,
 
 # fs
     "mountdir=s" => \$mountdir,
@@ -326,6 +335,7 @@ sub load_args
     "mount=s" => \$mount,
     "umount=s" => \$umount,
     "tar=s" => \$tar,
+    "rsync=s" => \$rsync,
 
 # logging
     "log_method=s" => \$log_method,
@@ -354,6 +364,7 @@ sub load_defaults
   $backuplv = '';
 
 # misc
+  $backuptype='tar';
   $prefix='backup';
   $datefmt='%Y%m%d_%H%M%S';
   $innodb_recover=0;
@@ -363,6 +374,7 @@ sub load_defaults
   $tararg='cvzf';
   $tarsuffixarg='';
   $tarfilesuffix='.tar.gz';
+  $rsyncarg='-avPW';
 
 # fs
   $mountdir='/var/tmp/mylvmbackup/mnt/';
@@ -377,6 +389,7 @@ sub load_defaults
   $mount='mount';
   $umount='umount';
   $tar='tar';
+  $rsync='rsync';
 
 # logging
   $log_method = 'console';
@@ -443,6 +456,29 @@ sub do_backup_tar
   }    
 }
 
+sub do_backup_rsync
+{
+  my $destdir = $archivename;
+  my $destdirtmp = sprintf('%s.INCOMPLETE-%07d',$destdir,int(rand(2**16)));
+  log_msg ("Archving with rsync to $destdir", LOG_INFO);
+
+  # Trailing slash is bad
+  my $relpath_noslash = $relpath;
+  $relpath_noslash =~ s/\/+$//g;
+
+  my $command = "$rsync $rsyncarg $mountdir/$relpath_noslash";
+  $command .= " $pos_filename" if (-f $pos_filename );
+  $command .= " $mycnf_filename" if (-f $mycnf_filename );
+  $command .= " $destdirtmp/";
+  if ( system($command) == 0 )
+  {
+    rename $destdirtmp, $destdir;
+    log_msg ("DONE", LOG_INFO);
+  } else {
+    log_msg ("FAIL $!", LOG_ERR);
+  }    
+}
+
 sub mount_snapshot
 { 
   my $params = 'ro';
-- 
1.5.3

Other related posts: