Imported Upstream version 3.3.0
[debian/amanda] / perl / Amanda / Interactivity.pm
diff --git a/perl/Amanda/Interactivity.pm b/perl/Amanda/Interactivity.pm
new file mode 100644 (file)
index 0000000..25fe79d
--- /dev/null
@@ -0,0 +1,151 @@
+# Copyright (c) 2010 Zmanda, Inc.  All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
+# Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
+
+package Amanda::Interactivity;
+
+=head1 NAME
+
+Amanda::Interactivity -- Parent class for user interactivity modules
+
+=head1 SYNOPSIS
+
+    use Amanda::Interactivity;
+
+    my $inter = Amanda::Interactivity->new(name => 'stdin');
+    $inter->user_request(
+       message => "Insert Volume labelled 'MY_LABEL-001' in changer DLT",
+       label => 'MY_LABEL-001',
+       new_volume => 0,
+       chg_name => 'DLT',
+       err => "Not found in the library",
+       request_cb => sub {
+           my ($err, $reply) = @_;
+           if ($err) {
+               # error from the script
+           } elsif (!defined $reply) {
+               # request aborted
+           } else {
+               # use reply
+           }
+       });
+
+=head1 SUMMARY
+
+This package provides a way for Amanda programs to communicate interactivityly
+with the user.  The program can send a message to the user and await a textual
+response.  The package operates asynchronously (see L<Amanda::MainLoop>), so
+the program may continue with other activities while waiting for an answer from
+the user.
+
+Several interactivity modules are (or soon will be) available, and can be
+selected by the user.
+
+=head1 INTERFACE
+
+A new object is create with the C<new> function as follows:
+
+    my $inter = Amanda::Interactivity->new(
+       name => $interactivity_name);
+
+Where C<$interactivity_name> is the name of the desired interactivity defined
+in the config file.
+
+=head2 INTERACTIVITY OBJECTS
+
+=head3 user_request
+
+  $inter->user_request(message     => $message,
+                       label       => $label,
+                       new_volume  => 0|1,
+                       err         => $err,
+                       chg_name    => $chg_name,
+                       request_cb  => $request_cb);
+
+This method return immediately.  It sends a message to the user and waits for a
+reply.
+ C<err> is the reason why the volume is needed.
+ C<message> is a sentence describing the requested volume.
+ The volume can be describe with many parameters:
+  C<label> is the requested label or the most prefered label.
+  C<new_volume> if a new volume is acceptable.
+  C<chg_name> the name of the changer where amanda expect the volume.
+
+A module can print only C<message> or build something prettier with the values
+of the other parameters.
+
+The C<request_cb> callback take one or two arguments.  In the even of an
+error, it is called with an C<Amanda::Changer::Error> object as first argument.
+If the request is answered, then the first argument is C<undef> and the second
+argument is the user's response.  If the request is aborted (see C<abort>,
+below), then both arguments are C<undef>.
+
+=head3 abort
+
+  $inter->abort()
+
+This method will abort all pending C<user_request> invocations, invoking their
+C<request_cb> with C<(undef, undef)>.
+
+=cut
+
+use Amanda::Config qw( :getconf );
+
+sub new {
+    shift eq 'Amanda::Interactivity'
+       or return;
+    my %params = @_;
+    my $interactivity_name = $params{'name'};
+
+    return undef if !defined $interactivity_name or $interactivity_name eq '';
+
+    my $interactivity = Amanda::Config::lookup_interactivity($interactivity_name);
+    my $plugin;
+    my $property;
+    if ($interactivity) {
+       $plugin = Amanda::Config::interactivity_getconf($interactivity, $INTERACTIVITY_PLUGIN);
+       $property = Amanda::Config::interactivity_getconf($interactivity, $INTERACTIVITY_PROPERTY);
+    } else {
+       $plugin = $interactivity_name;
+    }
+
+    die("No name for Amanda::Interactivity->(new)") if !defined $plugin;
+
+    my $pkgname = "Amanda::Interactivity::$plugin";
+    my $filename = $pkgname;
+    $filename =~ s|::|/|g;
+    $filename .= '.pm';
+
+    if (!exists $INC{$filename}) {
+       eval "use $pkgname;";
+       if ($@) {
+           my $err = $@;
+           die ($err);
+       }
+    }
+
+    my $self = eval {$pkgname->new($property);};
+    if ($@ || !defined $self) {
+       print STDERR "Can't instantiate $pkgname\n";
+       debug("Can't instantiate $pkgname");
+       die("Can't instantiate $pkgname");
+    }
+
+    return $self;
+}
+
+1;