diff options
author | Jonathan Bauer | 2016-04-01 16:50:13 +0200 |
---|---|---|
committer | Jonathan Bauer | 2016-04-01 16:50:13 +0200 |
commit | dbc0d9614421e064cc62aacf116ebb783c83f2f3 (patch) | |
tree | 091844b8578ff1d9ac18edfd3cee3e63210133d7 /modules/backup | |
parent | [ldapauth] Add homedir conf to ldap wizard (diff) | |
download | slx-admin-dbc0d9614421e064cc62aacf116ebb783c83f2f3.tar.gz slx-admin-dbc0d9614421e064cc62aacf116ebb783c83f2f3.tar.xz slx-admin-dbc0d9614421e064cc62aacf116ebb783c83f2f3.zip |
[merge] merging c3sl / fr - initial commit
Diffstat (limited to 'modules/backup')
-rw-r--r-- | modules/backup/config.json | 4 | ||||
-rw-r--r-- | modules/backup/module.inc.php | 164 | ||||
-rw-r--r-- | modules/backup/templates/_page.html | 41 | ||||
-rw-r--r-- | modules/backup/templates/restore.html | 62 |
4 files changed, 271 insertions, 0 deletions
diff --git a/modules/backup/config.json b/modules/backup/config.json new file mode 100644 index 00000000..4e7fa5fb --- /dev/null +++ b/modules/backup/config.json @@ -0,0 +1,4 @@ +{ + "category":"content", + "enabled":"true" +} diff --git a/modules/backup/module.inc.php b/modules/backup/module.inc.php new file mode 100644 index 00000000..4095f875 --- /dev/null +++ b/modules/backup/module.inc.php @@ -0,0 +1,164 @@ +<?php + +class Page_Backup extends Page +{ + + private $action = false; + private $templateData = array(); + + protected function doPreprocess() + { + User::load(); + if (!User::hasPermission('superadmin')) { + Message::addError('no-permission'); + Util::redirect('?do=Main'); + } + $this->action = Request::post('action'); + if ($this->action === 'backup') { + $this->backup(); + } elseif ($this->action === 'restore') { + $this->restore(); + } + } + + protected function doRender() + { + Render::setTitle(Dictionary::translate('lang_titleBackup')); + if ($this->action === 'restore') { + Render::addTemplate('restore', $this->templateData); + } else { + Render::addScriptBottom('fileselect'); + Render::addTemplate('_page'); + } + } + + private function backup() + { + $task = Taskmanager::submit('BackupRestore', array('mode' => 'backup')); + if (!isset($task['id'])) { + Message::addError('backup-failed'); + Util::redirect('?do=Backup'); + } + $task = Taskmanager::waitComplete($task, 30000); + if (!Taskmanager::isFinished($task) || !isset($task['data']['backupFile'])) { + Taskmanager::addErrorMessage($task); + Util::redirect('?do=Backup'); + } + while ((@ob_get_level()) > 0) + @ob_end_clean(); + $fh = @fopen($task['data']['backupFile'], 'rb'); + if ($fh === false) { + Message::addError('error-read', $task['data']['backupFile']); + Util::redirect('?do=Backup'); + } + Header('Content-Type: application/octet-stream', true); + Header('Content-Disposition: attachment; filename=' . 'satellite-backup_v' . Database::getExpectedSchemaVersion() . '_' . date('Y.m.d-H.i.s') . '.tgz'); + Header('Content-Length: ' . @filesize($task['data']['backupFile'])); + while (!feof($fh)) { + $data = fread($fh, 16000); + if ($data === false) { + EventLog::failure('Could not stream system backup to browser - backup corrupted!'); + die("\r\n\nDOWNLOAD INTERRUPTED!\n"); + } + echo $data; + @ob_flush(); + @flush(); + } + @fclose($fh); + @unlink($task['data']['backupFile']); + die(); + } + + private function restore() + { + if (!isset($_FILES['backupfile'])) { + Message::addError('missing-file'); + Util::redirect('?do=Backup'); + } + if ($_FILES['backupfile']['error'] != UPLOAD_ERR_OK) { + Message::addError('upload-failed', Util::uploadErrorString($_FILES['backupfile']['error'])); + Util::redirect('?do=Backup'); + } + $tempfile = '/tmp/bwlp-' . mt_rand(1, 100000) . '-' . crc32($_SERVER['REMOTE_ADDR']) . '.tgz'; + if (!move_uploaded_file($_FILES['backupfile']['tmp_name'], $tempfile)) { + Message::addError('error-write', $tempfile); + Util::redirect('?do=Backup'); + } + // Got uploaded file, now shut down all the daemons etc. + $parent = Trigger::stopDaemons(null, $this->templateData); + // Unmount store + $task = Taskmanager::submit('MountVmStore', array( + 'address' => 'null', + 'type' => 'images', + 'parentTask' => $parent, + 'failOnParentFail' => false + )); + if (isset($task['id'])) { + $this->templateData['mountid'] = $task['id']; + $parent = $task['id']; + } + EventLog::info('Creating backup, v' . Database::getExpectedSchemaVersion() . ' on ' . Property::getServerIp()); + // Finally run restore + $task = Taskmanager::submit('BackupRestore', array( + 'mode' => 'restore', + 'backupFile' => $tempfile, + 'parentTask' => $parent, + 'failOnParentFail' => false, + 'restoreOpenslx' => Request::post('restore_openslx', 'off') === 'on', + 'restoreDozmod' => Request::post('restore_dozmod', 'off') === 'on', + )); + if (isset($task['id'])) { + $this->templateData['restoreid'] = $task['id']; + $parent = $task['id']; + TaskmanagerCallback::addCallback($task, 'dbRestored'); + } + // Wait a bit + $task = Taskmanager::submit('SleepTask', array( + 'seconds' => 3, + 'parentTask' => $parent, + 'failOnParentFail' => false + )); + if (isset($task['id'])) + $parent = $task['id']; + // Reboot + $task = Taskmanager::submit('Reboot', array( + 'parentTask' => $parent, + 'failOnParentFail' => false + )); + // Leave this comment so the i18n scanner finds it: + // Message::addSuccess('restore-done'); + if (isset($task['id'])) + $this->templateData['rebootid'] = $task['id']; + } + private function stopDaemons($parent) + { + $task = Taskmanager::submit('SyncdaemonLauncher', array( + 'operation' => 'stop', + 'parentTask' => $parent, + 'failOnParentFail' => false + )); + if (isset($task['id'])) { + $this->templateData['syncid'] = $task['id']; + $parent = $task['id']; + } + $task = Taskmanager::submit('DozmodLauncher', array( + 'operation' => 'stop', + 'parentTask' => $parent, + 'failOnParentFail' => false + )); + if (isset($task['id'])) { + $this->templateData['dmsdid'] = $task['id']; + $parent = $task['id']; + } + $task = Taskmanager::submit('LdadpLauncher', array( + 'ids' => array(), + 'parentTask' => $parent, + 'failOnParentFail' => false + )); + if (isset($task['id'])) { + $this->templateData['ldadpid'] = $task['id']; + $parent = $task['id']; + } + return $parent; + } +} diff --git a/modules/backup/templates/_page.html b/modules/backup/templates/_page.html new file mode 100644 index 00000000..47b5a174 --- /dev/null +++ b/modules/backup/templates/_page.html @@ -0,0 +1,41 @@ +<h1>{{lang_backupRestore}}</h1> + +<form action="?do=Backup" method="post"> + <input type="hidden" name="token" value="{{token}}"> + <input type="hidden" name="action" value="backup"> + <div class="panel panel-default"> + <div class="panel-heading">{{lang_backup}}</div> + <div class="panel-body"> + <p>{{lang_backupDescription}}</p> + <button class="btn btn-primary" type="submit">{{lang_download}}</button> + </div> + </div> +</form> + +<form action="?do=Backup" method="post" enctype="multipart/form-data"> + <input type="hidden" name="token" value="{{token}}"> + <input type="hidden" name="action" value="restore"> + <div class="panel panel-default"> + <div class="panel-heading">{{lang_restore}}</div> + <div class="panel-body"> + <p>{{lang_restoreDescription}}</p> + <div class="input-group upload-ex"> + <input type="text" class="form-control" readonly placeholder="{{lang_selectFile}}"> + <span class="input-group-btn"> + <span class="btn btn-default btn-file"> + {{lang_browseForFile}}… <input type="file" name="backupfile"> + </span> + </span> + </div> + <div> + <label><input type="checkbox" name="restore_openslx" checked="checked"> {{lang_restoreSystemConfig}}</label> + <p><i>{{lang_systemExplanation}}</i></p> + </div> + <div> + <label><input type="checkbox" name="restore_dozmod" checked="checked"> {{lang_restoreDozmodConfig}}</label> + <p><i>{{lang_dozmodExplanation}}</i></p> + </div> + <button class="btn btn-primary" type="submit">{{lang_restore}}</button> + </div> + </div> +</form>
\ No newline at end of file diff --git a/modules/backup/templates/restore.html b/modules/backup/templates/restore.html new file mode 100644 index 00000000..4494a993 --- /dev/null +++ b/modules/backup/templates/restore.html @@ -0,0 +1,62 @@ +<div class="panel panel-default"> + <div class="panel-heading">{{lang_backup}}</div> + <div class="panel-body"> + <div id="zeug"> + <div data-tm-id="{{syncid}}" data-tm-log="messages">{{lang_stopping}} syncdaemon</div> + <div data-tm-id="{{dmsdid}}" data-tm-log="messages">{{lang_stopping}} dmsd</div> + <div data-tm-id="{{ldadpid}}" data-tm-log="messages">{{lang_stopping}} ldadp</div> + <div data-tm-id="{{mountid}}" data-tm-log="messages">{{lang_stopping}} vmstore</div> + <div data-tm-id="{{restoreid}}" data-tm-log="messages" data-tm-callback="restoreCb">{{lang_restoreConfig}}</div> + <div data-tm-id="{{rebootid}}" data-tm-log="messages">{{lang_reboot}}</div> + </div> + <div id="restorefailed" class="alert alert-danger" style="display:none"> + {{lang_restoreFailed}} + </div> + <div id="waiting" style="display:none"> + <span id="dots"></span> + </div> + </div> +</div> + +<script type="text/javascript"> + function restoreCb(task) + { + if (!task || !task.statusCode) + return; + if (task.statusCode === 'TASK_ERROR') { + $('#restorefailed').show('slow'); + } + if (task.statusCode === 'TASK_ERROR' || task.statusCode === 'TASK_FINISHED') { + startRebootPoll(); + } + } + + function startRebootPoll() + { + $('#waiting').show(); + $('#waiting').prepend('<span class="glyphicon glyphicon-refresh slx-rotation"></span>'); + $('#dots').text('{{lang_waitReboot}}'); + slxDotInterval = setInterval(function() { $('#dots').text($('#dots').text() + '..'); }, 3000); + setTimeout('rebootPoll()', 10000); + } + + function rebootPoll() + { + if (slxDotInterval !== false) { + clearInterval(slxDotInterval); + slxDotInterval = false; + } + $('#dots').text($('#dots').text() + '..'); + slxTimeoutId = setTimeout('rebootPoll()', 3500); + $.ajax({url: "index.php?do=Main", timeout: 3000}).success(function(data, textStatus, jqXHR) { + if (textStatus !== "success" && textStatus !== "notmodified") + return; + if (data.indexOf('Status: DB running') === -1) + return; + clearTimeout(slxTimeoutId); + setTimeout(function() { + window.location.replace("index.php?do=Main&message[]=success%7Crestore-done"); + }, 3500); + }); + } +</script> |