X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Famtape.pl;h=bb290014808ccca54956d6ba4ad41cc1e6097bfd;hb=4c9eba1feb11adf189bceb4001c425e641f0b56a;hp=d733d7016828be287b685e24394d69dfec75d640;hpb=fd48f3e498442f0cbff5f3606c7c403d0566150e;p=debian%2Famanda diff --git a/server-src/amtape.pl b/server-src/amtape.pl index d733d70..bb29001 100644 --- a/server-src/amtape.pl +++ b/server-src/amtape.pl @@ -19,6 +19,7 @@ use lib '@amperldir@'; use strict; +use warnings; use File::Basename; use Getopt::Long; @@ -33,9 +34,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 @@ -44,10 +47,11 @@ my %subcommands; sub usage { my ($finished_cb) = @_; - $finished_cb ||= sub { exit(1); }; + + $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; @@ -80,7 +84,7 @@ subcommand("usage", "usage", "this message", sub { my ($finished_cb, @args) = @_; - usage($finished_cb); + return usage($finished_cb); }); subcommand("reset", "reset", "reset changer to known state", @@ -91,6 +95,7 @@ sub { $chg->reset(finished_cb => sub { my ($err) = @_; + $chg->quit(); return failure($err, $finished_cb) if $err; print STDERR "changer is reset\n"; @@ -111,6 +116,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"; @@ -134,6 +140,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"; @@ -141,21 +148,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 $steps = define_steps - cb_ref => \$finished_cb; + my $chg; - 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'}); @@ -165,13 +195,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 { @@ -199,9 +235,6 @@ 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 { @@ -218,13 +251,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'}); + } }; }); @@ -244,11 +284,16 @@ 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->(); } @@ -256,13 +301,23 @@ sub { my $line = "slot $sl->{slot}:"; 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}"; + my $tle = $tl->lookup_tapelabel($sl->{label}); + 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 { @@ -281,11 +336,15 @@ sub { if ($sl->{'import_export'}) { $line .= " (import/export slot)"; } + if ($sl->{'current'}) { + $line .= " (current)"; + } # note that inventory goes to stdout print "$line\n"; } + $chg->quit(); $finished_cb->(); }); $chg->inventory(inventory_cb => $inventory_cb); @@ -306,19 +365,20 @@ 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, # this subcommand will need to support a --literal flag - usage($finished_cb) unless (@args == 1); + 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') { @@ -364,17 +424,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 { @@ -388,15 +438,17 @@ sub { subcommand("label", "label