5 Copyright (C) 2006 Eric Bollengier
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 ################################################################
30 # Manage with Expect the bconsole tool
35 # my $pref = new Pref(config_file => 'brestore.conf');
36 # my $bconsole = new Bconsole(pref => $pref);
39 my ($class, %arg) = @_;
42 pref => $arg{pref}, # Pref object
43 bconsole => undef, # Expect object
44 log_stdout => $arg{log_stdout} || 0,
45 timeout => $arg{debug} || 10,
46 debug => $arg{debug} || 0,
54 my ($self, %arg) = @_;
57 for my $key (keys %arg) {
59 $arg{$key} =~ tr/""/ /;
60 $cmd .= "$key=\"$arg{$key}\" ";
64 unless ($self->connect()) {
68 print "=> $cmd yes\n";
70 $self->{bconsole}->clear_accum();
71 $self->send("$cmd yes\n");
72 $self->expect_it('-re',qr/^[*]/);
73 my $ret = $self->before();
74 if ($ret =~ /jobid=(\d+)/is) {
83 my ($self, $what) = @_;
84 $self->{bconsole}->send($what);
89 my ($self, @what) = @_;
90 unless ($self->{bconsole}->expect($self->{timeout}, @what)) {
99 my ($self, $how) = @_;
101 if ($self->{bconsole}) {
102 $self->{bconsole}->log_stdout($how);
105 $self->{log_stdout} = $how;
112 if ($self->{error}) {
116 unless ($self->{bconsole}) {
117 my @cmd = split(/\s+/, $self->{pref}->{bconsole}) ;
119 $self->{error} = "bconsole string not found";
122 $self->{bconsole} = new Expect;
123 $self->{bconsole}->raw_pty(0);
124 $self->{bconsole}->debug($self->{debug});
125 $self->{bconsole}->log_stdout($self->{debug} || $self->{log_stdout});
127 # WARNING : die is trapped by gtk_main_loop()
128 # and exit() closes DBI connection
131 my $sav = $SIG{__DIE__};
132 $SIG{__DIE__} = sub { _exit 1 ;};
133 $ret = $self->{bconsole}->spawn(@cmd) ;
134 $SIG{__DIE__} = $sav;
142 # TODO : we must verify that expect return the good value
144 $self->expect_it('*');
145 $self->send_cmd('gui on');
152 my ($self, $jobid) = @_;
153 return $self->send_cmd("cancel jobid=$jobid");
156 # get text between to expect
160 return $self->{bconsole}->before();
165 my ($self, $cmd) = @_;
166 unless ($self->connect()) {
169 $self->send("$cmd\n");
170 $self->expect_it($cmd);
171 $self->{bconsole}->clear_accum();
172 $self->expect_it('-re',qr/^[*]/);
173 return $self->before();
178 my ($self, $cmd) = @_;
179 unless ($self->connect()) {
182 $self->send("$cmd\n");
183 $self->expect_it('-re', '[?].+:');
185 $self->send("yes\n");
186 $self->expect_it("yes");
187 $self->{bconsole}->clear_accum();
188 $self->expect_it('-re',qr/^[*]/);
189 return $self->before();
192 sub send_cmd_with_drive
194 my ($self, $cmd, $drive) = @_;
195 $drive = $drive || '0';
197 unless ($self->connect()) {
200 $self->send("$cmd\n");
201 $self->expect_it('-re', qr/:/); # wait for drive input
203 $self->send("$drive\n");
204 $self->expect_it('-re', '[0-9]');
205 $self->{bconsole}->clear_accum();
206 $self->expect_it('-re',qr/^[*]/);
207 return $self->before();
212 my ($self, %arg) = @_;
214 unless ($arg{storage}) {
218 unless ($self->connect()) {
222 $arg{drive} = $arg{drive} || '0' ;
223 $arg{pool} = $arg{pool} || 'Scratch';
225 my $cmd = "label barcodes pool=\"$arg{pool}\" storage=\"$arg{storage}\"";
228 $cmd .= " slots=$arg{slots}";
231 $self->send("$cmd\n");
232 $self->expect_it('-re', ':'); # wait for drive input
233 $self->send("$arg{drive}\n");
234 $self->expect_it('-re', '[?].+\)\s*:');
235 my $res = $self->before();
236 $self->send("yes\n");
237 $self->expect_it("yes");
238 $res .= $self->before();
239 $self->expect_it('-re',qr/^[*]/);
240 $res .= $self->before();
245 # return [ { name => 'test1', vol => '00001', ... },
246 # { name => 'test2', vol => '00002', ... }... ]
248 sub director_get_sched
250 my ($self, $days) = @_ ;
254 unless ($self->connect()) {
258 my $status = $self->send_cmd("st director days=$days") ;
261 foreach my $l (split(/\r?\n/, $status)) {
262 #Level Type Pri Scheduled Name Volume
263 #Incremental Backup 11 03-ao-06 23:05 TEST_DATA 000001
264 if ($l =~ /^(I|F|Di)\w+\s+\w+\s+\d+/i) {
265 my ($level, $type, $pri, $d, $h, @name_vol) = split(/\s+/, $l);
267 my $vol = pop @name_vol; # last element
268 my $name = join(" ", @name_vol); # can contains space
286 my ($self, $storage, $drive) = @_;
288 return $self->send_cmd_with_drive("update slots storage=$storage", $drive);
293 my ($self, $fs) = @_;
295 my $out = $self->send_cmd("show fileset=\"$fs\"");
299 foreach my $l (split(/\r\n/, $out)) {
301 if ($l =~ /^\s+([I|E])\s+(.+)$/) { # include
302 push @{$ret->{$1}}, { file => $2 };
312 return split(/\r\n/, $self->send_cmd(".jobs"));
318 return split(/\r\n/, $self->send_cmd(".filesets"));
324 return split(/\r\n/, $self->send_cmd(".storage"));
330 return split(/\r\n/, $self->send_cmd(".clients"));
336 return split(/\r\n/, $self->send_cmd(".pools"));
339 use Time::ParseDate qw/parsedate/;
340 use POSIX qw/strftime/;
345 my ($self, @volume) = @_;
346 return '' unless (@volume);
349 foreach my $vol (@volume) {
350 if ($vol =~ /^([\w\d\.-]+)$/) {
351 $sel .= " volume=$1";
354 $self->{error} = "Sorry media is bad";
364 my ($self, @volume) = @_;
366 my $sel = $self->_get_volume(@volume);
369 $ret = $self->send_cmd("purge $sel");
371 $ret = $self->{error};
378 my ($self, @volume) = @_;
380 my $sel = $self->_get_volume(@volume);
383 $ret = $self->send_cmd_yes("prune $sel");
385 $ret = $self->{error};
392 my ($self, @jobid) = @_;
394 return 0 unless (@jobid);
397 foreach my $job (@jobid) {
398 if ($job =~ /^(\d+)$/) {
402 $self->{error} = "Sorry jobid is bad";
407 $self->send_cmd("purge $sel");
413 $self->send("quit\n");
414 $self->{bconsole}->soft_close();
415 $self->{bconsole} = undef;
423 # grep -v __END__ Bconsole.pm | perl
427 print "test sans conio\n";
429 my $c = new Bconsole(pref => {
430 bconsole => '/tmp/bacula/sbin/bconsole -n -c /tmp/bacula/etc/bconsole.conf',
434 print "fileset : ", join(',', $c->list_fileset()), "\n";
435 print "job : ", join(',', $c->list_job()), "\n";
436 print "storage : ", join(',', $c->list_storage()), "\n";
437 #print "prune : " . $c->prune_volume('000001'), "\n";
438 #print "update : " . $c->send_cmd_with_drive('update slots storage=SDLT-1-2'), "\n";
439 #print "label : ", join(',', $c->label_barcodes(storage => 'SDLT-1-2',
441 # drive => 0)), "\n";