]> git.sur5r.net Git - bacula/bacula/blob - gui/baculum/protected/Web/Pages/RestoreWizard.php
baculum: Use client name instead of clientid and start using fileset to prepare resto...
[bacula/bacula] / gui / baculum / protected / Web / Pages / RestoreWizard.php
1 <?php
2 /*
3  * Bacula(R) - The Network Backup Solution
4  * Baculum   - Bacula web interface
5  *
6  * Copyright (C) 2013-2017 Kern Sibbald
7  *
8  * The main author of Baculum is Marcin Haba.
9  * The original author of Bacula is Kern Sibbald, with contributions
10  * from many others, a complete list can be found in the file AUTHORS.
11  *
12  * You may use this file and others of this release according to the
13  * license defined in the LICENSE file, which includes the Affero General
14  * Public License, v3.0 ("AGPLv3") and some additional permissions and
15  * terms pursuant to its AGPLv3 Section 7.
16  *
17  * This notice must be preserved when any source code is
18  * conveyed and/or propagated.
19  *
20  * Bacula(R) is a registered trademark of Kern Sibbald.
21  */
22
23 Prado::using('Application.Web.Class.BaculumWebPage'); 
24 Prado::using('System.Exceptions.TException');
25 Prado::using('System.Web.UI.WebControls.TWizard');
26 Prado::using('System.Web.UI.ActiveControls.TActiveDropDownList');
27 Prado::using('System.Web.UI.ActiveControls.TActivePanel');
28 Prado::using('System.Web.UI.ActiveControls.TActiveLinkButton');
29 Prado::using('System.Web.UI.ActiveControls.TActiveImageButton');
30 Prado::using('System.Web.UI.ActiveControls.TDropContainer');
31 Prado::using('System.Web.UI.ActiveControls.TDraggable');
32 Prado::using('System.Web.UI.ActiveControls.TActiveRadioButton');
33 Prado::using('System.Web.UI.ActiveControls.TActiveDataGrid');
34 Prado::using('System.Web.UI.ActiveControls.TCallback');
35
36 class RestoreWizard extends BaculumWebPage
37 {
38         private $job_levels_to_restore = array('F' => 'Full', 'I' => 'Incremental', 'D'=> 'Differential');
39         private $jobs = null;
40         private $filesets = null;
41         private $storages = null;
42         private $clients = null;
43         private $browser_root_dir = array('name' => '.', 'type' => 'dir');
44         private $browser_up_dir = array('name' => '..', 'type' => 'dir');
45
46         public $excluded_elements_from_add = array('.', '..');
47
48         const BVFS_PATH_PREFIX = 'b2';
49
50         public function onPreInit($param) {
51                 parent::onPreInit($param);
52                 $this->Application->getModule('web_users')->loginUser();
53         }
54
55         public function onInit($param) {
56                 parent::onInit($param);
57                 if(!$this->IsPostBack && !$this->IsCallBack) {
58                         $this->setBrowserFiles(array());
59                         $this->setFileVersions(array());
60                         $this->setFilesToRestore(array());
61                         $this->markFileToRestore(null, null);
62                         $this->setRestoreJobs();
63                         $_SESSION['restore_path'] = array();
64                 }
65         }
66
67         public function onLoad($param) {
68                 parent::onLoad($param);
69                         if($this->RestoreWizard->ActiveStepIndex == 0) {
70                                 $this->jobs = $this->getModule('api')->get(array('jobs'))->output;
71                                 $this->filesets = $this->getModule('api')->get(array('filesets'))->output;
72                         }
73                         $this->clients = $this->getModule('api')->get(array('clients'))->output;
74
75                         if(!$this->IsCallBack && (($this->RestoreWizard->ActiveStepIndex == 1 && $this->getPage()->BackupToRestore->ItemCount > 0) || $this->RestoreWizard->ActiveStepIndex == 3)) {
76                                 $this->setFileVersions(array());
77                                 $this->setBrowserPath('');
78                                 $this->prepareFilesToRestore();
79                                 $this->prepareVersionsToRestore();
80                         }
81         }
82
83         public function addFileToRestore($sender, $param) {
84                 $fileid = null;
85                 if (isset($param->callbackParameter)) {
86                         list(, , , $sourceElementID, , ) = explode('_', $sender->ClientID, 6);
87                         $fileid = $param->callbackParameter;
88                 } else {
89                         $control = $param->getDroppedControl();
90                         $item = $control->getNamingContainer();
91                         list(, , , $sourceElementID, , ) = explode('_', $param->getDragElementID(), 6); // I know that it is ugly.
92                 }
93                 if($sourceElementID == $this->VersionsDataGrid->ID) {
94                         if (is_null($fileid)) {
95                                 $fileid = $this->VersionsDataGrid->getDataKeys()->itemAt($item->getItemIndex());
96                         }
97                         $fileProperties = $this->getFileVersions($fileid);
98                 } else {
99                         if (is_null($fileid)) {
100                                 $fileid = $this->DataGridFiles->getDataKeys()->itemAt($item->getItemIndex());
101                         }
102                         $fileProperties = $this->getBrowserFile($fileid);
103                 }
104                 if($fileProperties['name'] != $this->browser_root_dir['name'] && $fileProperties['name'] != $this->browser_up_dir['name']) {
105                         $this->markFileToRestore($fileid, $fileProperties);
106                         $this->prepareFilesToRestore();
107                 }
108         }
109
110         public function removeSelectedFile($sender, $param) {
111                 $fileid = $param->CallbackParameter;
112                 $this->unmarkFileToRestore($fileid);
113                 $this->prepareFilesToRestore();
114         }
115
116         public function getVersions($sender, $param) {
117                 list($filename, $pathid, $filenameid, $jobid) = explode('|', $param->CallbackParameter, 4);
118                 if($filenameid == 0) {
119                         $this->setBrowserPath($filename);
120                         return;
121                 }
122                 $clientname = $this->BackupClientName->SelectedValue;
123                 $versions = $this->getModule('api')->get(array('bvfs', 'versions', $clientname, $jobid, $pathid, $filenameid))->output;
124                 $fileVersions = $this->getModule('misc')->parseFileVersions($filename, $versions);
125                 $this->setFileVersions($fileVersions);
126                 $this->VersionsDataGrid->dataSource = $fileVersions;
127                 $this->VersionsDataGrid->dataBind();
128                 $this->prepareFilesToRestore();
129         }
130
131         public function refreshSelectedFiles($sender, $param) {
132                 $this->prepareFilesToRestore();
133                 $this->SelectedVersionsDropper->render($param->NewWriter);
134         }
135
136         public function NextStep($sender, $param) {
137         }
138         
139         public function PreviousStep($sender, $param) {
140         }
141
142         public function wizardStop($sender, $param) {
143                 $this->goToDefaultPage();
144         }
145
146         public function setJobs($sender, $param) {
147                 $jobs_list = $jobs_group_list = array();
148                 $clientid = null;
149                 for ($i = 0; $i < count($this->clients); $i++) {
150                         if ($this->clients[$i]->name === $this->BackupClientName->SelectedValue) {
151                                 $clientid = $this->clients[$i]->clientid;
152                                 break;
153                         }
154                 }
155                 if(is_array($this->jobs)) {
156                         foreach($this->jobs as $job) {
157                                 if(array_key_exists($job->level, $this->job_levels_to_restore) && $job->type == 'B' && $job->jobstatus == 'T' && $job->clientid == $clientid) {
158                                         $jobs_list[$job->jobid] = sprintf('[%s] %s, %s, %s', $job->jobid, $job->name, $this->job_levels_to_restore[$job->level], $job->endtime);
159                                         $jobs_group_list[$job->name] = $job->name;
160                                 }
161                         }
162                 }
163
164                 $fileset_list = array();
165                 foreach($this->filesets as $director => $filesets) {
166                         $fileset_list = array_merge($fileset_list, $filesets);
167                 }
168
169                 $this->BackupToRestore->dataSource = $jobs_list;
170                 $this->BackupToRestore->dataBind();
171                 $this->GroupBackupToRestore->dataSource = $jobs_group_list;
172                 $this->GroupBackupToRestore->dataBind();
173                 $this->GroupBackupFileSet->dataSource = array_combine($fileset_list, $fileset_list);
174                 $this->GroupBackupFileSet->dataBind();
175                 $this->setRestoreClients($sender, $param);
176         }
177
178         public function setBackupClients($sender, $param) {
179                 if(!$this->IsPostBack) {
180                         $client_list = array();
181                         foreach($this->clients as $client) {
182                                 $client_list[$client->name] = $client->name;
183                         }
184                         $this->BackupClientName->dataSource = $client_list;
185                         $this->BackupClientName->dataBind();
186                 }
187         }
188
189         public function setRestoreClients($sender, $param) {
190                 if(!$this->IsPostBack || $sender->ID == $this->BackupClientName->ID) {
191                         $client_list = array();
192                         foreach($this->clients as $client) {
193                                 $client_list[$client->name] = $client->name;
194                         }
195                         $this->RestoreClient->SelectedValue = $this->BackupClientName->SelectedValue;
196                         $this->RestoreClient->dataSource = $client_list;
197                         $this->RestoreClient->dataBind();
198                 }
199         }
200
201         public function setStorage($sender, $param) {
202                 if(!$this->IsPostBack) {
203                         $storagesList = array();
204                         $storages = $this->getModule('api')->get(array('storages'))->output;
205                         foreach($storages as $storage) {
206                                 $storagesList[$storage->storageid] = $storage->name;
207                         }
208                         $this->GroupBackupStorage->dataSource = $storagesList;
209                         $this->GroupBackupStorage->dataBind();
210                 }
211         }
212
213         public function setPool($sender, $param) {
214                 if(!$this->IsPostBack) {
215                         $poolsList = array();
216                         $pools = $this->getModule('api')->get(array('pools'))->output;
217                         foreach($pools as $pool) {
218                                 $poolsList[$pool->poolid] = $pool->name;
219                         }
220                         $this->GroupBackupPool->dataSource = $poolsList;
221                         $this->GroupBackupPool->dataBind();
222                 }
223         }
224
225         public function setBackupClient($sender, $param) {
226                 $this->ClientToRestore->SelectedValue = $param->SelectedValue;
227         } 
228
229         public function setBackupSelection($sender, $param) {
230                 $this->GroupBackupToRestoreField->Display = ($sender->ID == $this->GroupBackupSelection->ID) ? 'Dynamic' : 'None';
231                 $this->BackupToRestoreField->Display = ($sender->ID == $this->OnlySelectedBackupSelection->ID) ? 'Dynamic' : 'None';
232                 $this->setBrowserFiles(array());
233                 $this->setFileVersions(array());
234                 $this->setFilesToRestore(array());
235                 $this->markFileToRestore(null, null);
236                 $_SESSION['restore_path'] = array();
237         }
238
239         public function resetFileBrowser($sender, $param) {
240                 $this->markFileToRestore(null, null);
241                 $this->setBrowserPath($this->browser_root_dir['name']);
242         }
243
244         private function prepareBrowserFiles($files) {
245                 $this->setBrowserFiles($files);
246                 $this->DataGridFiles->dataSource = $files;
247                 @$this->DataGridFiles->dataBind();
248         }
249
250         private function prepareVersionsToRestore() {
251                 $this->VersionsDataGrid->dataSource = $_SESSION['files_versions'];
252                 $this->VersionsDataGrid->dataBind();
253         }
254
255         private function prepareFilesToRestore() {
256                 $this->SelectedVersionsDataGrid->dataSource = $_SESSION['restore'];
257                 $this->SelectedVersionsDataGrid->dataBind();
258         }
259
260         private function setBrowserPath($path) {
261                 if(!empty($path)) {
262                         if($path == $this->browser_up_dir['name']) {
263                                 array_pop($_SESSION['restore_path']);
264                         } elseif($path == $this->browser_root_dir['name']) {
265                                 $_SESSION['restore_path'] = array();
266                         } else {
267                                 array_push($_SESSION['restore_path'], $path);
268                         }
269                 }
270                 $this->setBrowserLocalizator();
271                 $this->prepareBrowserContent();
272         }
273
274         private function getBrowserPath($stringFormat = false) {
275                 return ($stringFormat === true) ? implode($_SESSION['restore_path']) : $_SESSION['restore_path'];
276         }
277
278         private function setBrowserLocalizator() {
279                 $localization = $this->getBrowserPath(true);
280                 $this->PathField->HeaderText = mb_strlen($localization) > 56 ? '...' . mb_substr($localization, -56) : $localization;
281         }
282
283         private function prepareBrowserContent() {
284                 $jobids = $this->getElementaryBackup();
285                 $elements = array();
286                 if (!is_null($jobids)) {
287                         // generating Bvfs may takes a moment
288                         $this->generateBvfsCacheByJobids($jobids);
289                         $bvfs_dirs_list = $this->getModule('api')->set(array('bvfs', 'lsdirs'), array('jobids' => $jobids, 'path' => $this->getBrowserPath(true)));
290                         $bvfs_dirs = is_object($bvfs_dirs_list) ? $bvfs_dirs_list->output : array();
291                         $dirs = $this->getModule('misc')->parseBvfsList($bvfs_dirs);
292                         $bvfs_files_list = $this->getModule('api')->set(array('bvfs', 'lsfiles'), array('jobids' => $jobids, 'path' => $this->getBrowserPath(true)));
293                         $bvfs_files = is_object($bvfs_files_list) ? $bvfs_files_list->output : array();
294                         $files = $this->getModule('misc')->parseBvfsList($bvfs_files);
295                         $elements = array_merge($dirs, $files);
296                         if(count($this->getBrowserPath()) > 0) {
297                                 array_unshift($elements, $this->browser_root_dir);
298                         }
299                 }
300                 $this->prepareBrowserFiles($elements);
301         }
302
303         private function getElementaryBackup() {
304                 $jobids = null;
305                 if($this->OnlySelectedBackupSelection->Checked === true) {
306                         $jobs = $this->getModule('api')->get(array('bvfs', 'getjobids', $this->BackupToRestore->SelectedValue));
307                         $ids = is_object($jobs) ? $jobs->output : array();
308                         foreach($ids as $jobid) {
309                                 if(preg_match('/^([\d\,]+)$/', $jobid, $match) == 1) {
310                                         $jobids = $match[1];
311                                         break;
312                                 }
313                         }
314                 } else {
315                         $params = array(
316                                 'jobs',
317                                 'recent',
318                                 $this->GroupBackupToRestore->SelectedValue,
319                                 'client',
320                                 $this->BackupClientName->SelectedValue,
321                                 'fileset',
322                                 $this->GroupBackupFileSet->SelectedValue
323                         );
324                         $jobs_recent = $this->getModule('api')->get($params);
325                         if(count($jobs_recent->output) > 0) {
326                                 $ids = $jobs_recent->output;
327                                 $jobids = implode(',', $ids);
328                         }
329                 }
330                 return $jobids;
331         }
332
333         private function generateBvfsCacheByJobids($jobids) {
334                 $this->getModule('api')->set(array('bvfs', 'update'), array('jobids' => $jobids));
335         }
336
337         private function setFileVersions($versions) {
338                 $_SESSION['files_versions'] = $versions;
339         }
340
341         private function getFileVersions($fileid) {
342                 $versions = array();
343                 foreach($_SESSION['files_versions'] as $file) {
344                         if(array_key_exists('fileid', $file) && $file['fileid'] == $fileid) {
345                                 $versions = $file;
346                                 break;
347                         }
348                 }
349                 return $versions;
350         }
351
352         private function setBrowserFiles($files) {
353                 $_SESSION['files_browser'] = $files;
354         }
355
356         private function getBrowserFile($fileid) {
357                 $element = array();
358                 foreach($_SESSION['files_browser'] as $file) {
359                         if(array_key_exists('fileid', $file) && $file['fileid'] == $fileid) {
360                                 $element = $file;
361                                 break;
362                         }
363                 }
364                 return $element;
365         }
366
367         private function markFileToRestore($fileid, $file) {
368                 if($fileid === null) {
369                         $_SESSION['restore'] = array();
370                 } elseif($file['name'] != $this->browser_root_dir['name'] && $file['name'] != $this->browser_up_dir['name']) {
371                         $_SESSION['restore'][$fileid] = $file;
372                 }
373         }
374
375         private function unmarkFileToRestore($fileid) {
376                 if(array_key_exists($fileid, $_SESSION['restore'])) {
377                         unset($_SESSION['restore'][$fileid]);
378                 }
379         }
380
381         public function getFilesToRestore() {
382                 return $_SESSION['restore'];
383         }
384
385         public function setFilesToRestore($files) {
386                 $_SESSION['restore'] = $files;
387         }
388
389         public function getRestoreElements($asObject = false) {
390                 $fileids = array();
391                 $dirids = array();
392                 foreach($this->getFilesToRestore() as $fileid => $properties) {
393                         if($properties['type'] == 'dir') {
394                                 $dirids[] = $properties['pathid'];
395                         } elseif($properties['type'] == 'file') {
396                                 $fileids[] = $fileid;
397                         }
398                 }
399                 $ret = array('fileid' => $fileids, 'dirid' => $dirids);
400                 if($asObject === true) {
401                         $ret = (object)$ret;
402                 }
403                 return $ret;
404         }
405
406         public function wizardCompleted() {
407                 $jobids = $this->getElementaryBackup();
408                 $path = self::BVFS_PATH_PREFIX . getmypid();
409                 $restore_elements = $this->getRestoreElements();
410                 $cmd_props = array('jobids' => $jobids, 'path' => $path);
411                 if(count($restore_elements['fileid']) > 0) {
412                         $cmd_props['fileid'] = implode(',', $restore_elements['fileid']);
413                 }
414                 if(count($restore_elements['dirid']) > 0) {
415                         $cmd_props['dirid'] = implode(',', $restore_elements['dirid']);
416                 }
417
418                 $this->getModule('api')->create(array('bvfs', 'restore'), $cmd_props);
419                 $restore_props = array();
420                 $restore_props['rpath'] = $path;
421                 $restore_props['client'] = $this->RestoreClient->SelectedValue;
422                 $restore_props['priority'] = intval($this->RestoreJobPriority->Text);
423                 $restore_props['where'] =  $this->RestorePath->Text;
424                 $restore_props['replace'] = $this->ReplaceFiles->SelectedValue;
425                 $restore_props['restorejob'] = $this->RestoreJob->SelectedValue;
426                 
427                 $ret = $this->getModule('api')->create(array('jobs', 'restore'), $restore_props);
428                 $jobid = $this->getModule('misc')->findJobIdStartedJob($ret->output);
429                 $url_params = array('open' => 'Job');
430                 if (is_numeric($jobid)) {
431                         $url_params['id'] = $jobid;
432                 }
433                 $this->goToDefaultPage($url_params);
434         }
435
436         private function setRestoreJobs() {
437                 $restore_job_tasks = $this->Application->getModule('api')->get(array('jobs', 'tasks', 'type', 'R'))->output;
438                 $jobs = array();
439                 foreach ($restore_job_tasks as $director => $restore_jobs) {
440                         $jobs = array_merge($jobs, $restore_jobs);
441                 }
442                 $this->RestoreJob->DataSource = array_combine($jobs, $jobs);
443                 $this->RestoreJob->dataBind();
444         }
445 }
446 ?>