#!@PERL@
#
-# Copyright (c) 2008,2009 Zmanda, Inc. All Rights Reserved.
+# Copyright (c) 2008-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
use Amanda::Tapelist;
use Amanda::Util qw( :constants );
use File::Copy;
+use File::Basename;
use Getopt::Long;
my $amadmin = "$sbindir/amadmin";
my $keep_label;
my $verbose = 1;
my $help;
-my $logdir;
-my $log_file;
-my $log_created = 0;
-
-sub die_handler {
- if ($log_created == 1) {
- unlink $log_file;
- $log_created = 0;
- }
-}
-$SIG{__DIE__} = \&die_handler;
-
-sub int_handler {
- if ($log_created == 1) {
- unlink $log_file;
- $log_created = 0;
- }
- die "Interrupted\n";
-}
-$SIG{INT} = \&int_handler;
sub usage() {
print <<EOF
my $config_overrides = new_config_overrides( scalar(@ARGV) + 1 );
+debug("Arguments: " . join(' ', @ARGV));
+Getopt::Long::Configure(qw{ bundling });
my $opts_ok = GetOptions(
+ 'version' => \&Amanda::Util::version_opt,
"changer=s" => \$changer_name,
"cleanup" => \$cleanup,
"dryrun|n" => \$dry_run,
}
Amanda::Util::finish_setup($RUNNING_AS_DUMPUSER);
-$logdir = config_dir_relative(getconf($CNF_LOGDIR));
-$log_file = "$logdir/log";
-
-if ($erase) {
- # Check for log file existance
- if (-e $log_file) {
- `amcleanup -p $config_name`;
- }
-
- if (-e $log_file) {
- local *LOG;
- open(LOG, $log_file);
- my $info_line = <LOG>;
- close LOG;
- $info_line =~ /^INFO (.*) .* pid .*$/;
- my $process_name = $1;
- print "$process_name is running, or you must run amcleanup\n";
- exit 1;
- }
-}
# amadmin may later try to load this and will die if it has errors
# load it now to catch the problem sooner (before we might erase data)
die "Errors processing disklist";
}
-my $scrub_db = sub {
- my $tapelist_file = config_dir_relative(getconf($CNF_TAPELIST));
- my $tapelist = Amanda::Tapelist::read_tapelist($tapelist_file);
- unless ($tapelist) {
- die "Could not read the tapelist";
- }
+my $tapelist_file = config_dir_relative(getconf($CNF_TAPELIST));
+my $tapelist = Amanda::Tapelist->new($tapelist_file, !$dry_run);
+unless ($tapelist) {
+ die "Could not read the tapelist";
+}
+
+my $scrub_db = sub {
+ my $t = $tapelist->lookup_tapelabel($label);
if ($keep_label) {
- my $t = $tapelist->lookup_tapelabel($label);
$t->{'datestamp'} = 0 if $t;
+ } elsif (!defined $t) {
+ print "label '$label' not found in $tapelist_file\n";
+ exit 0;
} else {
$tapelist->remove_tapelabel($label);
}
- my $tmp_tapelist_file = "$AMANDA_TMPDIR/tapelist-amrmtape-" . time();
- my $backup_tapelist_file = "$AMANDA_TMPDIR/tapelist-backup-amrmtape-" . time();
- unless (copy($tapelist_file, $backup_tapelist_file)) {
- die "Failed to copy/backup $tapelist_file to $backup_tapelist_file";
+
+ #take a copy in case we roolback
+ my $backup_tapelist_file = dirname($tapelist_file) . "-backup-amrmtape-" . time();
+ if (-x $tapelist_file) {
+ unless (copy($tapelist_file, $backup_tapelist_file)) {
+ die "Failed to copy/backup $tapelist_file to $backup_tapelist_file";
+ }
}
- # writing to temp and then moving is generally safer than writing directly
+
unless ($dry_run) {
- $tapelist->write($tmp_tapelist_file);
- unless (move($tmp_tapelist_file, $tapelist_file)) {
- die "Failed to replace old tapelist with new tapelist.";
- }
+ $tapelist->write();
}
- my $tmp_curinfo_file = "$AMANDA_TMPDIR/curinfo-amrmtape-" . time();
+ my $tmp_curinfo_file = "$AMANDA_TMPDIR/curinfo-amrmtape-" . time() . "-" . $$;
unless (open(AMADMIN, "$amadmin $config_name export |")) {
die "Failed to execute $amadmin: $! $?";
}
- open(CURINFO, ">$tmp_curinfo_file");
+ open(CURINFO, ">$tmp_curinfo_file") or
+ die "Failed to open $tmp_curinfo_file for writing: $! $?";
sub info_line($) {
print CURINFO "$_[0]";
}
my $level = $parts[1];
my $cur_label = $parts[7];
- if ($cur_label eq $label) {
+ if (defined $cur_label and $cur_label eq $label) {
$dead_level = $level;
vlog "Discarding Host: $host, Disk: $disk, Level: $level\n";
} elsif ( $level > $dead_level ) {
my $erase_volume = make_cb('erase_volume' => sub {
if ($erase) {
- $log_created = 1;
- local *LOG;
- open(LOG, ">$log_file");
- print LOG "INFO amrmtape amrmtape pid $$\n";
- close LOG;
- my $chg = Amanda::Changer->new($changer_name);
+ my $chg = Amanda::Changer->new($changer_name, tapelist => $tapelist);
$chg->load(
'label' => $label,
'res_cb' => sub {
my $dev = $resv->{'device'};
die "Can not erase $label because the device doesn't support this feature"
unless $dev->property_get('full_deletion');
- if (!$dry_run) {
- $dev->erase()
- or die "Failed to erase volume";
- $dev->finish();
- # label the tape with the same label it had
- if ($keep_label) {
- $dev->start($ACCESS_WRITE, $label, undef)
- or die "Failed to write tape label";
- }
- }
+ my $rel_cb = make_cb('rel_cb' => sub {
+ $resv->release(finished_cb => sub {
+ my ($err) = @_;
- $resv->release(finished_cb => sub {
- my ($err) = @_;
- die $err if $err;
+ $chg->quit();
+ die $err if $err;
- $scrub_db->();
+ $scrub_db->();
+ });
});
+
+ if (!$dry_run) {
+ $dev->erase()
+ or die "Failed to erase volume";
+ $resv->set_label(finished_cb => sub {
+ $dev->finish();
+
+ # label the tape with the same label it had
+ if ($keep_label) {
+ $dev->start($ACCESS_WRITE, $label, undef)
+ or die "Failed to write tape label";
+ return $resv->set_label(label => $label, finished_cb => $rel_cb);
+ }
+ $rel_cb->();
+ });
+ } else {
+ $rel_cb->();
+ }
+
});
} else {
$scrub_db->();
$erase_volume->();
Amanda::MainLoop::run();
-if ($log_created == 1) {
- unlink $log_file;
- $log_created = 0;
-}
-
Amanda::Util::finish_application();