Imported Upstream version 3.3.3
[debian/amanda] / server-src / amcleanup.pl
1 #!@PERL@
2 # Copyright (c) 2008-2012 Zmanda, Inc.  All Rights Reserved.
3
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8
9 # This program is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 # for more details.
13
14 # You should have received a copy of the GNU General Public License along
15 # with this program; if not, write to the Free Software Foundation, Inc.,
16 # 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17
18 # Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
19 # Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
20
21 use lib '@amperldir@';
22 use strict;
23 use warnings;
24
25 use Getopt::Long;
26 use Amanda::Config qw( :init :getconf config_dir_relative );
27 use Amanda::Util qw( :constants );
28 use Amanda::Paths;
29 use Amanda::Constants;
30 use Amanda::Process;
31 use Amanda::Logfile;
32 use Amanda::Holding;
33 use Amanda::Debug qw( debug );
34 my $kill_enable=0;
35 my $process_alive=0;
36 my $verbose=0;
37 my $clean_holding=0;
38
39 sub usage() {
40     print "Usage: amcleanup [-k] [-v] [-p] [-r] conf\n";
41     exit 1;
42 }
43
44 Amanda::Util::setup_application("amcleanup", "server", $CONTEXT_CMDLINE);
45
46 my $config_overrides = new_config_overrides($#ARGV+1);
47
48 debug("Arguments: " . join(' ', @ARGV));
49 Getopt::Long::Configure(qw(bundling));
50 GetOptions(
51     'version' => \&Amanda::Util::version_opt,
52     'k' => \$kill_enable,
53     'p' => \$process_alive,
54     'v' => \$verbose,
55     'r' => \$clean_holding,
56     'help|usage' => \&usage,
57     'o=s' => sub { add_config_override_opt($config_overrides, $_[1]); },
58 ) or usage();
59
60 my $config_name = shift @ARGV or usage;
61
62 if ($kill_enable && $process_alive) {
63     die "amcleanup: Can't use -k and -p simultaneously\n";
64 }
65
66 set_config_overrides($config_overrides);
67 config_init($CONFIG_INIT_EXPLICIT_NAME, $config_name);
68 my ($cfgerr_level, @cfgerr_errors) = config_errors();
69 if ($cfgerr_level >= $CFGERR_WARNINGS) {
70     config_print_errors();
71     if ($cfgerr_level >= $CFGERR_ERRORS) {
72         die("errors processing config file");
73     }
74 }
75
76 Amanda::Util::finish_setup($RUNNING_AS_DUMPUSER);
77
78 my $logdir=config_dir_relative(getconf($CNF_LOGDIR));
79 my $logfile = "$logdir/log";
80 my $amreport="$sbindir/amreport";
81 my $amtrmidx="$amlibexecdir/amtrmidx";
82 my $amcleanupdisk="$sbindir/amcleanupdisk";
83
84 if ( ! -e "$CONFIG_DIR/$config_name" ) {
85     die "Configuration directory '$CONFIG_DIR/$config_name' doesn't exist\n";
86 }
87 if ( ! -d "$CONFIG_DIR/$config_name" ) {
88     die "Configuration directory '$CONFIG_DIR/$config_name' is not a directory\n";
89 }
90
91 my $Amanda_process = Amanda::Process->new($verbose);
92 $Amanda_process->load_ps_table();
93
94 if (-f "$logfile") {
95     $Amanda_process->scan_log($logfile);
96 } elsif (!$process_alive) {
97     $Amanda_process->set_master_process($config_name, "amdump", "amflush");
98 }
99
100 $Amanda_process->add_child();
101
102 my $nb_amanda_process = $Amanda_process->count_process();
103 #if amanda processes are running
104 if ($nb_amanda_process > 0) {
105     if ($process_alive) {
106         exit 0;
107     } elsif (!$kill_enable) {
108         print "amcleanup: ", $Amanda_process->{master_pname}, " Process is running at PID ", $Amanda_process->{master_pid}, " for $config_name configuration.\n";
109         print "amcleanup: Use -k option to stop all the process...\n";
110         print "Usage: amcleanup [-k] conf\n";
111         exit 0;
112     } else { #kill the processes
113         Amanda::Debug::debug("Killing amanda process");
114         $Amanda_process->kill_process("SIGTERM");
115         my $count = 5;
116         my $pp;
117         while ($count > 0) {
118            $pp = $Amanda_process->process_running();
119            if ($pp > 0) {
120                 $count--;
121                 sleep 1;
122            } else {
123                 $count = 0;
124            }
125         }
126         if ($pp > 0) {
127             $Amanda_process->kill_process("SIGKILL");
128             sleep 2;
129             $pp = $Amanda_process->process_running();
130         }
131         print "amcleanup: ", $nb_amanda_process, " Amanda processes were found running.\n";
132         print "amcleanup: $pp processes failed to terminate.\n";
133         Amanda::Debug::debug("$nb_amanda_process Amanda processes were found running");
134         Amanda::Debug::debug("$pp processes failed to terminate");
135     }
136 }
137
138 sub run_system {
139     my $check_code = shift;
140     my @cmd = @_;
141     my $pgm = $cmd[0];
142
143     system @cmd;
144     my $err = $?;
145     my $res = $!;
146
147     if ($err == -1) {
148         Amanda::Debug::debug("failed to execute $pgm: $res");
149         print "failed to execute $pgm: $res\n";
150     } elsif ($err & 127) {
151         Amanda::Debug::debug(sprintf("$pgm died with signal %d, %s coredump",
152                       ($err & 127), ($err & 128) ? 'with' : 'without'));
153         printf "$pgm died with signal %d, %s coredump\n",
154                 ($err & 127), ($err & 128) ? 'with' : 'without';
155     } elsif ($check_code && $err > 0) {
156         Amanda::Debug::debug(sprintf("$pgm exited with value %d", $err >> 8));
157         printf "$pgm exited with value %d %d\n", $err >> 8, $err;
158     }
159 }
160
161 # rotate log
162 if (-f $logfile) {
163     Amanda::Debug::debug("Processing log file");
164     run_system(0, $amreport, $config_name, "--from-amdump");
165
166     my $ts = Amanda::Logfile::get_current_log_timestamp();
167     Amanda::Logfile::log_rename($ts);
168
169     run_system(1, $amtrmidx, $config_name);
170 } else {
171     print "amcleanup: no unprocessed logfile to clean up.\n";
172 }
173
174 my $tapecycle = getconf($CNF_TAPECYCLE);
175
176 # cleanup logfiles
177 chdir "$CONFIG_DIR/$config_name";
178 foreach my $pname ("amdump", "amflush") {
179     my $errfile = "$logdir/$pname";
180     if (-f $errfile) {
181         print "amcleanup: $errfile exists, renaming it.\n";
182         Amanda::Debug::debug("$errfile exists, renaming it");
183
184         # Keep debug log through the tapecycle plus a couple days
185         my $maxdays=$tapecycle + 2;
186
187         my $days=1;
188         # First, find out the last existing errfile,
189         # to avoid ``infinite'' loops if tapecycle is infinite
190         while ($days < $maxdays  && -f "$errfile.$days") {
191             $days++;
192         }
193
194         # Now, renumber the existing log files
195         while ($days >= 2) {
196             my $ndays = $days - 1;
197             rename("$errfile.$ndays", "$errfile.$days");
198             $days=$ndays;
199         }
200         rename($errfile, "$errfile.1");
201     }
202 }
203
204 my @amcleanupdisk;
205 push @amcleanupdisk, $amcleanupdisk;
206 push @amcleanupdisk, "-v" if $verbose;
207 push @amcleanupdisk, "-r" if $clean_holding;
208 push @amcleanupdisk, $config_name;
209 system @amcleanupdisk;
210
211 Amanda::Util::finish_application();