mirror of https://github.com/digint/btrbk
btrbk: propagate target sections to (sub-)subsections (allow target sections everywhere in the config)
parent
f9ca7504c8
commit
de96f267b8
85
btrbk
85
btrbk
|
@ -251,8 +251,8 @@ sub WARN { my $t = shift; print STDERR "WARNING: $t\n" if($loglevel >= 1); }
|
||||||
sub ERROR { my $t = shift; print STDERR "ERROR: $t\n"; }
|
sub ERROR { my $t = shift; print STDERR "ERROR: $t\n"; }
|
||||||
|
|
||||||
sub VINFO {
|
sub VINFO {
|
||||||
my $vinfo = shift; my $t = shift || "vinfo";
|
my $vinfo = shift; my $t = shift || "vinfo"; my $maxdepth = shift // 2;
|
||||||
print STDERR Data::Dumper->new([$vinfo], [$t])->Maxdepth(2)->Dump();
|
print STDERR Data::Dumper->new([$vinfo], [$t])->Maxdepth($maxdepth)->Dump();
|
||||||
}
|
}
|
||||||
sub SUBVOL_LIST {
|
sub SUBVOL_LIST {
|
||||||
my $vol = shift; my $t = shift // "SUBVOL_LIST"; my $svl = vinfo_subvol_list($vol);
|
my $vol = shift; my $t = shift // "SUBVOL_LIST"; my $svl = vinfo_subvol_list($vol);
|
||||||
|
@ -1841,11 +1841,11 @@ sub parse_config_line($$$$$)
|
||||||
$value =~ s/^\/+/\//; # sanitize leading slash
|
$value =~ s/^\/+/\//; # sanitize leading slash
|
||||||
TRACE "config: adding volume \"$value\" to root context";
|
TRACE "config: adding volume \"$value\" to root context";
|
||||||
die unless($cur->{CONTEXT} eq "root");
|
die unless($cur->{CONTEXT} eq "root");
|
||||||
my $volume = { CONTEXT => "volume",
|
my $volume = { CONTEXT => "volume",
|
||||||
PARENT => $cur,
|
PARENT => $cur,
|
||||||
url => $value,
|
SUBSECTION => [],
|
||||||
|
url => $value,
|
||||||
};
|
};
|
||||||
$cur->{SUBSECTION} //= [];
|
|
||||||
push(@{$cur->{SUBSECTION}}, $volume);
|
push(@{$cur->{SUBSECTION}}, $volume);
|
||||||
$cur = $volume;
|
$cur = $volume;
|
||||||
}
|
}
|
||||||
|
@ -1868,14 +1868,14 @@ sub parse_config_line($$$$$)
|
||||||
my $snapshot_name = $value;
|
my $snapshot_name = $value;
|
||||||
$snapshot_name =~ s/^.*\///; # snapshot_name defaults to subvolume name
|
$snapshot_name =~ s/^.*\///; # snapshot_name defaults to subvolume name
|
||||||
die unless($cur->{CONTEXT} eq "volume");
|
die unless($cur->{CONTEXT} eq "volume");
|
||||||
my $subvolume = { CONTEXT => "subvolume",
|
my $subvolume = { CONTEXT => "subvolume",
|
||||||
PARENT => $cur,
|
PARENT => $cur,
|
||||||
rel_path => $value,
|
# SUBSECTION => [], # handled by target propagation
|
||||||
url => $cur->{url} . '/' . $value,
|
rel_path => $value,
|
||||||
|
url => $cur->{url} . '/' . $value,
|
||||||
snapshot_name => $snapshot_name,
|
snapshot_name => $snapshot_name,
|
||||||
};
|
};
|
||||||
$subvolume->{GLOB_CONTEXT} = 1 if($value =~ /\*/);
|
$subvolume->{GLOB_CONTEXT} = 1 if($value =~ /\*/);
|
||||||
$cur->{SUBSECTION} //= [];
|
|
||||||
push(@{$cur->{SUBSECTION}}, $subvolume);
|
push(@{$cur->{SUBSECTION}}, $subvolume);
|
||||||
$cur = $subvolume;
|
$cur = $subvolume;
|
||||||
}
|
}
|
||||||
|
@ -1885,10 +1885,6 @@ sub parse_config_line($$$$$)
|
||||||
$cur = $cur->{PARENT} || die;
|
$cur = $cur->{PARENT} || die;
|
||||||
TRACE "config: context changed to: $cur->{CONTEXT}";
|
TRACE "config: context changed to: $cur->{CONTEXT}";
|
||||||
}
|
}
|
||||||
if($cur->{CONTEXT} ne "subvolume") {
|
|
||||||
ERROR "Target keyword outside subvolume context, in \"$file\" line $.";
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
if($value =~ /^(\S+)\s+(\S+)$/)
|
if($value =~ /^(\S+)\s+(\S+)$/)
|
||||||
{
|
{
|
||||||
my ($target_type, $droot) = ($1, $2);
|
my ($target_type, $droot) = ($1, $2);
|
||||||
|
@ -1901,15 +1897,15 @@ sub parse_config_line($$$$$)
|
||||||
|
|
||||||
$droot =~ s/\/+$//; # remove trailing slash
|
$droot =~ s/\/+$//; # remove trailing slash
|
||||||
$droot =~ s/^\/+/\//; # sanitize leading slash
|
$droot =~ s/^\/+/\//; # sanitize leading slash
|
||||||
TRACE "config: adding target \"$droot\" (type=$target_type) to subvolume context: $cur->{url}";
|
TRACE "config: adding target \"$droot\" (type=$target_type) to $cur->{CONTEXT} context" . ($cur->{url} ? ": $cur->{url}" : "");
|
||||||
die unless($cur->{CONTEXT} eq "subvolume");
|
|
||||||
my $target = { CONTEXT => "target",
|
my $target = { CONTEXT => "target",
|
||||||
PARENT => $cur,
|
PARENT => $cur,
|
||||||
target_type => $target_type,
|
target_type => $target_type,
|
||||||
url => $droot,
|
url => $droot,
|
||||||
};
|
};
|
||||||
$cur->{SUBSECTION} //= [];
|
# NOTE: target sections are propagated to the apropriate SUBSECTION in _config_propagate_target()
|
||||||
push(@{$cur->{SUBSECTION}}, $target);
|
$cur->{TARGET} //= [];
|
||||||
|
push(@{$cur->{TARGET}}, $target);
|
||||||
$cur = $target;
|
$cur = $target;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1927,9 +1923,56 @@ sub parse_config_line($$$$$)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sub _config_propagate_target
|
||||||
|
{
|
||||||
|
my $cur = shift;
|
||||||
|
foreach my $subsection (@{$cur->{SUBSECTION}}) {
|
||||||
|
my @propagate_target;
|
||||||
|
foreach my $target (@{$cur->{TARGET}}) {
|
||||||
|
TRACE "propagating target \"$target->{url}\" from $cur->{CONTEXT} context to: $subsection->{CONTEXT} $subsection->{url}";
|
||||||
|
die if($target->{SUBSECTION});
|
||||||
|
|
||||||
|
# don't propagate if a target of same target_type and url already exists in subsection
|
||||||
|
if($subsection->{TARGET} &&
|
||||||
|
grep({ ($_->{url} eq $target->{url}) && ($_->{target_type} eq $target->{target_type}) } @{$subsection->{TARGET}}))
|
||||||
|
{
|
||||||
|
DEBUG "Skip propagation of \"target $target->{target_type} $target->{url}\" from $cur->{CONTEXT} context to \"$subsection->{CONTEXT} $subsection->{url}\": same target already exists";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
my %copy = ( %$target, PARENT => $cur );
|
||||||
|
# foreach my $key (keys %copy) {
|
||||||
|
# # config keys which are strongly related to target section are
|
||||||
|
# # superseded by their presence in later defined sections.
|
||||||
|
# next unless($key =~ /^target_/);
|
||||||
|
# next if($key eq "target_type"); # not really necessary, but make sure the target_type is not deleted
|
||||||
|
# if(exists($subsection->{$key})) {
|
||||||
|
# TRACE "delete superseded config option from target: $key=" . ($copy{$key} // "<undef>");
|
||||||
|
# delete $copy{$key};
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
push @propagate_target, \%copy;
|
||||||
|
}
|
||||||
|
$subsection->{TARGET} //= [];
|
||||||
|
unshift @{$subsection->{TARGET}}, @propagate_target; # maintain config order: propagated targets go in front of already defined targets
|
||||||
|
if($subsection->{CONTEXT} eq "subvolume") {
|
||||||
|
# finally create missing SUBSECTION in subvolume context
|
||||||
|
die if($subsection->{SUBSECTION});
|
||||||
|
$subsection->{SUBSECTION} = $subsection->{TARGET};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# recurse into SUBSECTION
|
||||||
|
_config_propagate_target($subsection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete $cur->{TARGET};
|
||||||
|
return $cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
sub init_config(@)
|
sub init_config(@)
|
||||||
{
|
{
|
||||||
my %config_root = ( CONTEXT => "root", @_ );
|
my %config_root = ( CONTEXT => "root", SUBSECTION => [], @_ );
|
||||||
|
|
||||||
# set defaults
|
# set defaults
|
||||||
foreach (keys %config_options) {
|
foreach (keys %config_options) {
|
||||||
|
@ -1989,6 +2032,8 @@ sub parse_config(@)
|
||||||
}
|
}
|
||||||
close FILE || ERROR "Failed to close configuration file: $!";
|
close FILE || ERROR "Failed to close configuration file: $!";
|
||||||
|
|
||||||
|
_config_propagate_target($root);
|
||||||
|
|
||||||
return $root;
|
return $root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue