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