lintian doesn't like orphan packages with uploaders...
[debian/amanda] / server-src / amcheck-device.pl
index ba1699f4dfbff53a1d07086e261feecda594ba14..b87d0e30954c9534609888f1029b489666523246 100644 (file)
@@ -1,9 +1,10 @@
 #! @PERL@
-# Copyright (c) 2009, 2010 Zmanda Inc.  All Rights Reserved.
+# Copyright (c) 2009-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
@@ -22,13 +23,14 @@ use strict;
 use warnings;
 
 use Amanda::Util qw( :constants );
-use Amanda::Config qw( :init );
+use Amanda::Config qw( :init :getconf );
 use Amanda::Logfile qw( :logtype_t log_add $amanda_log_trace_log );
 use Amanda::Debug;
 use Amanda::Device qw( :constants );
 use Amanda::MainLoop;
 use Amanda::Changer;
 use Amanda::Taper::Scan;
+use Amanda::Interactivity;
 use Getopt::Long;
 
 Amanda::Util::setup_application("amcheck-device", "server", $CONTEXT_CMDLINE);
@@ -37,6 +39,7 @@ my $config_overrides = new_config_overrides($#ARGV+1);
 my $overwrite = 0;
 Getopt::Long::Configure(qw{bundling});
 GetOptions(
+    'version' => \&Amanda::Util::version_opt,
     'o=s' => sub { add_config_override_opt($config_overrides, $_[1]); },
     'w' => \$overwrite,
 ) or usage();
@@ -93,6 +96,17 @@ sub _user_msg_fn {
                     print STDERR "slot $params{'err'}->{'this_slot'}:";
                 }
                 print STDERR " $params{'err'}\n";
+            } elsif (!$params{'res'}) {
+                my $volume_label = $params{'label'};
+                if ($params{'active'}) {
+                    print STDERR " volume '$volume_label' is still active and cannot be overwritten\n";
+                } elsif ($params{'does_not_match_labelstr'}) {
+                    print STDERR " volume '$volume_label' does not match labelstr '$params{'labelstr'}'\n";
+                } elsif ($params{'not_in_tapelist'}) {
+                    print STDERR " volume '$volume_label' is not in the tapelist\n"
+                } else {
+                    print STDERR " volume '$volume_label'\n";
+                }
             } else { # res must be defined
                 my $res = $params{'res'};
                 my $dev = $res->{'device'};
@@ -117,7 +131,12 @@ sub _user_msg_fn {
                 } elsif ($dev->status & $DEVICE_STATUS_VOLUME_UNLABELED and
                          $dev->volume_header and
                          $dev->volume_header->{'type'} == $Amanda::Header::F_WEIRD) {
-                    print STDERR " contains a non-Amanda volume; check and relabel it with 'amlabel -f'\n";
+                   my $autolabel = getconf($CNF_AUTOLABEL);
+                   if ($autolabel->{'non_amanda'}) {
+                       print STDERR " contains a non-Amanda volume\n";
+                   } else {
+                       print STDERR " contains a non-Amanda volume; check and relabel it with 'amlabel -f'\n";
+                   }
                 } elsif ($dev->status & $DEVICE_STATUS_VOLUME_ERROR) {
                     my $message = $dev->error_or_status();
                     print STDERR " Can't read label: $message\n";
@@ -141,16 +160,23 @@ sub failure {
 sub do_check {
     my ($finished_cb) = @_;
     my ($res, $label, $mode);
+    my $tlf = Amanda::Config::config_dir_relative(getconf($CNF_TAPELIST));
+    my $tl = Amanda::Tapelist->new($tlf);
+    my $chg = Amanda::Changer->new(undef, tapelist => $tl);
+    return failure($chg, $finished_cb) if ($chg->isa("Amanda::Changer::Error"));
+    my $interactivity = Amanda::Interactivity->new(
+                                       name => getconf($CNF_INTERACTIVITY));
+    my $scan_name = getconf($CNF_TAPERSCAN);
+    my $taperscan = Amanda::Taper::Scan->new(algorithm => $scan_name,
+                                            changer => $chg,
+                                            interactivity => $interactivity,
+                                            tapelist => $tl);
 
     my $steps = define_steps
-       cb_ref => \$finished_cb;
+       cb_ref => \$finished_cb,
+       finalize => sub { $taperscan->quit(); };
 
     step start => sub {
-       my $chg = Amanda::Changer->new();
-
-       return failure($chg, $finished_cb) if ($chg->isa("Amanda::Changer::Error"));
-
-       my $taperscan = Amanda::Taper::Scan->new(changer => $chg);
        $taperscan->scan(
            result_cb => $steps->{'result_cb'},
            user_msg_fn => \&_user_msg_fn
@@ -159,23 +185,29 @@ sub do_check {
 
     step result_cb => sub {
        (my $err, $res, $label, $mode) = @_;
-       return failure($err, $finished_cb) if $err;
-
-       if (defined $res->{'device'}->volume_label()) {
-           $res->set_label(label => $res->{'device'}->volume_label(),
-                           finished_cb => $steps->{'set_labeled'});
-       } else {
-           $steps->{'set_labeled'}->(undef);
-       };
-    };
+       if ($err) {
+           if ($res) {
+               $res->release(finished_cb => sub {
+                   return failure($err, $finished_cb);
+               });
+               return;
+           } else {
+               return failure($err, $finished_cb);
+           }
+       }
 
-    step set_labeled => sub {
        my $modestr = ($mode == $ACCESS_APPEND)? "append" : "write";
        my $slot = $res->{'this_slot'};
-       if (defined $res->{'device'}->volume_label()) {
+       if (defined $res->{'device'} and defined $res->{'device'}->volume_label()) {
            print "Will $modestr to volume '$label' in slot $slot.\n";
        } else {
-           print "Will $modestr label '$label' to new volume in slot $slot.\n";
+           my $header = $res->{'device'}->volume_header();
+           if (defined $header and defined $header->{'type'} and
+               $header->{'type'} == $Amanda::Header::F_WEIRD) {
+               print "Will $modestr label '$label' to non-Amanda volume in slot $slot.\n";
+           } else {
+               print "Will $modestr label '$label' to new volume in slot $slot.\n";
+           }
        }
 
        $steps->{'check_access_type'}->();
@@ -187,6 +219,13 @@ sub do_check {
            print "WARNING: Media access mode is WRITE_ONLY; dumps may not be recoverable\n";
        }
 
+       if (getconf_seen($CNF_DEVICE_OUTPUT_BUFFER_SIZE)) {
+           my $dobs = getconf($CNF_DEVICE_OUTPUT_BUFFER_SIZE);
+           my $block_size = $res->{'device'}->property_get("BLOCK_SIZE");
+           if ($block_size * 2 > $dobs) {
+               print "WARNING: DEVICE-OUTPUT-BUFFER-SIZE is not at least twice the block size of the device, it should be increased for better throughput\n";
+           }
+       }
        $steps->{'check_overwrite'}->();
     };
 
@@ -225,7 +264,8 @@ sub do_check {
        $finished_cb->();
     };
 }
-do_check(\&Amanda::MainLoop::quit);
+
+Amanda::MainLoop::call_later(\&do_check, \&Amanda::MainLoop::quit);
 Amanda::MainLoop::run();
 Amanda::Util::finish_application();
 exit($exit_status);