X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Famtape.pl;h=7a83996dd7f3ab224f2a0be07f099ab1bed7d350;hb=HEAD;hp=490a68eace11054322c7929fc8bc00125887375a;hpb=42ff24f2a525d5965e1841b2ebe3ee0f4b918ac6;p=debian%2Famanda diff --git a/server-src/amtape.pl b/server-src/amtape.pl index 490a68e..7a83996 100644 --- a/server-src/amtape.pl +++ b/server-src/amtape.pl @@ -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 @@ -34,9 +35,11 @@ use Amanda::Constants; use Amanda::MainLoop; use Amanda::Taper::Scan; use Amanda::Recovery::Scan; -use Amanda::Interactive; +use Amanda::Interactivity; +use Amanda::Tapelist; my $exit_status = 0; +my $tl; ## # Subcommand handling @@ -49,7 +52,7 @@ sub usage { $finished_cb = sub { exit(1); } if (!$finished_cb or !(ref($finished_cb) eq "CODE")); print STDERR < {} [-o configoption]* +Usage: amtape [-o configoption]* {} Valid commands are: EOF local $Text::Wrap::columns = 80 - 20; @@ -93,6 +96,7 @@ sub { $chg->reset(finished_cb => sub { my ($err) = @_; + $chg->quit(); return failure($err, $finished_cb) if $err; print STDERR "changer is reset\n"; @@ -113,6 +117,7 @@ sub { $chg->eject(@drive_args, finished_cb => sub { my ($err) = @_; + $chg->quit(); return failure($err, $finished_cb) if $err; print STDERR "drive ejected\n"; @@ -136,6 +141,7 @@ sub { $chg->clean(@drive_args, finished_cb => sub { my ($err) = @_; + $chg->quit(); return failure($err, $finished_cb) if $err; print STDERR "drive cleaned\n"; @@ -143,21 +149,44 @@ sub { }); }); -subcommand("show", "show", "scan all slots in the changer, starting with the current slot", +subcommand("show", "show []", "scan all slots (or listed slots) in the changer, starting with the current slot", sub { my ($finished_cb, @args) = @_; my $last_slot; my %seen_slots; - my $gres; + my $chg; - my $steps = define_steps - cb_ref => \$finished_cb; - - if (@args != 0) { + if (@args > 1) { return usage($finished_cb); } - my $chg = load_changer($finished_cb) or return; + my $what = $args[0]; + my @slots; + + if (defined $what) { + my @what1 = split /,/, $what; + foreach my $what1 (@what1) { + if ($what1 =~ /^(\d*)-(\d*)$/) { + my $begin = $1; + my $end = $2; + $end = $begin if $begin > $end; + while ($begin <= $end) { + push @slots, $begin; + $begin++; + } + } else { + push @slots, $what1; + } + } + } + + my $use_slots = @slots > 0; + + $chg = load_changer($finished_cb) or return; + + my $steps = define_steps + cb_ref => \$finished_cb, + finalize => sub { $chg->quit() if defined $chg }; step start => sub { $chg->info(info => [ 'num_slots' ], info_cb => $steps->{'info_cb'}); @@ -167,13 +196,19 @@ sub { my ($err, %info) = @_; return failure($err, $finished_cb) if $err; - print STDERR "amtape: scanning all $info{num_slots} slots in changer:\n"; + if ($use_slots) { + my $slot = shift @slots; + $chg->load(slot => $slot, + mode => "read", + res_cb => $steps->{'loaded'}); - $steps->{'load_current'}->(); - }; + } else { + print STDERR "amtape: scanning all $info{num_slots} slots in changer:\n"; - step load_current => sub { - $chg->load(relative_slot => 'current', mode => "read", res_cb => $steps->{'loaded'}); + $chg->load(relative_slot => 'current', + mode => "read", + res_cb => $steps->{'loaded'}); + } }; step loaded => sub { @@ -185,6 +220,10 @@ sub { return; } elsif ($err->volinuse and defined $err->{'slot'}) { $last_slot = $err->{'slot'}; + print STDERR sprintf("slot %3s: in use\n", $last_slot); + } elsif ($err->empty and defined $err->{'slot'}) { + $last_slot = $err->{'slot'}; + print STDERR sprintf("slot %3s: empty\n", $last_slot); } else { return failure($err, $finished_cb) if $err; } @@ -201,16 +240,11 @@ sub { print STDERR sprintf("slot %3s: date %-14s label %s\n", $last_slot, $dev->volume_time(), $dev->volume_label()); - $gres = $res; - return $res->set_label(label => $dev->volume_label(), - finished_cb => $steps->{'set_labeled'}); } elsif ($st == $DEVICE_STATUS_VOLUME_UNLABELED) { print STDERR sprintf("slot %3s: unlabeled volume\n", $last_slot); } else { print STDERR sprintf("slot %3s: %s\n", $last_slot, $dev->error_or_status()); } - } else { - print STDERR sprintf("slot %3s: in use\n", $last_slot); } if ($res) { @@ -220,13 +254,20 @@ sub { } }; - step set_labeled => sub { - $gres->release(finished_cb => $steps->{'released'}); - }; - step released => sub { - $chg->load(relative_slot => 'next', slot => $last_slot, - except_slots => { %seen_slots }, res_cb => $steps->{'loaded'}); + if ($use_slots) { + return $finished_cb->() if @slots == 0; + my $slot = shift @slots; + $chg->load(slot => $slot, + mode => "read", + res_cb => $steps->{'loaded'}); + + } else { + $chg->load(relative_slot => 'next', + slot => $last_slot, + except_slots => { %seen_slots }, + res_cb => $steps->{'loaded'}); + } }; }); @@ -246,25 +287,43 @@ sub { my ($err, $inv) = @_; if ($err) { if ($err->notimpl) { - print STDERR "inventory not supported by this changer\n"; + if ($err->{'message'}) { + print STDERR "inventory not supported by this changer: $err->{'message'}\n"; + } else { + print STDERR "inventory not supported by this changer\n"; + } } else { print STDERR "$err\n"; } + $chg->quit(); return $finished_cb->(); } for my $sl (@$inv) { my $line = "slot $sl->{slot}:"; + my $tle; if (!defined($sl->{device_status}) && !defined($sl->{label})) { $line .= " unknown state"; - } elsif ($sl->{'status'} == Amanda::Changer::SLOT_EMPTY) { + } elsif ($sl->{'state'} == Amanda::Changer::SLOT_EMPTY) { $line .= " empty"; } else { if (defined $sl->{label}) { $line .= " label $sl->{label}"; + $tle = $tl->lookup_tapelabel($sl->{label}); + if (defined $tle) { + if ($tle->{'meta'}) { + $line .= " ($tle->{'meta'})"; + } + } + } elsif ($sl->{'device_status'} == $DEVICE_STATUS_VOLUME_UNLABELED) { + $line .= " blank"; } elsif ($sl->{'device_status'} != $DEVICE_STATUS_SUCCESS) { - $line .= "device error"; + if (defined $sl->{'device_error'}) { + $line .= " " . $sl->{'device_error'}; + } else { + $line .= "device error"; + } } elsif ($sl->{'f_type'} != $Amanda::Header::F_TAPESTART) { $line .= " blank"; } else { @@ -283,11 +342,22 @@ sub { if ($sl->{'import_export'}) { $line .= " (import/export slot)"; } + if ($sl->{'current'}) { + $line .= " (current)"; + } + if (defined $tle) { + if (defined $sl->{'barcode'} and + defined $tle->{'barcode'} and + $sl->{'barcode'} ne $tle->{'barcode'}) { + $line .= " MISTMATCH barcode in tapelist: $tle->{'barcode'}"; + } + } # note that inventory goes to stdout print "$line\n"; } + $chg->quit(); $finished_cb->(); }); $chg->inventory(inventory_cb => $inventory_cb); @@ -308,10 +378,11 @@ subcommand("slot", "slot ", sub { my ($finished_cb, @args) = @_; my @slotarg; - my $gres; + my $chg; my $steps = define_steps - cb_ref => \$finished_cb; + cb_ref => \$finished_cb, + finalize => sub { $chg->quit() if defined $chg }; # NOTE: the syntax of this subcommand precludes actual slots named # 'current' or 'next' .. when we have a changer using such slot names, @@ -320,7 +391,7 @@ sub { return usage($finished_cb) unless (@args == 1); my $slot = shift @args; - my $chg = load_changer($finished_cb) or return; + $chg = load_changer($finished_cb) or return; step get_slot => sub { if ($slot eq 'current' or $slot eq 'next') { @@ -366,17 +437,7 @@ sub { my $gotslot = $res->{'this_slot'}; print STDERR "changed to slot $gotslot\n"; - if ($res->{device}->volume_label) { - $gres = $res; - $res->set_label(label => $res->{device}->volume_label(), - finished_cb => $steps->{'set_labeled'}); - } else { - $res->release(finished_cb => $steps->{'released'}); - } - }; - - step set_labeled => sub { - $gres->release(finished_cb => $steps->{'released'}); + $res->release(finished_cb => $steps->{'released'}); }; step released => sub { @@ -390,15 +451,17 @@ sub { subcommand("label", "label