#!@PERL@
-# Copyright (c) 2008,2009 Zmanda, Inc. All Rights Reserved.
+# Copyright (c) 2008, 2009, 2010 Zmanda, Inc. All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 as published
use lib '@amperldir@';
use strict;
+use warnings;
use Getopt::Long;
package Amanda::Application::Amzfs_sendrecv;
use Amanda::Config qw( :init :getconf config_dir_relative );
use Amanda::Debug qw( :logging );
use Amanda::Paths;
-use Amanda::Util qw( :constants );
+use Amanda::Util qw( :constants quote_string );
sub new {
my $class = shift;
print "HOST YES\n";
print "DISK YES\n";
print "MAX-LEVEL 9\n";
- print "INDEX-LINE NO\n";
+ print "INDEX-LINE YES\n";
print "INDEX-XML NO\n";
print "MESSAGE-LINE YES\n";
print "MESSAGE-XML NO\n";
sub command_selfcheck {
my $self = shift;
+ $self->print_to_server("disk " . quote_string($self->{disk}));
+
+ $self->print_to_server("amzfs-sendrecv version " . $Amanda::Constants::VERSION,
+ $Amanda::Script_App::GOOD);
$self->zfs_set_value();
if (!defined $self->{device}) {
if ($self->{error_status} == $Amanda::Script_App::GOOD) {
$self->zfs_create_snapshot();
$self->zfs_destroy_snapshot();
- print "OK " . $self->{disk} . "\n";
print "OK " . $self->{device} . "\n";
}
sub command_backup {
my $self = shift;
- my $mesgout_fd;
- open($mesgout_fd, '>&=3') ||
- $self->print_to_server_and_die("Can't open mesgout_fd: $!",
- $Amanda::Script_App::ERROR);
- $self->{mesgout} = $mesgout_fd;
-
if ($#{$self->{include_list}} >= 0) {
$self->print_to_server("include-list not supported for backup",
$Amanda::Script_App::ERROR);
my $refsnapshotname = $self->zfs_find_snapshot_level($level-1);
debug "Referenced snapshot name: $refsnapshotname|";
if ($refsnapshotname ne "") {
- $cmd = "$self->{pfexec_cmd} $self->{zfs_path} send -i $refsnapshotname $self->{filesystem}\@$self->{snapshot} | $Amanda::Paths::amlibexecdir/teecount";
+ $cmd = "$self->{pfexec_cmd} $self->{zfs_path} send -i $self->{filesystem}\@$refsnapshotname $self->{filesystem}\@$self->{snapshot} | $Amanda::Paths::amlibexecdir/teecount";
} else {
$self->print_to_server_and_die("cannot backup snapshot '$self->{filesystem}\@$self->{snapshot}': reference snapshot doesn't exists for level $level", $Amanda::Script_App::ERROR);
}
$err = Symbol::gensym;
$pid = open3($wtr, '>&STDOUT', $err, $cmd);
close $wtr;
+
+ if (defined($self->{index})) {
+ my $indexout;
+ open($indexout, '>&=4') ||
+ $self->print_to_server_and_die("Can't open indexout: $!",
+ $Amanda::Script_App::ERROR);
+ print $indexout "/\n";
+ close($indexout);
+ }
+
$errmsg = <$err>;
waitpid $pid, 0;
close $err;
my($ksize) = int ($size/1024);
$ksize=32 if ($ksize<32);
- print $mesgout_fd "sendbackup: size $ksize\n";
- print $mesgout_fd "sendbackup: end\n";
+ print {$self->{mesgout}} "sendbackup: size $ksize\n";
+ print {$self->{mesgout}} "sendbackup: end\n";
# destroy all snapshot of this level and higher
$self->zfs_purge_snapshot($level, 9);
sub command_index_from_image {
}
-#sub command_restore {
-# my $self = shift;
-#
-#TODO
-#}
+sub command_restore {
+ my $self = shift;
+
+ my $current_snapshot;
+ my $level = $self->{level}[0];
+ my $device = $self->{device};
+ if (defined $device) {
+ $device =~ s,^/,,;
+ $current_snapshot = $self->zfs_build_snapshotname($device);
+ $self->{'snapshot'} = $self->zfs_build_snapshotname($device, $level);
+ }
+
+ my $directory = $device;
+ $directory = $self->{directory} if defined $self->{directory};
+ $directory =~ s,^/,,;
+
+ my @cmd = ();
+
+ if ($self->{pfexec_cmd}) {
+ push @cmd, $self->{pfexec_cmd};
+ }
+ push @cmd, $self->{zfs_path};
+ push @cmd, "recv";
+ push @cmd, $directory;
+
+ debug("cmd:" . join(" ", @cmd));
+ system @cmd;
+
+ my $snapshotname;
+ my $newsnapname;
+ if (defined $device) {
+ $snapshotname = "$directory\@$current_snapshot";
+ $newsnapname = "$directory\@$self->{'snapshot'}";
+ } else {
+ # find snapshot name
+ @cmd = ();
+ if ($self->{pfexec_cmd}) {
+ push @cmd, $self->{pfexec_cmd};
+ }
+ push @cmd, $self->{zfs_path};
+ push @cmd, "list";
+ push @cmd, "-r";
+ push @cmd, "-t";
+ push @cmd, "snapshot";
+ push @cmd, $directory;
+ debug("cmd:" . join(" ", @cmd));
+
+ my($wtr, $rdr, $err, $pid);
+ my($msg, $errmsg);
+ $err = Symbol::gensym;
+ $pid = open3($wtr, $rdr, $err, @cmd);
+ close $wtr;
+ while ($msg = <$rdr>) {
+ next if $msg =~ /^NAME/;
+ my ($name, $used, $avail) = split(/ +/, $msg);
+ if ($name =~ /-current$/) {
+ $snapshotname = $name;
+ last;
+ }
+ }
+ $errmsg = <$err>;
+ waitpid $pid, 0;
+ close $rdr;
+ close $err;
+
+ if (defined $snapshotname and defined($level)) {
+ $newsnapname = $snapshotname;
+ $newsnapname =~ s/current$/$level/;
+ } else {
+ # destroy the snapshot
+ # restoring next level will fail.
+ @cmd = ();
+ if ($self->{pfexec_cmd}) {
+ push @cmd, $self->{pfexec_cmd};
+ }
+ push @cmd, $self->{zfs_path};
+ push @cmd, "destroy";
+ push @cmd, $snapshotname;
+
+ debug("cmd:" . join(" ", @cmd));
+ system @cmd;
+ }
+ }
+
+ if (defined $newsnapname) {
+ # rename -current snapshot to -level
+ @cmd = ();
+ if ($self->{pfexec_cmd}) {
+ push @cmd, $self->{pfexec_cmd};
+ }
+ push @cmd, $self->{zfs_path};
+ push @cmd, "rename";
+ push @cmd, $snapshotname;
+ push @cmd, $newsnapname;
+
+ debug("cmd:" . join(" ", @cmd));
+ system @cmd;
+ }
+}
sub command_print_command {
}