X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Famcheckdump.pl;h=e277e24b9290e00c8ec8f03efbdbc3f9d878be0f;hb=d28952249e392eb31bc8eecc53f6c477f30c617b;hp=95c7fa3426f00ac5b3dfaf20eda15562fb65d163;hpb=011a59f5a54864108a16af570a6b287410597cc2;p=debian%2Famanda diff --git a/server-src/amcheckdump.pl b/server-src/amcheckdump.pl index 95c7fa3..e277e24 100644 --- a/server-src/amcheckdump.pl +++ b/server-src/amcheckdump.pl @@ -1,9 +1,10 @@ #! @PERL@ -# Copyright (c) 2007, 2008, 2009, 2010 Zmanda, Inc. All Rights Reserved. +# Copyright (c) 2007-2012 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 -# by the Free Software Foundation. +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY @@ -70,8 +71,10 @@ my $opt_timestamp; my $opt_verbose = 0; my $config_overrides = new_config_overrides($#ARGV+1); +debug("Arguments: " . join(' ', @ARGV)); Getopt::Long::Configure(qw(bundling)); GetOptions( + 'version' => \&Amanda::Util::version_opt, 'timestamp|t=s' => \$opt_timestamp, 'verbose|v' => \$opt_verbose, 'help|usage|?' => \&usage, @@ -95,12 +98,12 @@ if ($cfgerr_level >= $CFGERR_WARNINGS) { Amanda::Util::finish_setup($RUNNING_AS_DUMPUSER); -# Interactive package -package Amanda::Interactive::amcheckdump; +# Interactivity package +package Amanda::Interactivity::amcheckdump; use POSIX qw( :errno_h ); use Amanda::MainLoop qw( :GIOCondition ); use vars qw( @ISA ); -@ISA = qw( Amanda::Interactive ); +@ISA = qw( Amanda::Interactivity ); sub new { my $class = shift; @@ -135,12 +138,12 @@ sub user_request { if (!defined $n_read) { return if ($! == EINTR); $self->abort(); - return $params{'finished_cb'}->( + return $params{'request_cb'}->( Amanda::Changer::Error->new('fatal', message => "Fail to read from stdin")); } elsif ($n_read == 0) { $self->abort(); - return $params{'finished_cb'}->( + return $params{'request_cb'}->( Amanda::Changer::Error->new('fatal', message => "Aborted by user")); } else { @@ -150,7 +153,7 @@ sub user_request { chomp $line; $buffer = ""; $self->abort(); - return $params{'finished_cb'}->(undef, $line); + return $params{'request_cb'}->(undef, $line); } } }; @@ -196,6 +199,8 @@ sub clerk_notif_holding { package main; +use Amanda::MainLoop qw( :GIOCondition ); + # Given a dumpfile_t, figure out the command line to validate, specified # as an argv array sub find_validation_command { @@ -218,7 +223,7 @@ sub find_validation_command { "TAR" => [ $Amanda::Constants::GNUTAR, qw(--ignore-zeros -tf -) ], "GTAR" => [ $Amanda::Constants::GNUTAR, qw(--ignore-zeros -tf -) ], "GNUTAR" => [ $Amanda::Constants::GNUTAR, qw(--ignore-zeros -tf -) ], - "SMBCLIENT" => [ $Amanda::Constants::GNUTAR, qw(--ignore-zeros -tf -) ], + "SMBCLIENT" => [ $Amanda::Constants::GNUTAR, qw(-tf -) ], "PKZIP" => undef, ); if (!exists $validation_programs{$program}) { @@ -249,16 +254,22 @@ sub main { my $tapelist; my $chg; - my $interactive; + my $interactivity; my $scan; my $clerk; my $plan; my $timestamp; my $all_success = 1; my @xfer_errs; + my %all_filter; + my $current_dump; + my $recovery_done; + my %recovery_params; my $steps = define_steps - cb_ref => \$finished_cb; + cb_ref => \$finished_cb, + finalize => sub { $scan->quit() if defined $scan; + $chg->quit() if defined $chg }; step start => sub { # set up the tapelist @@ -271,17 +282,17 @@ sub main { unless defined $opt_timestamp; # make an interactivity plugin - $interactive = Amanda::Interactive::amcheckdump->new(); + $interactivity = Amanda::Interactivity::amcheckdump->new(); # make a changer - $chg = Amanda::Changer->new(); + $chg = Amanda::Changer->new(undef, tapelist => $tapelist); return $steps->{'quit'}->($chg) if $chg->isa("Amanda::Changer::Error"); # make a scan $scan = Amanda::Recovery::Scan->new( chg => $chg, - interactive => $interactive); + interactivity => $interactivity); return $steps->{'quit'}->($scan) if $scan->isa("Amanda::Changer::Error"); @@ -332,6 +343,10 @@ sub main { step check_dumpfile => sub { my ($dump) = @_; + $current_dump = $dump; + + $recovery_done = 0; + %recovery_params = (); print "Validating image " . $dump->{hostname} . ":" . $dump->{diskname} . " dumped " . $dump->{dump_timestamp} . " level ". @@ -357,11 +372,11 @@ sub main { if ($hdr->{'srv_encrypt'}) { push @filters, Amanda::Xfer::Filter::Process->new( - [ $hdr->{'srv_encrypt'}, $hdr->{'srv_decrypt_opt'} ], 0, 0); + [ $hdr->{'srv_encrypt'}, $hdr->{'srv_decrypt_opt'} ], 0); } elsif ($hdr->{'clnt_encrypt'}) { push @filters, Amanda::Xfer::Filter::Process->new( - [ $hdr->{'clnt_encrypt'}, $hdr->{'clnt_decrypt_opt'} ], 0, 0); + [ $hdr->{'clnt_encrypt'}, $hdr->{'clnt_decrypt_opt'} ], 0); } else { return failure("could not decrypt encrypted dump: no program specified", $finished_cb); @@ -382,17 +397,17 @@ sub main { # TODO: this assumes that srvcompprog takes "-d" to decrypt push @filters, Amanda::Xfer::Filter::Process->new( - [ $hdr->{'srvcompprog'}, "-d" ], 0, 0); + [ $hdr->{'srvcompprog'}, "-d" ], 0); } elsif ($hdr->{'clntcompprog'}) { # TODO: this assumes that clntcompprog takes "-d" to decrypt push @filters, Amanda::Xfer::Filter::Process->new( - [ $hdr->{'clntcompprog'}, "-d" ], 0, 0); + [ $hdr->{'clntcompprog'}, "-d" ], 0); } else { push @filters, Amanda::Xfer::Filter::Process->new( [ $Amanda::Constants::UNCOMPRESS_PATH, - $Amanda::Constants::UNCOMPRESS_OPT ], 0, 0); + $Amanda::Constants::UNCOMPRESS_OPT ], 0); } # adjust the header @@ -404,14 +419,48 @@ sub main { # we need to throw out its stdout my $argv = find_validation_command($hdr); if (defined $argv) { - push @filters, Amanda::Xfer::Filter::Process->new($argv, 0, 0); + push @filters, Amanda::Xfer::Filter::Process->new($argv, 0); } # we always throw out stdout my $xfer_dest = Amanda::Xfer::Dest::Null->new(0); + # start reading all filter stderr + foreach my $filter (@filters) { + my $fd = $filter->get_stderr_fd(); + $fd.=""; + $fd = int($fd); + my $src = Amanda::MainLoop::fd_source($fd, + $G_IO_IN|$G_IO_HUP|$G_IO_ERR); + my $buffer = ""; + $all_filter{$src} = 1; + $src->set_callback( sub { + my $b; + my $n_read = POSIX::read($fd, $b, 1); + if (!defined $n_read) { + return; + } elsif ($n_read == 0) { + delete $all_filter{$src}; + $src->remove(); + POSIX::close($fd); + if (!%all_filter and $recovery_done) { + $steps->{'filter_done'}->(); + } + } else { + $buffer .= $b; + if ($b eq "\n") { + my $line = $buffer; + print STDERR "filter stderr: $line"; + chomp $line; + debug("filter stderr: $line"); + $buffer = ""; + } + } + }); + } + my $xfer = Amanda::Xfer->new([ $xfer_src, @filters, $xfer_dest ]); - $xfer->start($steps->{'handle_xmsg'}); + $xfer->start($steps->{'handle_xmsg'}, 0, $current_dump->{'bytes'}); $clerk->start_recovery( xfer => $xfer, recovery_cb => $steps->{'recovery_cb'}); @@ -429,12 +478,17 @@ sub main { }; step recovery_cb => sub { - my %params = @_; + %recovery_params = @_; + $recovery_done = 1; + + $steps->{'filter_done'}->() if !%all_filter; + }; + step filter_done => sub { # distinguish device errors from validation errors - if (@{$params{'errors'}}) { + if (@{$recovery_params{'errors'}}) { print STDERR "While reading from volumes:\n"; - print STDERR "$_\n" for @{$params{'errors'}}; + print STDERR "$_\n" for @{$recovery_params{'errors'}}; return $steps->{'quit'}->("validation aborted"); } @@ -458,18 +512,20 @@ sub main { if ($err) { $exit_code = 1; print STDERR $err, "\n"; - return $clerk->quit(finished_cb => $finished_cb); + return $clerk->quit(finished_cb => $finished_cb) if defined $clerk; + return $finished_cb->(); } if ($all_success) { print "All images successfully validated\n"; } else { - print "Some images failed to be correclty validated.\n"; + print "Some images failed to be correctly validated.\n"; $exit_code = 1; } return $clerk->quit(finished_cb => $finished_cb); }; + } main(sub { Amanda::MainLoop::quit(); });