App-Yabsm
view release on metacpan or search on metacpan
lib/App/Yabsm/Backup/SSH.pm view on Meta::CPAN
# Like &do_ssh_backup_bootstrap but only perform the bootstrap if it hasn't
# been performed yet.
arg_count_or_die(3, 3, @_);
my $ssh = shift;
my $ssh_backup = shift;
my $config_ref = shift;
$ssh //= new_ssh_conn($ssh_backup, $config_ref);
my $local_boot_snap = the_local_bootstrap_snapshot($ssh_backup, 'ssh', $config_ref);
my $remote_boot_snap = the_remote_bootstrap_snapshot($ssh, $ssh_backup, $config_ref);
unless ($local_boot_snap && $remote_boot_snap) {
$local_boot_snap = do_ssh_backup_bootstrap($ssh, $ssh_backup, $config_ref);
}
return $local_boot_snap;
}
sub the_remote_bootstrap_snapshot {
# Return the remote bootstrap snapshot for $ssh_backup if it exists and
# return undef otherwise. Die if we find multiple bootstrap snapshots.
arg_count_or_die(3, 3, @_);
my $ssh = shift;
my $ssh_backup = shift;
my $config_ref = shift;
$ssh //= new_ssh_conn($ssh_backup, $config_ref);
my $remote_backup_dir = ssh_backup_dir($ssh_backup, undef, $config_ref);
my @boot_snaps = grep { is_snapshot_name($_, ONLY_BOOTSTRAP => 1) } ssh_system_or_die($ssh, "ls -1 -a '$remote_backup_dir'");
map { chomp $_ ; $_ = "$remote_backup_dir/$_" } @boot_snaps;
if (0 == @boot_snaps) {
return undef;
}
elsif (1 == @boot_snaps) {
return $boot_snaps[0];
}
else {
my $ssh_dest = ssh_backup_ssh_dest($ssh_backup, $config_ref);
die "yabsm: ssh error: $ssh_dest: found multiple remote bootstrap snapshots in '$remote_backup_dir'\n";
}
}
sub new_ssh_conn {
# Return a Net::OpenSSH connection object to $ssh_backup's ssh destination or
# die if a connection cannot be established.
arg_count_or_die(2, 2, @_);
my $ssh_backup = shift;
my $config_ref = shift;
my $home_dir = (getpwuid $<)[7]
or die q(yabsm: error: user ').scalar(getpwuid $<).q(' does not have a home directory to hold SSH keys);
my $pub_key = "$home_dir/.ssh/id_ed25519.pub";
my $priv_key = "$home_dir/.ssh/id_ed25519";
unless (-f $pub_key) {
my $username = getpwuid $<;
die "yabsm: error: cannot not find '$username' users SSH public SSH key '$pub_key'\n";
}
unless (-f $priv_key) {
my $username = getpwuid $<;
die "yabsm: error: cannot not find '$username' users private SSH key '$priv_key'\n";
}
my $ssh_dest = ssh_backup_ssh_dest($ssh_backup, $config_ref);
my $ssh = Net::OpenSSH->new(
$ssh_dest,
master_opts => [ '-q' ], # quiet
batch_mode => 1, # Key based auth only
ctl_dir => '/tmp',
remote_shell => 'sh',
);
if ($ssh->error) {
die "yabsm: ssh error: $ssh_dest: cannot establish SSH connection: ".$ssh->error."\n";
}
return $ssh;
}
sub ssh_system_or_die {
# Like Net::OpenSSH::capture but die if the command fails.
arg_count_or_die(2, 3, @_);
my $ssh = shift;
my %opts = ref $_[0] eq 'HASH' ? %{ shift() } : ();
my $cmd = shift;
wantarray ? my @out = $ssh->capture(\%opts, $cmd) : my $out = $ssh->capture(\%opts, $cmd);
if ($ssh->error) {
my $host = $ssh->get_host;
die "yabsm: ssh error: $host: remote command '$cmd' failed:".$ssh->error."\n";
}
return wantarray ? @out : $out;
}
sub check_ssh_backup_config_or_die {
# Ensure that the $ssh_backup's ssh destination server is configured
# properly and die with useful errors if not.
arg_count_or_die(3, 3, @_);
my $ssh = shift;
my $ssh_backup = shift;
my $config_ref = shift;
$ssh //= new_ssh_conn($ssh_backup, $config_ref);
my $remote_backup_dir = ssh_backup_dir($ssh_backup, undef, $config_ref);
my $ssh_dest = ssh_backup_ssh_dest($ssh_backup, $config_ref);
my (undef, $stderr) = $ssh->capture2(qq(
ERRORS=''
add_error() {
( run in 0.651 second using v1.01-cache-2.11-cpan-6aa56a78535 )