5 Bweb - A Bacula web interface
6 Bacula® - The Network Backup Solution
8 Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
10 The main author of Bweb is Eric Bollengier.
11 The main author of Bacula is Kern Sibbald, with contributions from
12 many others, a complete list can be found in the file AUTHORS.
14 This program is Free Software; you can redistribute it and/or
15 modify it under the terms of version two of the GNU General Public
16 License as published by the Free Software Foundation plus additions
17 that are listed in the file LICENSE.
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
29 Bacula® is a registered trademark of John Walker.
30 The licensor of Bacula is the Free Software Foundation Europe
31 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zurich,
32 Switzerland, email:ftf@fsfeurope.org.
41 ################################################################
42 # Manage with Expect the bconsole tool
47 # my $pref = new Pref(config_file => 'brestore.conf');
48 # my $bconsole = new Bconsole(pref => $pref);
51 my ($class, %arg) = @_;
54 pref => $arg{pref}, # Pref object
55 bconsole => undef, # Expect object
56 log_stdout => $arg{log_stdout} || 0,
57 timeout => $arg{timeout} || 20,
58 debug => $arg{debug} || 0,
66 my ($self, %arg) = @_;
69 for my $key (keys %arg) {
71 $arg{$key} =~ tr/""/ /;
72 $cmd .= "$key=\"$arg{$key}\" ";
76 unless ($self->connect()) {
80 print STDERR "===> $cmd yes\n";
81 $self->{bconsole}->clear_accum();
82 $self->send("$cmd yes\n");
83 $self->expect_it('-re',qr/^[*]/);
84 my $ret = $self->before();
85 if ($ret =~ /jobid=(\d+)/is) {
92 # for brestore.pl::BwebConsole
100 my ($self, $what) = @_;
101 $self->{bconsole}->send($what);
106 my ($self, @what) = @_;
107 unless ($self->{bconsole}->expect($self->{timeout}, @what)) {
116 my ($self, $how) = @_;
118 if ($self->{bconsole}) {
119 $self->{bconsole}->log_stdout($how);
122 $self->{log_stdout} = $how;
127 my ($self, $error) = @_;
129 print STDERR "E: bconsole (", $self->{pref}->{bconsole}, ") $!\n";
137 if ($self->{error}) {
141 unless ($self->{bconsole}) {
142 my @cmd = split(/\s+/, $self->{pref}->{bconsole}) ;
144 return $self->error("bconsole string not found");
146 $self->{bconsole} = new Expect;
147 $self->{bconsole}->raw_pty(0);
148 $self->{bconsole}->debug($self->{debug});
149 $self->{bconsole}->log_stdout($self->{debug} || $self->{log_stdout});
151 # WARNING : die is trapped by gtk_main_loop()
152 # and exit() closes DBI connection
155 my $sav = $SIG{__DIE__};
156 $SIG{__DIE__} = sub { _exit 1 ;};
157 my $old = $ENV{COLUMNS};
159 $ret = $self->{bconsole}->spawn(@cmd) ;
160 delete $ENV{COLUMNS};
161 $ENV{COLUMNS} = $old if ($old) ;
162 $SIG{__DIE__} = $sav;
166 return $self->error($ret);
169 # TODO : we must verify that expect return the good value
171 $self->expect_it('*');
172 $self->send_cmd('gui on');
179 my ($self, $jobid) = @_;
180 return $self->send_cmd("cancel jobid=$jobid");
183 # get text between to expect
187 return $self->{bconsole}->before();
192 my ($self, $cmd) = @_;
193 unless ($self->connect()) {
196 $self->send("$cmd\n");
197 $self->expect_it($cmd);
198 $self->{bconsole}->clear_accum();
199 $self->expect_it('-re',qr/^[*]/);
200 return $self->before();
205 my ($self, $cmd) = @_;
206 unless ($self->connect()) {
209 $self->send("$cmd\n");
210 $self->expect_it('-re', '[?].+:');
212 $self->send("yes\n");
213 $self->expect_it("yes");
214 $self->{bconsole}->clear_accum();
215 $self->expect_it('-re',qr/^[*]/);
216 return $self->before();
221 my ($self, %arg) = @_;
223 unless ($arg{storage}) {
227 unless ($self->connect()) {
231 $arg{drive} = $arg{drive} || '0' ;
232 $arg{pool} = $arg{pool} || 'Scratch';
234 my $cmd = "label barcodes drive=$arg{drive} pool=\"$arg{pool}\" storage=\"$arg{storage}\"";
237 $cmd .= " slots=$arg{slots}";
240 $self->send("$cmd\n");
241 $self->expect_it('-re', '[?].+\).*:');
242 my $res = $self->before();
243 $self->send("yes\n");
244 $self->expect_it("yes");
245 $res .= $self->before();
246 $self->expect_it('-re',qr/^[*]/);
247 $res .= $self->before();
252 # return [ { name => 'test1', vol => '00001', ... },
253 # { name => 'test2', vol => '00002', ... }... ]
255 sub director_get_sched
257 my ($self, $days) = @_ ;
261 unless ($self->connect()) {
265 my $status = $self->send_cmd("st director days=$days") ;
268 foreach my $l (split(/\r?\n/, $status)) {
269 #Level Type Pri Scheduled Name Volume
270 #Incremental Backup 11 03-ao-06 23:05 TEST_DATA 000001
271 if ($l =~ /^(I|F|Di)\w+\s+\w+\s+\d+/i) {
272 my ($level, $type, $pri, $d, $h, @name_vol) = split(/\s+/, $l);
274 my $vol = pop @name_vol; # last element
275 my $name = join(" ", @name_vol); # can contains space
293 my ($self, $storage, $drive) = @_;
294 $drive = $drive || 0;
296 return $self->send_cmd("update slots storage=$storage drive=$drive");
301 my ($self, $fs) = @_;
303 my $out = $self->send_cmd("show fileset=\"$fs\"");
307 foreach my $l (split(/\r\n/, $out)) {
309 if ($l =~ /^\s+([I|E])\s+(.+)$/) { # include
310 push @{$ret->{$1}}, { file => $2 };
320 return split(/\r\n/, $self->send_cmd(".jobs"));
326 return split(/\r\n/, $self->send_cmd(".filesets"));
332 return split(/\r\n/, $self->send_cmd(".storage"));
338 return split(/\r\n/, $self->send_cmd(".clients"));
344 return split(/\r\n/, $self->send_cmd(".pools"));
347 use Time::ParseDate qw/parsedate/;
348 use POSIX qw/strftime/;
353 my ($self, @volume) = @_;
354 return '' unless (@volume);
357 foreach my $vol (@volume) {
358 if ($vol =~ /^([\w\d\.-]+)$/) {
359 $sel .= " volume=$1";
362 $self->error("Sorry media is bad");
372 my ($self, @volume) = @_;
374 my $sel = $self->_get_volume(@volume);
377 $ret = $self->send_cmd("purge $sel");
379 $ret = $self->{error};
386 my ($self, @volume) = @_;
388 my $sel = $self->_get_volume(@volume);
391 $ret = $self->send_cmd("prune $sel yes");
393 $ret = $self->{error};
400 my ($self, @jobid) = @_;
402 return 0 unless (@jobid);
405 foreach my $job (@jobid) {
406 if ($job =~ /^(\d+)$/) {
410 return $self->error("Sorry jobid is bad");
414 $self->send_cmd("purge $sel");
420 $self->send("quit\n");
421 $self->{bconsole}->soft_close();
422 $self->{bconsole} = undef;
430 # grep -v __END__ Bconsole.pm | perl
434 print "test sans conio\n";
436 my $c = new Bconsole(pref => {
437 bconsole => '/tmp/bacula/sbin/bconsole -n -c /tmp/bacula/etc/bconsole.conf',
441 print "fileset : ", join(',', $c->list_fileset()), "\n";
442 print "job : ", join(',', $c->list_job()), "\n";
443 print "storage : ", join(',', $c->list_storage()), "\n";
444 #print "prune : " . $c->prune_volume('000001'), "\n";
445 #print "update : " . $c->send_cmd('update slots storage=SDLT-1-2, drive=0'), "\n";
446 #print "label : ", join(',', $c->label_barcodes(storage => 'SDLT-1-2',
448 # drive => 0)), "\n";