From adaabb599a20a7347731eb8241f2a6682fe3a11c Mon Sep 17 00:00:00 2001 From: Axel Burri Date: Fri, 12 Dec 2014 16:29:04 +0100 Subject: [PATCH] btrbk: added support for changelog on send-receive --- btrbk | 71 +++++++++++++++++++++++++++++++++++++++++++----------- btrbk.conf | 32 +++++++++++++++++++++--- 2 files changed, 86 insertions(+), 17 deletions(-) diff --git a/btrbk b/btrbk index 48f9c15..6912fe4 100755 --- a/btrbk +++ b/btrbk @@ -90,7 +90,7 @@ sub run_cmd($;$) { my $cmd = shift; my $non_destructive = shift; - my $ret; + my $ret = ""; INFO ">>> $cmd" unless($non_destructive); if($non_destructive || (not $dryrun)) { DEBUG "CMD: $cmd"; @@ -145,12 +145,12 @@ sub parse_config($) my $file = shift; DEBUG "parsing config file: $file"; tie my %cfg, "Tie::IxHash"; - open FILE, "<$file" or die $!; + open(FILE, '<', $file) or die $!; while () { chomp; next if /^\s*#/; # ignore comments DEBUG "parse_config: parsing line: $_"; - if(/^\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+([a-z,]+)\s*$/) + if(/^\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*$/) { my %job = ( type => "subvol_backup", sroot => $1, @@ -249,17 +249,43 @@ sub btrfs_snapshot($$) run_cmd("/sbin/btrfs subvolume snapshot -r $src $dst"); } -sub btrfs_send_receive($$;$) +sub btrfs_send_receive($$;$$) { my $src = shift; my $dst = shift; my $parent = shift // ""; - INFO "[btrfs] send_receive" . ($parent ? " (incremental)" : " (INIT)") . ":"; - INFO "[btrfs] source: $src"; - INFO "[btrfs] parent: $parent" if($parent); - INFO "[btrfs] dest : $dst"; + my $changelog = shift // ""; + my $now = localtime; + my @info; + push @info, "[btrfs] send_receive" . ($parent ? " (incremental)" : " (INIT)") . ":"; + push @info, "[btrfs] source: $src"; + push @info, "[btrfs] parent: $parent" if($parent); + push @info, "[btrfs] dest : $dst"; + push @info, "[btrfs] log : $changelog" if($changelog); + INFO $_ foreach(@info); + my $parent_option = $parent ? "-p $parent" : ""; - run_cmd("/sbin/btrfs send $parent_option $src | /sbin/btrfs receive $dst/"); + my $receive_option = ""; + $receive_option = "-v" if($changelog || $verbose); + $receive_option = "-v -v" if($parent && $changelog); + my $cmd = "/sbin/btrfs send $parent_option $src | /sbin/btrfs receive $receive_option $dst/ 2>&1"; + my $ret = run_cmd($cmd); + # run_cmd("/bin/sync"); + if($changelog && (not $dryrun)) + { + INFO "--- writing changelog: $changelog"; + if(open(LOGFILE, '>>', $changelog)) { + print LOGFILE "<<< START btrfs_send_receive: $now >>>\n"; + print LOGFILE "$_\n" foreach(@info); + print LOGFILE "[btrfs] cmd : $cmd\n"; + print LOGFILE "[btrfs] cmd output:\n" . $ret; + print LOGFILE "\n<<< END btrfs_send_receive: $now >>>\n"; + close(LOGFILE); + } + else { + WARN "Failed to open changelog file: $!"; + } + } } sub get_latest_common($$$$) @@ -324,7 +350,6 @@ MAIN: HELP_MESSAGE(0); exit 0; } - my $jobs = parse_config($config); my $postfix = '.' . strftime($time_format, localtime); my %snapshots_created; @@ -369,6 +394,19 @@ MAIN: } die("snapshot already exists at destination: $droot") if(check_vol($droot, "${svol}${postfix}")); + my $changelog = ""; + if(grep(/^log/, @job_opts)) + { + if(my @res = grep(/^log=\S+$/, @job_opts)) { + die if(scalar(@res) != 1); + $changelog = $res[0]; + $changelog =~ s/^log=//; + } + else { + # log defaults to sidecar of destination snapshot + $changelog = "$droot/$dvol/${svol}${postfix}.btrbk.log"; + } + } if(grep(/incremental/, @job_opts)) { INFO "--- processing option=incremental"; @@ -378,11 +416,16 @@ MAIN: INFO "--- found common parent: $latest_common"; my $parent_snap = "$src_snapshot_dir/$latest_common"; die("snapshot parent source does not exists: $sroot/$parent_snap") unless check_vol($sroot, $parent_snap); - btrfs_send_receive("$sroot/$ssnap", "$droot/$dvol", "$sroot/$parent_snap"); + btrfs_send_receive("$sroot/$ssnap", "$droot/$dvol", "$sroot/$parent_snap", $changelog); } elsif(grep(/init/, @job_opts)) { - INFO "--- no common parent subvolume found, making new snapshot copy (option=init)"; - btrfs_send_receive("$sroot/$ssnap", "$droot/$dvol"); + if(check_vol($droot, $dvol)) { + INFO "--- no common parent subvolume found, making new snapshot copy (option=init)"; + btrfs_send_receive("$sroot/$ssnap", "$droot/$dvol", undef, $changelog); + } + else { + WARN "backup to $droot failed: target subvolume not found: $droot/$dvol"; + } } else { WARN "backup to $droot failed: no common parent subvolume found, and job option \"create\" is not set"; @@ -391,7 +434,7 @@ MAIN: elsif(grep(/create/, @job_opts)) { INFO "<$type> making new snapshot copy (option=create))"; - btrfs_send_receive("${sroot}/${ssnap}", "${droot}/${dvol}"); + btrfs_send_receive("${sroot}/${ssnap}", "${droot}/${dvol}", undef, $changelog); } } } diff --git a/btrbk.conf b/btrbk.conf index f4a3780..6139cea 100644 --- a/btrbk.conf +++ b/btrbk.conf @@ -1,5 +1,31 @@ -/mnt/btr_boot/ boot /mnt/btr_ext/ _btrbk init,incremental -/mnt/btr_boot/ boot /mnt/btr_extext/ _btrbk incremental +# options: +# +# init create initial (non-incremental) snapshot if needed +# incremental do incremental backups (recommended) +# create always create non-incremental snapshots +# log log to "sidecar" file for each revision (suffix ".btrfs.log") +# log= append log to specified logfile +# + +# + +/mnt/btr_system root_gentoo /mnt/btr_ext _btrbk incremental,init +/mnt/btr_system root_gentoo /mnt/btr_backup _btrbk incremental,init,log +/mnt/btr_system kvm /mnt/btr_ext _btrbk incremental,init +/mnt/btr_system kvm /mnt/btr_backup _btrbk incremental,init,log + +/mnt/btr_data home /mnt/btr_backup _btrbk incremental,init,log +/mnt/btr_data sdms.data /mnt/btr_backup _btrbk incremental,init,log + +/mnt/btr_ext data /mnt/btr_backup _btrbk incremental,init,log +# TODO: these monthly +#/mnt/btr_ext video /mnt/btr_backup _btrbk incremental,init,log +#/mnt/btr_ext audio /mnt/btr_backup _btrbk incremental,init,log + +# TODO: these monthly +#/mnt/btr_boot boot /mnt/btr_ext _btrbk incremental,init,log +#/mnt/btr_boot boot /mnt/btr_backup _btrbk incremental + # non-incremental, create a new snapshot at every invocation! -#/mnt/btr_boot/ boot /mnt/btr_extext/ _btrbk create +##/mnt/btr_boot boot /mnt/btr_backup _btrbk create