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