-# 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
driveinuse All drives are in use
unknown Unknown reason
empty The slot is empty
+ device Failed to set up the device
Like types, checks for particular reasons should use the methods, to avoid
undetected typos:
=head3 make_new_tape_label
$chg->make_new_tape_label(barcode => $barcode,
+ slot => $slot,
meta => $meta);
To devise a new name for a volume using the C<barcode> and C<meta> arguments.
$self->{'fatal_error'} = $err
if ($err->fatal);
- $cb->($err);
+ $cb->($err) if $cb;
}
return $err;
my ($statefile, $cb, $sub) = @_;
my ($filelock, $STATE);
my $poll = 0; # first delay will be 0.1s; see below
+ my $time;
+
+ if (defined $self->{'lock-timeout'}) {
+ $time = time() + $self->{'lock-timeout'};
+ } else {
+ $time = time() + 1000;
+ }
my $steps = define_steps
cb_ref => \$cb;
step lock => sub {
my $rv = $filelock->lock();
- if ($rv == 1) {
+ if ($rv == 1 && time() < $time) {
# loop until we get the lock, increasing $poll to 10s
$poll += 100 unless $poll >= 10000;
return Amanda::MainLoop::call_after($poll, $steps->{'lock'});
+ } elsif ($rv == 1) {
+ return $self->make_error("fatal", $cb,
+ message => "Timeout trying to lock '$statefile'");
} elsif ($rv == -1) {
return $self->make_error("fatal", $cb,
message => "Error locking '$statefile'");
my $tl = $self->{'tapelist'};
die ("make_new_tape_label: no tapelist") if !$tl;
- return undef if !defined $self->{'autolabel'}->{'template'};
- return undef if !defined $self->{'labelstr'};
+ if (!defined $self->{'autolabel'}) {
+ return (undef, "autolabel not set");
+ }
+ if (!defined $self->{'autolabel'}->{'template'}) {
+ return (undef, "template is not set, you must set autolabel");
+ }
+ if (!defined $self->{'labelstr'}) {
+ return (undef, "labelstr not set");
+ }
my $template = $self->{'autolabel'}->{'template'};
my $labelstr = $self->{'labelstr'};
+ my $slot_digit = 1;
- if (!$template) {
- return (undef, "template is not set, you must set autolabel");
- }
$template =~ s/\$\$/SUBSTITUTE_DOLLAR/g;
$template =~ s/\$b/SUBSTITUTE_BARCODE/g;
$template =~ s/\$m/SUBSTITUTE_META/g;
$template =~ s/\$o/SUBSTITUTE_ORG/g;
$template =~ s/\$c/SUBSTITUTE_CONFIG/g;
+ if ($template =~ /\$([0-9]*)s/) {
+ $slot_digit = $1;
+ $slot_digit = 1 if $slot_digit < 1;
+ $template =~ s/\$[0-9]*s/SUBSTITUTE_SLOT/g;
+ }
my $org = getconf($CNF_ORG);
my $config = Amanda::Config::get_config_name();
my $barcode = $params{'barcode'};
$barcode = '' if !defined $barcode;
my $meta = $params{'meta'};
+ my $slot = $params{'slot'};
+ $slot = '' if !defined $slot;
$meta = $self->make_new_meta_label(%params) if !defined $meta;
$meta = '' if !defined $meta;
$template =~ s/SUBSTITUTE_ORG/$org/g;
$template =~ s/SUBSTITUTE_CONFIG/$config/g;
$template =~ s/SUBSTITUTE_META/$meta/g;
- # Do not susbtitute the barcode now
+ # Do not susbtitute the barcode and slot now
(my $npercents =
$template) =~ s/[^%]*(%+)[^%]*/length($1)/e;
- my $nlabels = 10 ** $npercents;
+ $npercents = 0 if $npercents eq $template;
my $label;
if ($npercents == 0) {
- if ($template =~ /SUBSTITUTE_BARCODE/ && defined $barcode) {
- $label = $template;
- $label =~ s/SUBSTITUTE_BARCODE/$barcode/g;
- if ($tl->lookup_tapelabel($label)) {
- return (undef, "Label '$label' already exists");
- }
- } elsif ($template =~ /SUBSTITUTE_BARCODE/ && !defined $barcode) {
- return (undef, "Can't generate new label because volume have no barcode");
- } else {
+ $label = $template;
+ $label =~ s/SUBSTITUTE_BARCODE/$barcode/g;
+ if ($template =~ /SUBSTITUTE_SLOT/) {
+ my $slot_label = sprintf("%0*d", $slot_digit, $slot);
+ $label =~ s/SUBSTITUTE_SLOT/$slot_label/g;
+ }
+ if ($template =~ /SUBSTITUTE_BARCODE/ && !defined $barcode) {
+ return (undef, "Can't generate new label because volume has no barcode");
+ } elsif ($template =~ /SUBSTITUTE_SLOT/ && !defined $slot) {
+ return (undef, "Can't generate new label because volume has no slot");
+ } elsif ($label eq $template) {
return (undef, "autolabel require at least one '%'");
+ } elsif ($tl->lookup_tapelabel($label)) {
+ return (undef, "Label '$label' already exists");
}
} else {
# make up a sprintf pattern
}
}
+ my $nlabels = 10 ** $npercents;
my ($i);
for ($i = 1; $i < $nlabels; $i++) {
$label = sprintf($sprintf_pat, $i);
last unless (exists $existing_labels{$label});
}
- # susbtitute the barcode
+ # susbtitute the barcode and slot
$label =~ s/SUBSTITUTE_BARCODE/$barcode/g;
+ if ($template =~ /SUBSTITUTE_SLOT/) {
+ my $slot_label = sprintf("%0*d", $slot_digit, $slot);
+ $label =~ s/SUBSTITUTE_SLOT/$slot_label/g;
+ }
# bail out if we didn't find an unused label
return (undef, "Can't label unlabeled volume: All label used")
(my $npercents =
$template) =~ s/[^%]*(%+)[^%]*/length($1)/e;
+ $npercents = 0 if $npercents eq $template;
my $nlabels = 10 ** $npercents;
# make up a sprintf pattern
if (!defined $dev_status) {
return 0;
} elsif ($dev_status & $DEVICE_STATUS_VOLUME_UNLABELED and
- $f_type == $Amanda::Header::F_EMPTY) {
+ defined $f_type and
+ $f_type == $Amanda::Header::F_EMPTY) {
return 0 if (!$autolabel->{'empty'});
} elsif ($dev_status & $DEVICE_STATUS_VOLUME_UNLABELED and
+ defined $f_type and
$f_type == $Amanda::Header::F_WEIRD) {
return 0 if (!$autolabel->{'non_amanda'});
} elsif ($dev_status & $DEVICE_STATUS_VOLUME_ERROR) {
sub volinuse { $_[0]->failed && $_[0]->{'reason'} eq 'volinuse'; }
sub unknown { $_[0]->failed && $_[0]->{'reason'} eq 'unknown'; }
sub empty { $_[0]->failed && $_[0]->{'reason'} eq 'empty'; }
+sub device { $_[0]->failed && $_[0]->{'reason'} eq 'device'; }
# slot accessor
sub slot { $_[0]->{'slot'}; }
my $self = shift;
my %params = @_;
- return if $self->{'released'};
+ if ($self->{'released'}) {
+ $params{'finished_cb'}->(undef) if exists $params{'finished_cb'};
+ return;
+ }
# always finish the device on release; it's illegal for anything
# else to use the device after this point, anyway, so we want to
$params{'barcode'} = $self->{'barcode'} if !defined $params{'barcode'};
$params{'meta'} = $self->{'meta'} if !defined $params{'meta'};
+ $params{'slot'} = $self->{'this_slot'} if !defined $params{'slot'};
return $self->{'chg'}->make_new_tape_label(%params);
}
package Amanda::Changer::Config;
use Amanda::Config qw( :getconf string_to_boolean );
-use Amanda::Device;
+use Amanda::Device qw( :constants );
sub new {
my $class = shift;
while (my ($propname, $propinfo) = each(%properties)) {
for my $value (@{$propinfo->{'values'}}) {
if (!$device->property_set($propname, $value)) {
- my $msg = "Error setting '$propname' on device '".$device->device_name."'";
+ my $msg;
+ if ($device->status == $DEVICE_STATUS_SUCCESS) {
+ $msg = "Error setting '$propname' on device '".$device->device_name."'";
+ } else {
+ $msg = $device->error() . " on device '".$device->device_name."'";
+ }
if (exists $propinfo->{'optional'}) {
if ($propinfo->{'optional'} eq 'warn') {
warn("$msg (ignored)");