mirror of https://github.com/jimsalterjrs/sanoid
implemented clone handling (try to recreate on target instead of full replication)
This commit is contained in:
parent
22160deb8e
commit
c8b880c5e2
116
syncoid
116
syncoid
|
|
@ -104,17 +104,59 @@ my $exitcode = 0;
|
|||
## replication ##
|
||||
|
||||
if (!defined $args{'recursive'}) {
|
||||
syncdataset($sourcehost, $sourcefs, $targethost, $targetfs);
|
||||
syncdataset($sourcehost, $sourcefs, $targethost, $targetfs, undef);
|
||||
} else {
|
||||
if ($debug) { print "DEBUG: recursive sync of $sourcefs.\n"; }
|
||||
my @datasets = getchilddatasets($sourcehost, $sourcefs, $sourceisroot);
|
||||
foreach my $dataset(@datasets) {
|
||||
|
||||
my @deferred;
|
||||
|
||||
foreach my $datasetProperties(@datasets) {
|
||||
my $dataset = $datasetProperties->{'name'};
|
||||
my $origin = $datasetProperties->{'origin'};
|
||||
if ($origin eq "-") {
|
||||
$origin = undef;
|
||||
} else {
|
||||
# check if clone source is replicated too
|
||||
my @values = split(/@/, $origin, 2);
|
||||
my $srcdataset = $values[0];
|
||||
|
||||
my $found = 0;
|
||||
foreach my $datasetProperties(@datasets) {
|
||||
if ($datasetProperties->{'name'} eq $srcdataset) {
|
||||
$found = 1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
if ($found == 0) {
|
||||
# clone source is not replicated, do a full replication
|
||||
$origin = undef;
|
||||
} else {
|
||||
# clone source is replicated, defer until all non clones are replicated
|
||||
push @deferred, $datasetProperties;
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
$dataset =~ s/\Q$sourcefs\E//;
|
||||
chomp $dataset;
|
||||
my $childsourcefs = $sourcefs . $dataset;
|
||||
my $childtargetfs = $targetfs . $dataset;
|
||||
# print "syncdataset($sourcehost, $childsourcefs, $targethost, $childtargetfs); \n";
|
||||
syncdataset($sourcehost, $childsourcefs, $targethost, $childtargetfs);
|
||||
syncdataset($sourcehost, $childsourcefs, $targethost, $childtargetfs, $origin);
|
||||
}
|
||||
|
||||
# replicate cloned datasets and if this is the initial run, recreate them on the target
|
||||
foreach my $datasetProperties(@deferred) {
|
||||
my $dataset = $datasetProperties->{'name'};
|
||||
my $origin = $datasetProperties->{'origin'};
|
||||
|
||||
$dataset =~ s/\Q$sourcefs\E//;
|
||||
chomp $dataset;
|
||||
my $childsourcefs = $sourcefs . $dataset;
|
||||
my $childtargetfs = $targetfs . $dataset;
|
||||
syncdataset($sourcehost, $childsourcefs, $targethost, $childtargetfs, $origin);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -147,37 +189,51 @@ sub getchilddatasets {
|
|||
$fsescaped = escapeshellparam($fsescaped);
|
||||
}
|
||||
|
||||
my $getchildrencmd = "$rhost $mysudocmd $zfscmd list -o name -t filesystem,volume -Hr $fsescaped |";
|
||||
my $getchildrencmd = "$rhost $mysudocmd $zfscmd list -o name,origin -t filesystem,volume -Hr $fsescaped |";
|
||||
if ($debug) { print "DEBUG: getting list of child datasets on $fs using $getchildrencmd...\n"; }
|
||||
open FH, $getchildrencmd;
|
||||
my @children = <FH>;
|
||||
close FH;
|
||||
|
||||
if (defined $args{'skip-parent'}) {
|
||||
# parent dataset is the first element
|
||||
shift @children;
|
||||
if (! open FH, $getchildrencmd) {
|
||||
die "ERROR: list command failed!\n";
|
||||
}
|
||||
|
||||
if (defined $args{'exclude'}) {
|
||||
my $excludes = $args{'exclude'};
|
||||
foreach (@$excludes) {
|
||||
for my $i ( 0 .. $#children ) {
|
||||
if ($children[$i] =~ /$_/) {
|
||||
if ($debug) { print "DEBUG: excluded $children[$i] because of $_\n"; }
|
||||
undef $children[$i]
|
||||
my @children;
|
||||
my $first = 1;
|
||||
|
||||
DATASETS: while(<FH>) {
|
||||
chomp;
|
||||
|
||||
if (defined $args{'skip-parent'} && $first eq 1) {
|
||||
# parent dataset is the first element
|
||||
$first = 0;
|
||||
next;
|
||||
}
|
||||
|
||||
my ($dataset, $origin) = /^([^\t]+)\t([^\t]+)/;
|
||||
|
||||
if (defined $args{'exclude'}) {
|
||||
my $excludes = $args{'exclude'};
|
||||
foreach (@$excludes) {
|
||||
print("$dataset\n");
|
||||
if ($dataset =~ /$_/) {
|
||||
if ($debug) { print "DEBUG: excluded $dataset because of $_\n"; }
|
||||
next DATASETS;
|
||||
}
|
||||
}
|
||||
|
||||
@children = grep{ defined }@children;
|
||||
}
|
||||
|
||||
my %properties;
|
||||
$properties{'name'} = $dataset;
|
||||
$properties{'origin'} = $origin;
|
||||
|
||||
push @children, \%properties;
|
||||
}
|
||||
close FH;
|
||||
|
||||
return @children;
|
||||
}
|
||||
|
||||
sub syncdataset {
|
||||
|
||||
my ($sourcehost, $sourcefs, $targethost, $targetfs) = @_;
|
||||
my ($sourcehost, $sourcefs, $targethost, $targetfs, $origin) = @_;
|
||||
|
||||
my $sourcefsescaped = escapeshellparam($sourcefs);
|
||||
my $targetfsescaped = escapeshellparam($targetfs);
|
||||
|
|
@ -305,11 +361,25 @@ sub syncdataset {
|
|||
my $sendcmd = "$sourcesudocmd $zfscmd send $sourcefsescaped\@$oldestsnapescaped";
|
||||
my $recvcmd = "$targetsudocmd $zfscmd receive $receiveextraargs -F $targetfsescaped";
|
||||
|
||||
my $pvsize = getsendsize($sourcehost,"$sourcefs\@$oldestsnap",0,$sourceisroot);
|
||||
my $pvsize;
|
||||
if (defined $origin) {
|
||||
my $originescaped = escapeshellparam($origin);
|
||||
$sendcmd = "$sourcesudocmd $zfscmd send -i $originescaped $sourcefsescaped\@$oldestsnapescaped";
|
||||
my $streamargBackup = $args{'streamarg'};
|
||||
$args{'streamarg'} = "-i";
|
||||
$pvsize = getsendsize($sourcehost,$origin,"$sourcefs\@$oldestsnap",$sourceisroot);
|
||||
$args{'streamarg'} = $streamargBackup;
|
||||
} else {
|
||||
$pvsize = getsendsize($sourcehost,"$sourcefs\@$oldestsnap",0,$sourceisroot);
|
||||
}
|
||||
|
||||
my $disp_pvsize = readablebytes($pvsize);
|
||||
if ($pvsize == 0) { $disp_pvsize = 'UNKNOWN'; }
|
||||
my $synccmd = buildsynccmd($sendcmd,$recvcmd,$pvsize,$sourceisroot,$targetisroot);
|
||||
if (!$quiet) {
|
||||
if (defined $origin) {
|
||||
print "INFO: Clone is recreated on target $targetfs based on $origin\n";
|
||||
}
|
||||
if (!defined ($args{'no-stream'}) ) {
|
||||
print "INFO: Sending oldest full snapshot $sourcefs\@$oldestsnap (~ $disp_pvsize) to new target filesystem:\n";
|
||||
} else {
|
||||
|
|
@ -396,7 +466,7 @@ sub syncdataset {
|
|||
|
||||
# a resumed transfer will only be done to the next snapshot,
|
||||
# so do an normal sync cycle
|
||||
return syncdataset($sourcehost, $sourcefs, $targethost, $targetfs);
|
||||
return syncdataset($sourcehost, $sourcefs, $targethost, $targetfs, undef);
|
||||
}
|
||||
|
||||
# find most recent matching snapshot and do an -I
|
||||
|
|
|
|||
Loading…
Reference in New Issue