Skip to content

Commit

Permalink
Do not require user to be specified for syncoid
Browse files Browse the repository at this point in the history
Extends syncoid remote capabilities to match that of ssh as closely as
possible: allow a remote dataset to be specified without a username.

 - Detect if a remote reference is possible by looking for a : before
   any / characters.
 - Check if there are any pool names that might conflict with this
   name. E.g., 'weird:symbol/ds' might refer to the pool "symbol" on
   host "weird", and dataset ds. OR it might refer to the local pool
   "weird:symbol" and dataset ds.
 - Prefer local pools, matching existing behavior. No preexisting
   functioning configurations will break.
 - The name of the control socket is changed slightly.
 - A bug in the handling of remote datasets with colons in the name
   is addressed.

Signed-off-by: Antonio Russo <[email protected]>
  • Loading branch information
aerusso committed Nov 1, 2020
1 parent 9544ea7 commit f397687
Showing 1 changed file with 41 additions and 8 deletions.
49 changes: 41 additions & 8 deletions syncoid
Original file line number Diff line number Diff line change
Expand Up @@ -1420,20 +1420,53 @@ sub targetexists {
sub getssh {
my $fs = shift;

my $rhost;
my $rhost = "";
my $isroot;
my $socket;
my $remoteuser = "";

# if we got passed something with an @ in it, we assume it's an ssh connection, eg root@myotherbox
if ($fs =~ /\@/) {
$rhost = $fs;
$fs =~ s/^\S*\@\S*://;
$fs =~ s/^[^\@:]*\@[^\@:]*://;
$rhost =~ s/:\Q$fs\E$//;
my $remoteuser = $rhost;
$remoteuser =~ s/\@.*$//;
$remoteuser = $rhost;
$remoteuser =~ s/\@.*$//;
# do not require a username to be specified
$rhost =~ s/^@//;
} elsif ($fs =~ m{^[^/]*:}) {
# if we got passed something with an : in it, BEFORE any forward slash
# (i.e., not in a dataset name) it MAY be an ssh connection
# but we need to check if there is a pool with that name
my $pool = $fs;
$pool =~ s%/.*$%%;
my ($pools, $error, $exit) = capture {
system("$zfscmd list -d0 -H -oname");
};
$rhost = $fs;
if ($exit != 0) {
warn "Unable to enumerate pools (is zfs available?)";
} else {
foreach (split(/\n/,$pools)) {
if ($_ eq $pool) {
# there's a pool with this name.
$rhost = "";
last;
}
}
}
if ($rhost ne "") {
# there's no pool that might conflict with this
$rhost =~ s/:.*$//;
$fs =~ s/\Q$rhost\E://;
}
}

if ($rhost ne "") {
if ($remoteuser eq 'root' || $args{'no-privilege-elevation'}) { $isroot = 1; } else { $isroot = 0; }
# now we need to establish a persistent master SSH connection
$socket = "/tmp/syncoid-$remoteuser-$rhost-" . time();
$socket = "/tmp/syncoid-$rhost-" . time();

open FH, "$sshcmd -M -S $socket -o ControlPersist=1m $args{'sshport'} $rhost exit |";
close FH;

Expand Down Expand Up @@ -1882,9 +1915,9 @@ syncoid - ZFS snapshot replication tool
=head1 SYNOPSIS
syncoid [options]... SOURCE TARGET
or syncoid [options]... SOURCE USER@HOST:TARGET
or syncoid [options]... USER@HOST:SOURCE TARGET
or syncoid [options]... USER@HOST:SOURCE USER@HOST:TARGET
or syncoid [options]... SOURCE [[USER]@]HOST:TARGET
or syncoid [options]... [[USER]@]HOST:SOURCE TARGET
or syncoid [options]... [[USER]@]HOST:SOURCE [[USER]@]HOST:TARGET
SOURCE Source ZFS dataset. Can be either local or remote
TARGET Target ZFS dataset. Can be either local or remote
Expand Down

0 comments on commit f397687

Please sign in to comment.