btrbk: adapted/fixed target "clean" for refactored configuration

pull/30/head
Axel Burri 2015-01-12 17:56:35 +01:00
parent 1aaa72ebfe
commit c445fa7970
1 changed files with 123 additions and 115 deletions

140
btrbk
View File

@ -67,12 +67,10 @@ my %config_options = (
incremental => { default => "yes", accept => [ "yes", "no", "strict" ] }, incremental => { default => "yes", accept => [ "yes", "no", "strict" ] },
receive_log => { default => undef, accept => [ "sidecar", "no" ], accept_file => "absolute" }, receive_log => { default => undef, accept => [ "sidecar", "no" ], accept_file => "absolute" },
snapshot_create_always => { default => undef, accept => [ "yes", "no" ] }, snapshot_create_always => { default => undef, accept => [ "yes", "no" ] },
snapshot_preserve_all => { default => "yes", accept => [ "yes", "no" ] }, # TODO: honor this snapshot_preserve_days => { default => "all", accept => [ "no", "all" ], accept_number => 1 },
snapshot_preserve_days => { default => undef, accept => [ "no" ], accept_number => 1 }, snapshot_preserve_weekly => { default => 0, accept => [ "no" ], accept_number => 1 },
snapshot_preserve_weekly => { default => undef, accept => [ "no" ], accept_number => 1 }, target_preserve_days => { default => "all", accept => [ "no", "all" ], accept_number => 1 },
target_preserve_all => { default => "yes", accept => [ "yes", "no" ] }, # TODO: honor this target_preserve_weekly => { default => 0, accept => [ "no" ], accept_number => 1 },
target_preserve_days => { default => undef, accept => [ "no" ], accept_number => 1 },
target_preserve_weekly => { default => undef, accept => [ "no" ], accept_number => 1 },
); );
my @config_target_types = qw(send-receive); my @config_target_types = qw(send-receive);
@ -679,39 +677,50 @@ sub check_backup_scheme(@)
my %args = @_; my %args = @_;
my $vol_date = $args{vol_date} || die; my $vol_date = $args{vol_date} || die;
my $today = $args{today} || die; my $today = $args{today} || die;
my $keep_days = $args{keep_days} || die; my $week_start = $args{week_start} || die;
my $weekly_threshold = $args{weekly_threshold} || die; my $preserve_days = $args{preserve_days} // die;
my $keep_info = $args{keep_info} || die; my $preserve_weekly = $args{preserve_weekly} // die;
my $keep = 0; my $preserve_info = $args{preserve_info} || die;
my $preserve = 0;
my ($vol_y, $vol_m, $vol_d) = @$vol_date; my ($vol_y, $vol_m, $vol_d) = @$vol_date;
# calculate weekly_threshold
my @weekly_threshold = Add_Delta_Days(@$week_start, (-7 * $preserve_weekly));
TRACE "weekly_threshold for preserve_weekly=$preserve_weekly: " . join('-', @weekly_threshold);
if($preserve_days eq "all") {
$preserve = "preserve_days is set to \"all\"";
DEBUG "$preserve";
}
else {
my $dd = Delta_Days(@$vol_date, @$today); my $dd = Delta_Days(@$vol_date, @$today);
if($dd <= $keep_days) if($dd <= $preserve_days)
{ {
$keep = "less than $keep_days days old (age=$dd days)"; $preserve = "less than $preserve_days days old (age: $dd days)";
DEBUG "$keep"; DEBUG "$preserve";
}
} }
if(Delta_Days(@$vol_date, @$weekly_threshold) < 0) if(Delta_Days(@$vol_date, @weekly_threshold) < 0)
{ {
DEBUG "not older than " . join('-', @$weekly_threshold); DEBUG "not older than " . join('-', @weekly_threshold);
my ($vol_wnr, $vol_wy) = Week_of_Year(@$vol_date); my ($vol_wnr, $vol_wy) = Week_of_Year(@$vol_date);
unless($keep_info->{week}->{"$vol_wy-$vol_wnr"}) unless($preserve_info->{week}->{"$vol_wy-$vol_wnr"})
{ {
$keep_info->{week}->{"$vol_wy-$vol_wnr"} = 1; $preserve_info->{week}->{"$vol_wy-$vol_wnr"} = 1;
$keep = "last in week $vol_wy-$vol_wnr"; $preserve = "last in week #$vol_wnr, $vol_wy";
DEBUG "$keep"; DEBUG "$preserve";
} }
} }
unless($keep_info->{month}->{"$vol_y-$vol_m"}) unless($preserve_info->{month}->{"$vol_y-$vol_m"})
{ {
$keep_info->{month}->{"$vol_y-$vol_m"} = 1; $preserve_info->{month}->{"$vol_y-$vol_m"} = 1;
$keep = "last in month $vol_y-$vol_m"; $preserve = "last in month $vol_y-$vol_m";
DEBUG "$keep"; DEBUG "$preserve";
} }
return $keep; return $preserve;
} }
@ -1052,6 +1061,7 @@ MAIN:
my $droot = $config_target->{droot} || die; my $droot = $config_target->{droot} || die;
my $target_type = $config_target->{target_type} || die; my $target_type = $config_target->{target_type} || die;
my $success = 0;
if($target_type eq "send-receive") if($target_type eq "send-receive")
{ {
INFO "Creating subvolume backup ($target_type) for: $sroot/$svol"; INFO "Creating subvolume backup ($target_type) for: $sroot/$svol";
@ -1070,11 +1080,11 @@ MAIN:
if($latest_common_src && $latest_common_dst) { if($latest_common_src && $latest_common_dst) {
my $parent_snap = $latest_common_src->{FS_PATH}; my $parent_snap = $latest_common_src->{FS_PATH};
INFO "Incremental from parent snapshot: $parent_snap"; INFO "Incremental from parent snapshot: $parent_snap";
btrfs_send_receive($snapshot, $droot, $parent_snap, $receive_log); $success = btrfs_send_receive($snapshot, $droot, $parent_snap, $receive_log);
} }
elsif($incremental ne "strict") { elsif($incremental ne "strict") {
INFO "No common parent subvolume present, creating full backup"; INFO "No common parent subvolume present, creating full backup";
btrfs_send_receive($snapshot, $droot, undef, $receive_log); $success = btrfs_send_receive($snapshot, $droot, undef, $receive_log);
} }
else { else {
WARN "Backup to $droot failed: no common parent subvolume found, and option \"incremental\" is set to \"strict\""; WARN "Backup to $droot failed: no common parent subvolume found, and option \"incremental\" is set to \"strict\"";
@ -1082,12 +1092,13 @@ MAIN:
} }
else { else {
INFO "Creating full backup (option \"incremental\" is not set)"; INFO "Creating full backup (option \"incremental\" is not set)";
btrfs_send_receive($snapshot, $droot, undef, $receive_log); $success = btrfs_send_receive($snapshot, $droot, undef, $receive_log);
} }
} }
else { else {
ERROR "Unknown target type \"$target_type\", skipping: $sroot/$svol"; ERROR "Unknown target type \"$target_type\", skipping: $sroot/$svol";
} }
$config_target->{ABORTED} = 1 unless($success);
} }
} }
} }
@ -1098,30 +1109,8 @@ MAIN:
{ {
$dryrun = 1; $dryrun = 1;
# TODO: gather all information first, then delete all backups/snapshots at the end # TODO: gather all information first, then delete all backups/snapshots at the end
# TODO: always keep first/last # TODO: always preserve first/last
#
# remove backups following a keep_days/keep_weekly scheme
#
foreach my $job (@$jobs)
{
next if($job->{ABORTED});
my $sroot = $job->{sroot} || die;
my $svol = $job->{svol} || die;
my $droot = $job->{droot} || die;
my $job_opts = $job->{options} || die;
unless(ref($job_opts->{preserve})) {
INFO "Skip cleaning of subvolume backups (option preserve is not set): $sroot/$svol";
next;
}
INFO "Cleaning subvolume backups of job: $sroot/$svol";
my $keep_days = $job_opts->{preserve}->{daily};
my $keep_weekly = $job_opts->{preserve}->{weekly};
# calculate weekly_threshold
my @last_sunday; my @last_sunday;
if(Day_of_Week(@today) == 7) { # today is sunday if(Day_of_Week(@today) == 7) { # today is sunday
@last_sunday = @today; @last_sunday = @today;
@ -1129,14 +1118,29 @@ MAIN:
else { else {
@last_sunday = Add_Delta_Days(Monday_of_Week(Week_of_Year(@today)), -1); @last_sunday = Add_Delta_Days(Monday_of_Week(Week_of_Year(@today)), -1);
} }
my @weekly_threshold = Add_Delta_Days(@last_sunday, (-7 * $keep_weekly));
DEBUG "last sunday: " . join('-', @last_sunday); DEBUG "last sunday: " . join('-', @last_sunday);
DEBUG "weekly_threshold for keep_weekly=$keep_weekly: " . join('-', @weekly_threshold);
#
# remove backups following a preserve_days/preserve_weekly scheme
#
foreach my $config_vol (@{$config->{VOLUME}})
{
next if($config_vol->{ABORTED});
my $sroot = $config_vol->{sroot} || die;
foreach my $config_subvol (@{$config_vol->{SUBVOLUME}})
{
next if($config_subvol->{ABORTED});
my $svol = $config_subvol->{svol} || die;
INFO "Cleaning subvolume backups for: $sroot/$svol";
foreach my $config_target (@{$config_subvol->{TARGET}})
{
next if($config_target->{ABORTED});
my $droot = $config_target->{droot} || die;
# #
# delete backups # delete backups
# #
my $keep_info = {}; my $preserve_info = {};
my @delete_backups; my @delete_backups;
INFO "Cleaning backups: $droot/$svol.*"; INFO "Cleaning backups: $droot/$svol.*";
foreach my $vol (sort { $b cmp $a } keys %{$vol_info{$droot}}) foreach my $vol (sort { $b cmp $a } keys %{$vol_info{$droot}})
@ -1145,15 +1149,16 @@ MAIN:
my @vol_date = ($1, $2, $3); my @vol_date = ($1, $2, $3);
DEBUG "Checking: $vol"; DEBUG "Checking: $vol";
my $keep = check_backup_scheme( my $preserve = check_backup_scheme(
vol_date => \@vol_date, vol_date => \@vol_date,
today => \@today, today => \@today,
weekly_threshold => \@weekly_threshold, week_start => \@last_sunday, # TODO: configurable
keep_days => $keep_days, preserve_days => config_key($config_target, "target_preserve_days"),
keep_info => $keep_info, preserve_weekly => config_key($config_target, "target_preserve_weekly"),
preserve_info => $preserve_info,
); );
if($keep) { if($preserve) {
INFO "$vol: preserved: $keep"; INFO "$vol: preserved: $preserve";
} }
else { else {
INFO "$vol: DELETE"; INFO "$vol: DELETE";
@ -1161,11 +1166,12 @@ MAIN:
} }
} }
btrfs_subvolume_delete(@delete_backups); btrfs_subvolume_delete(@delete_backups);
}
# #
# delete snapshots # delete snapshots
# #
$keep_info = {}; my $preserve_info = {};
my @delete_snapshots; my @delete_snapshots;
INFO "Cleaning snapshots: $sroot/$snapdir$svol.*"; INFO "Cleaning snapshots: $sroot/$snapdir$svol.*";
foreach my $vol (sort { $b cmp $a } keys %{$vol_info{$sroot}}) foreach my $vol (sort { $b cmp $a } keys %{$vol_info{$sroot}})
@ -1174,15 +1180,16 @@ MAIN:
my @vol_date = ($1, $2, $3); my @vol_date = ($1, $2, $3);
DEBUG "Checking: $vol"; DEBUG "Checking: $vol";
my $keep = check_backup_scheme( my $preserve = check_backup_scheme(
vol_date => \@vol_date, vol_date => \@vol_date,
today => \@today, today => \@today,
weekly_threshold => \@weekly_threshold, week_start => \@last_sunday, # TODO: configurable
keep_days => $keep_days, preserve_days => config_key($config_subvol, "snapshot_preserve_days"),
keep_info => $keep_info, preserve_weekly => config_key($config_subvol, "snapshot_preserve_weekly"),
preserve_info => $preserve_info,
); );
if($keep) { if($preserve) {
INFO "$vol: preserved: $keep"; INFO "$vol: preserved: $preserve";
} }
else { else {
INFO "$vol: DELETE"; INFO "$vol: DELETE";
@ -1192,6 +1199,7 @@ MAIN:
btrfs_subvolume_delete(@delete_snapshots); btrfs_subvolume_delete(@delete_snapshots);
} }
} }
}
} }