1# vim:ft=perl 2# Copyright (c) 2008-2013 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 94085, USA, or: http://www.zmanda.com 20 21package Amanda::Script_App; 22 23no warnings; 24no strict; 25$GOOD = 0; 26$ERROR = 1; 27$FAILURE = 2; 28 29use strict; 30use warnings; 31use Amanda::Constants; 32use Amanda::Config qw( :init :getconf config_dir_relative ); 33use Amanda::Debug qw( :logging ); 34use Amanda::Paths; 35use Amanda::Util qw( :constants ); 36use Carp; 37 38=head1 NAME 39 40Amanda::Script_App - perl utility functions for Scripts. 41 42=head1 SYNOPSIS 43 44This module should not be used directly. Instead, use C<Amanda::Application> or 45C<Amanda::Script>. 46 47=cut 48 49sub new { 50 my $class = shift; 51 my ($execute_where, $type, $config_name) = @_; 52 53 my $self = {}; 54 bless ($self, $class); 55 56 # extract the last component of the class name 57 my $name = $class; 58 $name =~ s/^.*:://; 59 $self->{'name'} = $name; 60 61 if(!defined $execute_where) { 62 $execute_where = "client"; 63 } 64 Amanda::Util::setup_application($name, $execute_where, $CONTEXT_DAEMON); 65 debug("Arguments: " . join(' ', @ARGV)); 66 67 #initialize config client to get values from amanda-client.conf 68 config_init($CONFIG_INIT_CLIENT, undef); 69 my ($cfgerr_level, @cfgerr_errors) = config_errors(); 70 if ($cfgerr_level >= $CFGERR_WARNINGS) { 71 config_print_errors(); 72 if ($cfgerr_level >= $CFGERR_ERRORS) { 73 confess("errors processing config file"); 74 } 75 } 76 if ($config_name) { 77 config_init($CONFIG_INIT_CLIENT | $CONFIG_INIT_EXPLICIT_NAME | $CONFIG_INIT_OVERLAY, $config_name); 78 ($cfgerr_level, @cfgerr_errors) = config_errors(); 79 if ($cfgerr_level >= $CFGERR_WARNINGS) { 80 config_print_errors(); 81 if ($cfgerr_level >= $CFGERR_ERRORS) { 82 confess("errors processing config file for $config_name"); 83 } 84 } 85 } 86 87 Amanda::Util::finish_setup($RUNNING_AS_ANY); 88 89 $self->{error_status} = $Amanda::Script_App::GOOD; 90 $self->{type} = $type; 91 $self->{known_commands} = {}; 92 93 debug("$type: $name\n"); 94 95 return $self; 96} 97 98 99#$_[0] message 100#$_[1] status: GOOD or ERROR 101sub print_to_server { 102 my $self = shift; 103 my($msg, $status) = @_; 104 Amanda::Debug::debug($msg); 105 106 if ($status != 0) { 107 $self->{error_status} = $status; 108 } 109 if ($self->{action} eq "check") { 110 if ($status == $Amanda::Script_App::GOOD) { 111 print STDOUT "OK $msg\n"; 112 } else { 113 print STDOUT "ERROR $msg\n"; 114 } 115 } elsif ($self->{action} eq "estimate") { 116 if ($status == $Amanda::Script_App::GOOD) { 117 #do nothing 118 } else { 119 print STDERR "ERROR $msg\n"; 120 } 121 } elsif ($self->{action} eq "backup") { 122 if ($status == $Amanda::Script_App::GOOD) { 123 print {$self->{mesgout}} "| $msg\n"; 124 } elsif ($status == $Amanda::Script_App::ERROR) { 125 print {$self->{mesgout}} "? $msg\n"; 126 } else { 127 print {$self->{mesgout}} "sendbackup: error [$msg]\n"; 128 } 129 } elsif ($self->{action} eq "restore") { 130 print STDERR "$msg\n"; 131 } elsif ($self->{action} eq "validate") { 132 print STDERR "$msg\n"; 133 } else { 134 print STDERR "$msg\n"; 135 } 136} 137 138#$_[0] message 139#$_[1] status: GOOD or ERROR 140sub print_to_server_and_die { 141 my $self = shift; 142 my($msg, $status) = @_; 143 144 $status = $Amanda::Script_App::FAILURE; 145 146 $self->print_to_server($msg, $status); 147 if (!defined $self->{die} && $self->can("check_for_backup_failure")) { 148 $self->{die} = 1; 149 $self->check_for_backup_failure(); 150 } 151 exit 1; 152} 153 154 155sub do { 156 my $self = shift; 157 my $command = shift; 158 159 if (!defined $command) { 160 $self->print_to_server_and_die("check", "no command", 161 $Amanda::Script_App::ERROR); 162 return; 163 } 164 $command =~ tr/A-Z-/a-z_/; 165 debug("command: $command"); 166 167 # first make sure this is a valid command. 168 if (!exists($self->{known_commands}->{$command})) { 169 print STDERR "Unknown command `$command'.\n"; 170 exit 1; 171 } 172 173 my $action = $command; 174 $action =~ s/^pre_//; 175 $action =~ s/^post_//; 176 $action =~ s/^inter_//; 177 $action =~ s/^dle_//; 178 $action =~ s/^host_//; 179 $action =~ s/^level_//; 180 181 if ($action eq 'amcheck' || $action eq 'selfcheck') { 182 $self->{action} = 'check'; 183 } elsif ($action eq 'estimate') { 184 $self->{action} = 'estimate'; 185 } elsif ($action eq 'backup') { 186 $self->{action} = 'backup'; 187 } elsif ($action eq 'recover' || $action eq 'restore') { 188 $self->{action} = 'restore'; 189 } elsif ($action eq 'validate') { 190 $self->{action} = 'validate'; 191 } else { 192 $self->{action} = $action; 193 } 194 195 if ($action eq 'backup') { 196 $self->_set_mesgout(); 197 } 198 199 # now convert it to a function name and see if it's 200 # defined 201 my $function_name = "command_$command"; 202 my $default_name = "default_$command"; 203 204 if (!$self->can($function_name)) { 205 if (!$self->can($default_name)) { 206 print STDERR "command `$command' is not supported by the '" . 207 $self->{name} . "' " . $self->{type} . ".\n"; 208 exit 1; 209 } 210 $self->$default_name(); 211 return; 212 } 213 214 # it exists -- call it 215 $self->$function_name(); 216 217 Amanda::Util::finish_application(); 218 exit($self->{'error_status'}); 219} 220 2211; 222