From c70d6b583c464a5e23c5ad9b348c8a22fe7d62e9 Mon Sep 17 00:00:00 2001 From: Eric Bollengier Date: Sat, 24 Nov 2007 00:08:52 +0000 Subject: [PATCH] ebl Add brestore_xxx tables to sql scripts ebl Add a batch=1 option to bresto.pl to fill bresto tables ebl Adapt Bconsole.pm to run a restore job ebl Make bresto.html/js working (you can restore files now) git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@5971 91ce42f0-d328-0410-95d8-f526ca767f89 --- gui/bweb/cgi/bresto.pl | 205 ++++++++++++++----------- gui/bweb/html/bresto.js | 228 ++++++++++++++-------------- gui/bweb/lib/Bconsole.pm | 12 +- gui/bweb/script/bweb-mysql.sql | 39 +++++ gui/bweb/script/bweb-postgresql.sql | 34 +++++ gui/bweb/technotes-2.3 | 4 + 6 files changed, 323 insertions(+), 199 deletions(-) diff --git a/gui/bweb/cgi/bresto.pl b/gui/bweb/cgi/bresto.pl index a8f28dbfb6..6a77af6c63 100755 --- a/gui/bweb/cgi/bresto.pl +++ b/gui/bweb/cgi/bresto.pl @@ -178,12 +178,13 @@ sub update_brestore_table print STDERR "Creating missing recursion paths for $job\n"; - $query = "SELECT brestore_pathvisibility.PathId, Path FROM brestore_pathvisibility - JOIN Path ON( brestore_pathvisibility.PathId = Path.PathId) - LEFT JOIN brestore_pathhierarchy ON (brestore_pathvisibility.PathId = brestore_pathhierarchy.PathId) - WHERE brestore_pathvisibility.JobId = $job - AND brestore_pathhierarchy.PathId IS NULL - ORDER BY Path"; + $query = " +SELECT brestore_pathvisibility.PathId, Path FROM brestore_pathvisibility + JOIN Path ON( brestore_pathvisibility.PathId = Path.PathId) + LEFT JOIN brestore_pathhierarchy ON (brestore_pathvisibility.PathId = brestore_pathhierarchy.PathId) + WHERE brestore_pathvisibility.JobId = $job + AND brestore_pathhierarchy.PathId IS NULL + ORDER BY Path"; my $sth = $self->dbh_prepare($query); $sth->execute(); @@ -200,19 +201,17 @@ sub update_brestore_table # This query gives all parent pathids for a given jobid that aren't stored. # It has to be called until no record is updated ... $query = " - INSERT INTO brestore_pathvisibility (PathId, JobId) ( - SELECT a.PathId,$job - FROM - (SELECT DISTINCT h.PPathId AS PathId - FROM brestore_pathhierarchy AS h - JOIN brestore_pathvisibility AS p ON (h.PathId=p.PathId) - WHERE p.JobId=$job) AS a - LEFT JOIN - (SELECT PathId - FROM brestore_pathvisibility - WHERE JobId=$job) AS b - ON (a.PathId = b.PathId) - WHERE b.PathId IS NULL)"; +INSERT INTO brestore_pathvisibility (PathId, JobId) ( + SELECT a.PathId,$job + FROM ( + SELECT DISTINCT h.PPathId AS PathId + FROM brestore_pathhierarchy AS h + JOIN brestore_pathvisibility AS p ON (h.PathId=p.PathId) + WHERE p.JobId=$job) AS a LEFT JOIN + (SELECT PathId + FROM brestore_pathvisibility + WHERE JobId=$job) AS b ON (a.PathId = b.PathId) + WHERE b.PathId IS NULL)"; my $rows_affected; while (($rows_affected = $self->dbh_do($query)) and ($rows_affected !~ /^0/)) @@ -338,16 +337,15 @@ sub ls_files my $query = "SELECT File.FilenameId, listfiles.id, listfiles.Name, File.LStat, File.JobId - FROM - (SELECT Filename.Name, max(File.FileId) as id + FROM File, ( + SELECT Filename.Name, max(File.FileId) as id FROM File, Filename - WHERE File.FilenameId = Filename.FilenameId - AND Filename.Name != '' - AND File.PathId IN ($inlistpath) - AND File.JobId IN ($inclause) - GROUP BY Filename.Name - ORDER BY Filename.Name) AS listfiles, -File + WHERE File.FilenameId = Filename.FilenameId + AND Filename.Name != '' + AND File.PathId IN ($inlistpath) + AND File.JobId IN ($inclause) + GROUP BY Filename.Name + ORDER BY Filename.Name) AS listfiles WHERE File.FileId = listfiles.id"; $self->debug($query); @@ -453,14 +451,16 @@ sub set_job_ids_for_date # incrementals and differentials until we have found a full so it goes # like this : store all incrementals until we have found a differential # or a full, then find the full - my $query = "SELECT JobId, FileSet, Level, JobStatus - FROM Job JOIN FileSet USING (FileSetId) - JOIN Client USING (ClientId) $filter - WHERE EndTime <= $date - AND Client.Name = '$client' - AND Type IN ('B') - AND JobStatus IN ('T') - ORDER BY FileSet, JobTDate DESC"; + my $query = " +SELECT JobId, FileSet, Level, JobStatus + FROM Job + JOIN FileSet USING (FileSetId) + JOIN Client USING (ClientId) $filter + WHERE EndTime <= $date + AND Client.Name = '$client' + AND Type IN ('B') + AND JobStatus IN ('T') + ORDER BY FileSet, JobTDate DESC"; my @CurrentJobIds; my $result = $self->dbh_selectall_arrayref($query); @@ -738,9 +738,13 @@ my $action = CGI::param('action') || ''; my $args = $bvfs->get_form('pathid', 'filenameid', 'fileid', 'qdate', 'limit', 'offset', 'client'); -print CGI::header('application/x-javascript'); +if (CGI::param('batch')) { + $bvfs->update_cache(); + exit 0; +} if ($action eq 'list_client') { + print CGI::header('application/x-javascript'); my $filter = $bvfs->get_client_filter(); my $q = "SELECT Name FROM Client $filter"; @@ -752,6 +756,7 @@ if ($action eq 'list_client') { exit 0; } elsif ($action eq 'list_job') { + print CGI::header('application/x-javascript'); my $filter = $bvfs->get_client_filter(); my $query = " @@ -766,12 +771,13 @@ if ($action eq 'list_client') { print "["; print join(',', map { - "[$_->[4], '$_->[0]', '$_->[0] $_->[1] $_->[2] ($_->[3])']" + "[$_->[4], '$_->[0]', '$_->[0] $_->[1] $_->[2] ($_->[3]) $_->[4]']" } @$result); print "]\n"; exit 0; } elsif ($action eq 'list_storage') { # TODO: use .storage hier + print CGI::header('application/x-javascript'); my $q="SELECT Name FROM Storage"; my $lst = $bvfs->dbh_selectall_arrayref($q); @@ -781,7 +787,7 @@ if ($action eq 'list_client') { exit 0; } -my @jobid = $bvfs->get_jobids(grep { /^\d+$/ } CGI::param('jobid')); +my @jobid = $bvfs->get_jobids(grep { /^\d+(,\d+)*$/ } CGI::param('jobid')); if (!scalar(@jobid) and $args->{qdate} and $args->{client}) { @jobid = $bvfs->set_job_ids_for_date($args->{client}, $args->{qdate}); } @@ -809,6 +815,75 @@ if ($pathid =~ /^(\d+)$/) { $bvfs->ch_dir($pathid); +if ($action eq 'restore') { + + # TODO: pouvoir choisir le replace et le jobname + my $arg = $bvfs->get_form(qw/client storage regexwhere where/); + + if (!$arg->{client}) { + print "ERROR: missing client\n"; + exit 1; + } + + my $fileid = join(',', grep { /^\d+$/ } CGI::param('fileid')); + my @dirid = grep { /^\d+$/ } CGI::param('dirid'); + my $inclause = join(',', @jobid); + + my @union; + + if ($fileid) { + push @union, + "(SELECT JobId, FileIndex, FilenameId, PathId FROM File WHERE FileId IN ($fileid))"; + } + + # using this is not good because the sql engine doesn't know + # what LIKE will use. It will be better to get Path% in perl + # but it doesn't work with accents... :( + foreach my $dirid (@dirid) { + push @union, " + (SELECT File.JobId, File.FileIndex, File.FilenameId, File.PathId + FROM Path JOIN File USING (PathId) + WHERE Path.Path LIKE + (SELECT ". $bvfs->dbh_strcat('Path',"'\%'") ." FROM Path + WHERE PathId = $dirid + ) + AND File.JobId IN ($inclause))"; + } + + return unless scalar(@union); + + my $u = join(" UNION ", @union); + + $bvfs->dbh_do("CREATE TEMPORARY TABLE btemp AS ($u)"); + # TODO: remove FilenameId et PathId + $bvfs->dbh_do("CREATE TABLE b2$$ AS ( +SELECT btemp.JobId, btemp.FileIndex, btemp.FilenameId, btemp.PathId + FROM btemp, + (SELECT max(JobId) as JobId, PathId, FilenameId + FROM btemp + GROUP BY PathId, FilenameId + ORDER BY JobId DESC) AS a + WHERE a.JobId = btemp.JobId + AND a.PathId= btemp.PathId + AND a.FilenameId = btemp.FilenameId +)"); + my $bconsole = $bvfs->get_bconsole(); + # TODO: pouvoir choisir le replace et le jobname + my $jobid = $bconsole->run(client => $arg->{client}, + storage => $arg->{storage}, + where => $arg->{where}, + regexwhere=> $arg->{regexwhere}, + restore => 1, + file => "?b2$$"); + + $bvfs->dbh_do("DROP TABLE b2$$"); + sleep(2); + print CGI::redirect("bweb.pl?action=dsp_cur_job;jobid=$jobid") ; + exit 0; +} + +print CGI::header('application/x-javascript'); + if ($action eq 'list_files') { print "["; my $files = $bvfs->ls_files(); @@ -816,7 +891,7 @@ if ($action eq 'list_files') { # File.FilenameId, listfiles.id, listfiles.Name, File.LStat, File.JobId print join(',', - map { "[$_->[1], $_->[0], $pathid, \"$_->[2]\", 10, \"2007-01-01 00:00:00\"]" } + map { "[$_->[1], $_->[0], $pathid, $_->[4], \"$_->[2]\", 10, \"2007-01-01 00:00:00\"]" } @$files); print "]\n"; @@ -827,7 +902,7 @@ if ($action eq 'list_files') { # return ($dirid,$dir_basename,$lstat,$jobid) print join(',', - map { "{ 'id': '$_->[0]', 'text': '$_->[1]', 'cls':'folder'}" } + map { "{ 'jobid': '$bvfs->{curjobids}', 'id': '$_->[0]', 'text': '$_->[1]', 'cls':'folder'}" } @$dirs); print "]\n"; @@ -856,7 +931,7 @@ if ($action eq 'list_files') { SELECT DISTINCT VolumeName, InChanger FROM File, ( -- Get all media from this job - SELECT MAX(FirstIndex) AS FirstIndex, MIN(LastIndex) AS LastIndex, + SELECT MIN(FirstIndex) AS FirstIndex, MAX(LastIndex) AS LastIndex, VolumeName, Inchanger FROM JobMedia JOIN Media USING (MediaId) WHERE JobId IN ($jobid) @@ -864,57 +939,13 @@ if ($action eq 'list_files') { ) AS allmedia WHERE File.FileId IN ($fileid) AND File.FileIndex >= allmedia.FirstIndex - AND File.FileIndex <= allmedia.LastIndex; + AND File.FileIndex <= allmedia.LastIndex "; my $lst = $bvfs->dbh_selectall_arrayref($q); print "["; print join(',', map { "[ '$_->[0]', $_->[1]]" } @$lst); print "]\n"; -} elsif ($action eq 'restore') { - my $fileid = join(',', grep { /^\d+$/ } CGI::param('fileid')); - my @dirid = grep { /^\d+$/ } CGI::param('dirid'); - my $inclause = join(',', @jobid); - - my @union; - - if ($fileid) { - push @union, "(SELECT JobId, FileIndex FROM File WHERE FileId IN ($fileid))"; - } - - # using this is not good because the sql engine doesn't know - # what LIKE will use. It will be better to get Path% in perl - # but it doesn't work with accents... :( - foreach my $dirid (@dirid) { - push @union, " - (SELECT File.JobId, File.FileIndex, File.FilenameId, File.PathId - FROM Path JOIN File USING (PathId) - WHERE Path.Path LIKE - (SELECT ". $bvfs->dbh_strcat('Path',"'\%'") ." FROM Path - WHERE PathId = $dirid - ) - AND File.JobId IN ($inclause))"; - } - - return unless scalar(@union); - - my $u = join(" UNION ", @union); - - $bvfs->dbh_do("CREATE TEMP TABLE btemp AS ($u)"); - # TODO: remove FilenameId et PathId - $bvfs->dbh_do("CREATE TABLE b2$$ AS ( -SELECT btemp.JobId, btemp.FileIndex, btemp.FilenameId, btemp.PathId - FROM btemp, - (SELECT max(JobId) as JobId, PathId, FilenameId - FROM btemp - GROUP BY PathId, FilenameId - ORDER BY JobId DESC) AS a - WHERE a.JobId = btemp.JobId - AND a.PathId= btemp.PathId - AND a.FilenameId = btemp.FilenameId -)"); - - print "restore file=?b2$$ done\n"; } __END__ diff --git a/gui/bweb/html/bresto.js b/gui/bweb/html/bresto.js index b4c2701a34..e2ff595a9d 100644 --- a/gui/bweb/html/bresto.js +++ b/gui/bweb/html/bresto.js @@ -49,12 +49,15 @@ Ext.namespace('Ext.brestore'); Ext.brestore.jobid=0; // selected jobid Ext.brestore.jobdate=''; // selected date Ext.brestore.client=''; // selected client +Ext.brestore.rclient=''; // selected client for resto +Ext.brestore.storage=''; // selected storage for resto Ext.brestore.path=''; // current path (without user location) Ext.brestore.root_path=''; // user location Ext.brestore.option_vosb = false; Ext.brestore.option_vafv = false; Ext.brestore.dlglaunch; +Ext.BLANK_IMAGE_URL = '/bweb/ext/resources/images/aero/s.gif'; // 1.1 function get_node_path(node) { @@ -109,6 +112,7 @@ function ext_init() id:'source' }); tree.setRootNode(root); + Ext.brestore.tree = root; // render the tree tree.render(); @@ -145,6 +149,7 @@ function ext_init() {name: 'fileid' }, {name: 'filenameid'}, {name: 'pathid' }, + {name: 'jobid' }, {name: 'name' }, {name: 'size', type: 'int' }, {name: 'mtime', type: 'date', dateFormat: 'Y-m-d h:i:s'} @@ -175,6 +180,9 @@ function ext_init() },{ dataIndex: 'fileid', hidden: true + },{ + dataIndex: 'jobid', + hidden: true } ]); @@ -251,13 +259,15 @@ function ext_init() width: 100 },{ dataIndex: 'pathid', - hidden: true + header: 'PathId' +// hidden: true },{ dataIndex: 'filenameid', hidden: true },{ dataIndex: 'fileid', - hidden: true + header: 'FileId' +// hidden: true } ]); @@ -295,13 +305,13 @@ function ext_init() if (data.grid.id == 'div-files') { for(var i=0;i $cmd yes\n"; + print STDERR "===> $cmd $go\n"; $self->{bconsole}->clear_accum(); - $self->send("$cmd yes\n"); + $self->send("$cmd $go\n"); $self->expect_it('-re',qr/^[*]/); my $ret = $self->before(); if ($ret =~ /jobid=(\d+)/is) { diff --git a/gui/bweb/script/bweb-mysql.sql b/gui/bweb/script/bweb-mysql.sql index 65a31806dd..601d569c48 100644 --- a/gui/bweb/script/bweb-mysql.sql +++ b/gui/bweb/script/bweb-mysql.sql @@ -1,3 +1,38 @@ +-- -------------------------------------------------- +-- Upgrade from 2.2 +-- -------------------------------------------------- + +-- New tables for bresto (same as brestore) + +CREATE TABLE brestore_knownjobid +( + JobId integer NOT NULL, + CONSTRAINT brestore_knownjobid_pkey PRIMARY KEY (JobId) +); + +CREATE TABLE brestore_pathhierarchy +( + PathId integer NOT NULL, + PPathId integer NOT NULL, + CONSTRAINT brestore_pathhierarchy_pkey PRIMARY KEY (PathId) +); + +CREATE INDEX brestore_pathhierarchy_ppathid + ON brestore_pathhierarchy (PPathId); + +CREATE TABLE brestore_pathvisibility +( + PathId integer NOT NULL, + JobId integer NOT NULL, + Size int8 DEFAULT 0, + Files int4 DEFAULT 0, + CONSTRAINT brestore_pathvisibility_pkey PRIMARY KEY (JobId, PathId) +); + +CREATE INDEX brestore_pathvisibility_jobid + ON brestore_pathvisibility (JobId); + + CREATE TABLE bweb_user ( userid serial not null, @@ -53,6 +88,10 @@ CREATE TABLE bweb_client_group_acl ); +-- -------------------------------------------------- +-- Upgrade from 2.0 +-- -------------------------------------------------- + -- Manage Client groups in bweb -- Works with postgresql and mysql5 diff --git a/gui/bweb/script/bweb-postgresql.sql b/gui/bweb/script/bweb-postgresql.sql index d02572f2f7..7bab62c00b 100644 --- a/gui/bweb/script/bweb-postgresql.sql +++ b/gui/bweb/script/bweb-postgresql.sql @@ -3,6 +3,40 @@ -- Upgrade from 2.2 -- -------------------------------------------------- + +-- New tables for bresto (same as brestore) + +CREATE TABLE brestore_knownjobid +( + JobId integer NOT NULL, + CONSTRAINT brestore_knownjobid_pkey PRIMARY KEY (JobId) +); + +CREATE TABLE brestore_pathhierarchy +( + PathId integer NOT NULL, + PPathId integer NOT NULL, + CONSTRAINT brestore_pathhierarchy_pkey PRIMARY KEY (PathId) +); + +CREATE INDEX brestore_pathhierarchy_ppathid + ON brestore_pathhierarchy (PPathId); + +CREATE TABLE brestore_pathvisibility +( + PathId integer NOT NULL, + JobId integer NOT NULL, + Size int8 DEFAULT 0, + Files int4 DEFAULT 0, + CONSTRAINT brestore_pathvisibility_pkey PRIMARY KEY (JobId, PathId) +); + +CREATE INDEX brestore_pathvisibility_jobid + ON brestore_pathvisibility (JobId); + + +-- New job log view + CREATE FUNCTION concat (text, text) RETURNS text AS ' DECLARE result text; diff --git a/gui/bweb/technotes-2.3 b/gui/bweb/technotes-2.3 index 91e3105399..e96d3bac45 100644 --- a/gui/bweb/technotes-2.3 +++ b/gui/bweb/technotes-2.3 @@ -1,2 +1,6 @@ 23Nov07 +ebl Add brestore_xxx tables to sql scripts +ebl Add a batch=1 option to bresto.pl to fill bresto tables +ebl Adapt Bconsole.pm to run a restore job +ebl Make bresto.html/js working (you can restore files now) ebl Improve run job from scheduled view and missing view -- 2.39.5