25fe79de687e1740bfb44f2415e8e63a03ca203e
[debian/amanda] / perl / Amanda / Interactivity.pm
1 # Copyright (c) 2010 Zmanda, Inc.  All Rights Reserved.
2 #
3 # This program is free software; you can redistribute it and/or modify it
4 # under the terms of the GNU General Public License version 2 as published
5 # by the Free Software Foundation.
6 #
7 # This program is distributed in the hope that it will be useful, but
8 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
9 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
10 # for more details.
11 #
12 # You should have received a copy of the GNU General Public License along
13 # with this program; if not, write to the Free Software Foundation, Inc.,
14 # 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
15 #
16 # Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
17 # Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
18
19 package Amanda::Interactivity;
20
21 =head1 NAME
22
23 Amanda::Interactivity -- Parent class for user interactivity modules
24
25 =head1 SYNOPSIS
26
27     use Amanda::Interactivity;
28
29     my $inter = Amanda::Interactivity->new(name => 'stdin');
30     $inter->user_request(
31         message => "Insert Volume labelled 'MY_LABEL-001' in changer DLT",
32         label => 'MY_LABEL-001',
33         new_volume => 0,
34         chg_name => 'DLT',
35         err => "Not found in the library",
36         request_cb => sub {
37             my ($err, $reply) = @_;
38             if ($err) {
39                 # error from the script
40             } elsif (!defined $reply) {
41                 # request aborted
42             } else {
43                 # use reply
44             }
45         });
46
47 =head1 SUMMARY
48
49 This package provides a way for Amanda programs to communicate interactivityly
50 with the user.  The program can send a message to the user and await a textual
51 response.  The package operates asynchronously (see L<Amanda::MainLoop>), so
52 the program may continue with other activities while waiting for an answer from
53 the user.
54
55 Several interactivity modules are (or soon will be) available, and can be
56 selected by the user.
57
58 =head1 INTERFACE
59
60 A new object is create with the C<new> function as follows:
61
62     my $inter = Amanda::Interactivity->new(
63         name => $interactivity_name);
64
65 Where C<$interactivity_name> is the name of the desired interactivity defined
66 in the config file.
67
68 =head2 INTERACTIVITY OBJECTS
69
70 =head3 user_request
71
72   $inter->user_request(message     => $message,
73                        label       => $label,
74                        new_volume  => 0|1,
75                        err         => $err,
76                        chg_name    => $chg_name,
77                        request_cb  => $request_cb);
78
79 This method return immediately.  It sends a message to the user and waits for a
80 reply.
81  C<err> is the reason why the volume is needed.
82  C<message> is a sentence describing the requested volume.
83  The volume can be describe with many parameters:
84   C<label> is the requested label or the most prefered label.
85   C<new_volume> if a new volume is acceptable.
86   C<chg_name> the name of the changer where amanda expect the volume.
87
88 A module can print only C<message> or build something prettier with the values
89 of the other parameters.
90
91 The C<request_cb> callback take one or two arguments.  In the even of an
92 error, it is called with an C<Amanda::Changer::Error> object as first argument.
93 If the request is answered, then the first argument is C<undef> and the second
94 argument is the user's response.  If the request is aborted (see C<abort>,
95 below), then both arguments are C<undef>.
96
97 =head3 abort
98
99   $inter->abort()
100
101 This method will abort all pending C<user_request> invocations, invoking their
102 C<request_cb> with C<(undef, undef)>.
103
104 =cut
105
106 use Amanda::Config qw( :getconf );
107
108 sub new {
109     shift eq 'Amanda::Interactivity'
110         or return;
111     my %params = @_;
112     my $interactivity_name = $params{'name'};
113
114     return undef if !defined $interactivity_name or $interactivity_name eq '';
115
116     my $interactivity = Amanda::Config::lookup_interactivity($interactivity_name);
117     my $plugin;
118     my $property;
119     if ($interactivity) {
120         $plugin = Amanda::Config::interactivity_getconf($interactivity, $INTERACTIVITY_PLUGIN);
121         $property = Amanda::Config::interactivity_getconf($interactivity, $INTERACTIVITY_PROPERTY);
122     } else {
123         $plugin = $interactivity_name;
124     }
125
126     die("No name for Amanda::Interactivity->(new)") if !defined $plugin;
127
128     my $pkgname = "Amanda::Interactivity::$plugin";
129     my $filename = $pkgname;
130     $filename =~ s|::|/|g;
131     $filename .= '.pm';
132
133     if (!exists $INC{$filename}) {
134         eval "use $pkgname;";
135         if ($@) {
136             my $err = $@;
137             die ($err);
138         }
139     }
140
141     my $self = eval {$pkgname->new($property);};
142     if ($@ || !defined $self) {
143         print STDERR "Can't instantiate $pkgname\n";
144         debug("Can't instantiate $pkgname");
145         die("Can't instantiate $pkgname");
146     }
147
148     return $self;
149 }
150
151 1;