added sudo cmds everywhere hopefully...

This commit is contained in:
Jim Salter 2015-03-21 19:51:28 -04:00
parent 3604fcab0a
commit 63e32196d0
1 changed files with 59 additions and 38 deletions

97
syncoid
View File

@ -38,8 +38,13 @@ my $lscmd = '/bin/ls';
my ($sourcehost,$sourcefs,$sourceisroot) = getssh($rawsourcefs); my ($sourcehost,$sourcefs,$sourceisroot) = getssh($rawsourcefs);
my ($targethost,$targetfs,$targetisroot) = getssh($rawtargetfs); my ($targethost,$targetfs,$targetisroot) = getssh($rawtargetfs);
my $sourcesudocmd;
my $targetsudocmd;
if ($sourceisroot) { $sourcesudocmd = ''; } else { $sourcesudocmd = $sudocmd; }
if ($targetisroot) { $targetsudocmd = ''; } else { $targetsudocmd = $sudocmd; }
# make sure target is not currently in receive. # make sure target is not currently in receive.
if (iszfsbusy($targethost,$targetfs)) { if (iszfsbusy($targethost,$targetfs,$targetisroot)) {
die "Cannot sync now: $targetfs is already target of a zfs receive process.\n"; die "Cannot sync now: $targetfs is already target of a zfs receive process.\n";
} }
@ -49,7 +54,7 @@ if (iszfsbusy($targethost,$targetfs)) {
my %avail = checkcommands(); my %avail = checkcommands();
$sshcmd = "$sshcmd $sshcipher"; $sshcmd = "$sshcmd $sshcipher";
# does the target filesystem exist yet? # does the target filesystem exist yet?
my $targetexists = targetexists($targethost,$targetfs); my $targetexists = targetexists($targethost,$targetfs,$targetisroot);
# build hashes of the snaps on the source and target filesystems. # build hashes of the snaps on the source and target filesystems.
my %snaps; my %snaps;
@ -71,17 +76,17 @@ if (! $targetexists) {
# do an initial sync from the oldest source snapshot # do an initial sync from the oldest source snapshot
# THEN do an -I to the newest # THEN do an -I to the newest
my $oldestsnap = getoldestsnapshot(\%snaps); my $oldestsnap = getoldestsnapshot(\%snaps);
my $sendcmd = "$zfscmd send $sourcefs\@$oldestsnap"; my $sendcmd = "$sourcesudocmd $zfscmd send $sourcefs\@$oldestsnap";
my $recvcmd = "$zfscmd receive -F $targetfs"; my $recvcmd = "$targetsudocmd $zfscmd receive -F $targetfs";
my $pvsize = getsendsize("$sourcefs\@$oldestsnap"); my $pvsize = getsendsize("$sourcefs\@$oldestsnap",$sourceisroot);
my $disp_pvsize = readablebytes($pvsize); my $disp_pvsize = readablebytes($pvsize);
if ($pvsize == 0) { $disp_pvsize = 'UNKNOWN'; } if ($pvsize == 0) { $disp_pvsize = 'UNKNOWN'; }
my $synccmd = buildsynccmd($sendcmd,$recvcmd,$pvsize); my $synccmd = buildsynccmd($sendcmd,$recvcmd,$pvsize,$sourceisroot,$targetisroot);
print "Sending oldest full snapshot $oldestsnap (~ $disp_pvsize) to new target filesystem:\n"; print "Sending oldest full snapshot $oldestsnap (~ $disp_pvsize) to new target filesystem:\n";
if ($debug) { print "DEBUG: $synccmd\n"; } if ($debug) { print "DEBUG: $synccmd\n"; }
# make sure target is (still) not currently in receive. # make sure target is (still) not currently in receive.
if (iszfsbusy($targethost,$targetfs)) { if (iszfsbusy($targethost,$targetfs,$targetisroot)) {
die "Cannot sync now: $targetfs is already target of a zfs receive process.\n"; die "Cannot sync now: $targetfs is already target of a zfs receive process.\n";
} }
system($synccmd); system($synccmd);
@ -91,17 +96,17 @@ if (! $targetexists) {
if ($oldestsnap ne $newsyncsnap) { if ($oldestsnap ne $newsyncsnap) {
# get current readonly status of target, then set it to on during sync # get current readonly status of target, then set it to on during sync
$originaltargetreadonly = getzfsvalue($targethost,$targetfs,'readonly'); $originaltargetreadonly = getzfsvalue($targethost,$targetfs,$targetisroot,'readonly');
setzfsvalue($targethost,$targetfs,'readonly','on'); setzfsvalue($targethost,$targetfs,$targetisroot,'readonly','on');
$sendcmd = "$zfscmd send -I $sourcefs\@$oldestsnap $sourcefs\@$newsyncsnap"; $sendcmd = "$zfscmd send -I $sourcefs\@$oldestsnap $sourcefs\@$newsyncsnap";
$pvsize = getsendsize("$sourcefs\@$oldestsnap","$sourcefs\@$newsyncsnap"); $pvsize = getsendsize("$sourcefs\@$oldestsnap","$sourcefs\@$newsyncsnap",$sourceisroot);
$disp_pvsize = readablebytes($pvsize); $disp_pvsize = readablebytes($pvsize);
if ($pvsize == 0) { $disp_pvsize = "UNKNOWN"; } if ($pvsize == 0) { $disp_pvsize = "UNKNOWN"; }
$synccmd = buildsynccmd($sendcmd,$recvcmd,$pvsize); $synccmd = buildsynccmd($sendcmd,$recvcmd,$pvsize,$sourceisroot,$targetisroot);
# make sure target is (still) not currently in receive. # make sure target is (still) not currently in receive.
if (iszfsbusy($targethost,$targetfs)) { if (iszfsbusy($targethost,$targetfs,$targetisroot)) {
die "Cannot sync now: $targetfs is already target of a zfs receive process.\n"; die "Cannot sync now: $targetfs is already target of a zfs receive process.\n";
} }
@ -110,7 +115,7 @@ if (! $targetexists) {
system($synccmd); system($synccmd);
# restore original readonly value to target after sync complete # restore original readonly value to target after sync complete
setzfsvalue($targethost,$targetfs,'readonly',$originaltargetreadonly); setzfsvalue($targethost,$targetfs,$targetisroot,'readonly',$originaltargetreadonly);
} }
} else { } else {
# find most recent matching snapshot and do an -I # find most recent matching snapshot and do an -I
@ -118,12 +123,12 @@ if (! $targetexists) {
# get current readonly status of target, then set it to on during sync # get current readonly status of target, then set it to on during sync
$originaltargetreadonly = getzfsvalue($targethost,$targetfs,'readonly'); $originaltargetreadonly = getzfsvalue($targethost,$targetfs,'readonly');
setzfsvalue($targethost,$targetfs,'readonly','on'); setzfsvalue($targethost,$targetfs,$targetisroot,'readonly','on');
my $matchingsnap = getmatchingsnapshot(\%snaps); my $matchingsnap = getmatchingsnapshot(\%snaps);
# make sure target is (still) not currently in receive. # make sure target is (still) not currently in receive.
if (iszfsbusy($targethost,$targetfs)) { if (iszfsbusy($targethost,$targetfs,$targetisroot)) {
die "Cannot sync now: $targetfs is already target of a zfs receive process.\n"; die "Cannot sync now: $targetfs is already target of a zfs receive process.\n";
} }
@ -135,12 +140,12 @@ if (! $targetexists) {
system ("$zfscmd rollback -R $targetfs\@$matchingsnap"); system ("$zfscmd rollback -R $targetfs\@$matchingsnap");
} }
my $sendcmd = "$zfscmd send -I $sourcefs\@$matchingsnap $sourcefs\@$newsyncsnap"; my $sendcmd = "$sourcesudocmd $zfscmd send -I $sourcefs\@$matchingsnap $sourcefs\@$newsyncsnap";
my $recvcmd = "$zfscmd receive $targetfs"; my $recvcmd = "$targetsudocmd $zfscmd receive $targetfs";
my $pvsize = getsendsize("$sourcefs\@$matchingsnap","$sourcefs\@$newsyncsnap"); my $pvsize = getsendsize("$sourcefs\@$matchingsnap","$sourcefs\@$newsyncsnap",$sourceisroot);
my $disp_pvsize = readablebytes($pvsize); my $disp_pvsize = readablebytes($pvsize);
if ($pvsize == 0) { $disp_pvsize = "UNKNOWN"; } if ($pvsize == 0) { $disp_pvsize = "UNKNOWN"; }
my $synccmd = buildsynccmd($sendcmd,$recvcmd,$pvsize); my $synccmd = buildsynccmd($sendcmd,$recvcmd,$pvsize,$sourceisroot,$targetisroot);
print "Sending incremental $matchingsnap ... $newsyncsnap (~ $disp_pvsize):\n"; print "Sending incremental $matchingsnap ... $newsyncsnap (~ $disp_pvsize):\n";
if ($debug) { print "DEBUG: $synccmd\n"; } if ($debug) { print "DEBUG: $synccmd\n"; }
@ -151,8 +156,8 @@ if (! $targetexists) {
} }
# prune obsolete sync snaps on source and target. # prune obsolete sync snaps on source and target.
pruneoldsyncsnaps($sourcehost,$sourcefs,$newsyncsnap,keys %{ $snaps{'source'}}); pruneoldsyncsnaps($sourcehost,$sourcefs,$newsyncsnap,$sourceisroot,keys %{ $snaps{'source'}});
pruneoldsyncsnaps($targethost,$targetfs,$newsyncsnap,keys %{ $snaps{'target'}}); pruneoldsyncsnaps($targethost,$targetfs,$newsyncsnap,$targetisroot,keys %{ $snaps{'target'}});
# debug: print contents of %snaps to stdout # debug: print contents of %snaps to stdout
#dumphash(\%snaps); #dumphash(\%snaps);
@ -382,7 +387,7 @@ sub checkcommands {
} }
sub iszfsbusy { sub iszfsbusy {
my ($rhost,$fs) = @_; my ($rhost,$fs,$isroot) = @_;
if ($rhost ne '') { $rhost = "$sshcmd $rhost"; } if ($rhost ne '') { $rhost = "$sshcmd $rhost"; }
if ($debug) { print "DEBUG: checking to see if $fs on $rhost is already in zfs receive using $rhost $pscmd axo args= ...\n"; } if ($debug) { print "DEBUG: checking to see if $fs on $rhost is already in zfs receive using $rhost $pscmd axo args= ...\n"; }
@ -404,18 +409,22 @@ sub iszfsbusy {
} }
sub setzfsvalue { sub setzfsvalue {
my ($rhost,$fs,$property,$value) = @_; my ($rhost,$fs,$isroot,$property,$value) = @_;
if ($rhost ne '') { $rhost = "$sshcmd $rhost"; } if ($rhost ne '') { $rhost = "$sshcmd $rhost"; }
if ($debug) { print "DEBUG: setting $property to $value on $fs...\n"; } if ($debug) { print "DEBUG: setting $property to $value on $fs...\n"; }
system("$rhost $zfscmd set $property=$value $fs"); my $mysudocmd;
if ($isroot) { $mysudocmd = ''; } else { $mysudocmd = $sudocmd; }
system("$rhost $mysudocmd $zfscmd set $property=$value $fs");
return; return;
} }
sub getzfsvalue { sub getzfsvalue {
my ($rhost,$fs,$property) = @_; my ($rhost,$fs,$isroot,$property) = @_;
if ($rhost ne '') { $rhost = "$sshcmd $rhost"; } if ($rhost ne '') { $rhost = "$sshcmd $rhost"; }
if ($debug) { print "DEBUG: getting current value of $property on $fs...\n"; } if ($debug) { print "DEBUG: getting current value of $property on $fs...\n"; }
open FH, "$rhost $zfscmd get -H $property $fs |"; my $mysudocmd;
if ($isroot) { $mysudocmd = ''; } else { $mysudocmd = $sudocmd; }
open FH, "$rhost $mysudocmd $zfscmd get -H $property $fs |";
my $value = <FH>; my $value = <FH>;
close FH; close FH;
my @values = split(/\s/,$value); my @values = split(/\s/,$value);
@ -448,7 +457,7 @@ sub getoldestsnapshot {
} }
sub buildsynccmd { sub buildsynccmd {
my ($sendcmd,$recvcmd,$pvsize) = @_; my ($sendcmd,$recvcmd,$pvsize,$sourceisroot,$targetisroot) = @_;
# here's where it gets fun: figuring out when to compress and decompress. # here's where it gets fun: figuring out when to compress and decompress.
# to make this work for all possible combinations, you may have to decompress # to make this work for all possible combinations, you may have to decompress
# AND recompress across the pipe viewer. FUN. # AND recompress across the pipe viewer. FUN.
@ -489,7 +498,7 @@ sub buildsynccmd {
if ($avail{'targetmbuffer'}) { $synccmd .= "$mbuffercmd $args{'target-bwlimit'} $mbufferoptions | "; } if ($avail{'targetmbuffer'}) { $synccmd .= "$mbuffercmd $args{'target-bwlimit'} $mbufferoptions | "; }
if ($avail{'compress'}) { $synccmd .= "$args{'decompresscmd'} | "; } if ($avail{'compress'}) { $synccmd .= "$args{'decompresscmd'} | "; }
if ($avail{'localpv'}) { $synccmd .= "$pvcmd -s $pvsize | "; } if ($avail{'localpv'}) { $synccmd .= "$pvcmd -s $pvsize | "; }
$synccmd .= $recvcmd; $synccmd .= "$recvcmd";
} else { } else {
#remote source, remote target... weird, but whatever, I'm not here to judge you. #remote source, remote target... weird, but whatever, I'm not here to judge you.
#$synccmd = "$sshcmd $sourcehost '$sendcmd | $args{'compresscmd'} | $mbuffercmd' | $args{'decompresscmd'} | $pvcmd | $args{'compresscmd'} | $mbuffercmd | $sshcmd $targethost '$args{'decompresscmd'} | $mbuffercmd | $recvcmd'"; #$synccmd = "$sshcmd $sourcehost '$sendcmd | $args{'compresscmd'} | $mbuffercmd' | $args{'decompresscmd'} | $pvcmd | $args{'compresscmd'} | $mbuffercmd | $sshcmd $targethost '$args{'decompresscmd'} | $mbuffercmd | $recvcmd'";
@ -510,10 +519,13 @@ sub buildsynccmd {
} }
sub pruneoldsyncsnaps { sub pruneoldsyncsnaps {
my ($rhost,$fs,$newsyncsnap,@snaps) = @_; my ($rhost,$fs,$newsyncsnap,$isroot,@snaps) = @_;
if ($rhost ne '') { $rhost = "$sshcmd $rhost"; } if ($rhost ne '') { $rhost = "$sshcmd $rhost"; }
my $hostid = hostname(); my $hostid = hostname();
my $mysudocmd;
if ($isroot) { $mysudocmd=''; } else { $mysudocmd = $sudocmd; }
my @prunesnaps; my @prunesnaps;
# only prune snaps beginning with syncoid and our own hostname # only prune snaps beginning with syncoid and our own hostname
@ -534,7 +546,7 @@ sub pruneoldsyncsnaps {
my $prunecmd; my $prunecmd;
foreach my $snap(@prunesnaps) { foreach my $snap(@prunesnaps) {
$counter ++; $counter ++;
$prunecmd .= "$zfscmd destroy $fs\@$snap; "; $prunecmd .= "$mysudocmd $zfscmd destroy $fs\@$snap; ";
if ($counter > $maxsnapspercmd) { if ($counter > $maxsnapspercmd) {
$prunecmd =~ s/\; $//; $prunecmd =~ s/\; $//;
if ($rhost ne '') { $prunecmd = '"' . $prunecmd . '"'; } if ($rhost ne '') { $prunecmd = '"' . $prunecmd . '"'; }
@ -569,21 +581,25 @@ sub getmatchingsnapshot {
} }
sub newsyncsnap { sub newsyncsnap {
my ($rhost,$fs) = @_; my ($rhost,$fs,$isroot) = @_;
if ($rhost ne '') { $rhost = "$sshcmd $rhost"; } if ($rhost ne '') { $rhost = "$sshcmd $rhost"; }
my $mysudocmd;
if ($isroot) { $mysudocmd = ''; } else { $mysudocmd = $sudocmd; }
my $hostid = hostname(); my $hostid = hostname();
my %date = getdate(); my %date = getdate();
my $snapname = "syncoid\_$hostid\_$date{'stamp'}"; my $snapname = "syncoid\_$hostid\_$date{'stamp'}";
my $snapcmd = "$rhost $zfscmd snapshot $fs\@$snapname\n"; my $snapcmd = "$rhost $mysudocmd $zfscmd snapshot $fs\@$snapname\n";
system($snapcmd); system($snapcmd);
return $snapname; return $snapname;
} }
sub targetexists { sub targetexists {
my ($rhost,$fs) = @_; my ($rhost,$fs,$isroot) = @_;
if ($rhost ne '') { $rhost = "$sshcmd $rhost"; } if ($rhost ne '') { $rhost = "$sshcmd $rhost"; }
my $mysudocmd;
if ($isroot) { $mysudocmd = ''; } else { $mysudocmd = $sudocmd; }
if ($debug) { print "DEBUG: checking to see if target filesystem exists...\n"; } if ($debug) { print "DEBUG: checking to see if target filesystem exists...\n"; }
open FH, "$rhost $zfscmd get -H name $fs 2>&1 |"; open FH, "$rhost $mysudocmd $zfscmd get -H name $fs 2>&1 |";
$targetexists = <FH>; $targetexists = <FH>;
close FH; close FH;
my $exit = $?; my $exit = $?;
@ -618,11 +634,13 @@ sub dumphash() {
} }
sub getsnaps() { sub getsnaps() {
my ($snaps,$type,$rhost,$fs) = @_; my ($snaps,$type,$rhost,$fs,$isroot) = @_;
my $mysudocmd;
if ($isroot) { $mysudocmd = ''; } else { $mysudocmd = $sudocmd; }
if ($rhost ne '') { $rhost = "$sshcmd $rhost"; } if ($rhost ne '') { $rhost = "$sshcmd $rhost"; }
my $getsnapcmd = "$rhost $zfscmd get -Hpd 1 creation $fs |"; my $getsnapcmd = "$rhost $mysudocmd $zfscmd get -Hpd 1 creation $fs |";
if ($debug) { print "DEBUG: getting list of snapshots on $fs...\n"; } if ($debug) { print "DEBUG: getting list of snapshots on $fs...\n"; }
open FH, $getsnapcmd; open FH, $getsnapcmd;
my @rawsnaps = <FH>; my @rawsnaps = <FH>;
@ -646,7 +664,10 @@ sub getsnaps() {
sub getsendsize { sub getsendsize {
my ($snap1,$snap2) = @_; my ($snap1,$snap2,$isroot) = @_;
my $mysudocmd;
if ($isroot) { $mysudocmd = ''; } else { $mysudocmd = $sudocmd; }
my $snaps; my $snaps;
if ($snap2 ne '') { if ($snap2 ne '') {
@ -663,7 +684,7 @@ sub getsendsize {
} }
if ($debug) { print "DEBUG: getting estimated transfer size from source $sourcehost...\n"; } if ($debug) { print "DEBUG: getting estimated transfer size from source $sourcehost...\n"; }
open FH, "$sourcessh $zfscmd send -nP $snaps 2>&1 |"; open FH, "$sourcessh $mysudocmd $zfscmd send -nP $snaps 2>&1 |";
my @rawsize = <FH>; my @rawsize = <FH>;
close FH; close FH;
my $exit = $?; my $exit = $?;