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