btrbk: added support for changelog on send-receive

pull/30/head
Axel Burri 2014-12-12 16:29:04 +01:00
parent 3aa6acfc6e
commit adaabb599a
2 changed files with 86 additions and 17 deletions

71
btrbk
View File

@ -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 (<FILE>) {
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);
}
}
}

View File

@ -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=<logfile> append log to specified logfile
#
# <src_mountpoint> <src_subvol> <dst_mountpoint> <dst_subvol_pool> <options>
/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