action = Request::post('action'); if ($this->action === 'backup') { User::assertPermission("create"); $this->backup(); } elseif ($this->action === 'restore') { User::assertPermission("restore"); $this->restore(); } elseif ($this->action === 'config') { User::assertPermission("config"); $this->config(); } User::assertPermission('*'); } protected function doRender() { if ($this->action === 'restore') { // TODO: We're in post mode, redirect with all the taskids first... Render::addTemplate('restore', $this->templateData); } elseif (($taskid = Request::get('errtaskid', false, 'string')) !== false) { Render::addTemplate('task-error', ['taskid' => $taskid]); } else { // Normal page $title = Property::get('page-title-prefix', ''); $bgcolor = Property::get('logo-background', ''); $lastBackup = (int)Property::get(BackupRestore::PROP_LAST_BACKUP, 0); if ($lastBackup === 0) { $lastBackup = false; } else { $lastBackup = date('d.m.Y', $lastBackup); } $params = [ 'id_color' => $bgcolor, 'id_prefix' => $title, 'last_backup' => $lastBackup, 'backup_' . Property::get(BackupRestore::PROP_AUTO_BACKUP_MODE, BackupRestore::BACKUP_MODE_OFF) . '_checked' => 'checked', 'autoBackupPw' => Property::get(BackupRestore::PROP_AUTO_BACKUP_PASS, ''), ]; Permission::addGlobalTags($params['perms'], NULL, ['create', 'restore', 'config']); Render::addTemplate('_page', $params); } } private function backup() { $password = trim(Request::post('passwd', '', 'string')); if (empty($password)) { $password = null; } EventLog::info('Creating backup on ' . Property::getServerIp()); $task = Taskmanager::submit('BackupRestore', [ 'mode' => 'backup', 'password' => $password, ]); if (!isset($task['id'])) { Message::addError('backup-failed'); Util::redirect('?do=Backup'); } $task = Taskmanager::waitComplete($task, 60000); if (!Taskmanager::isFinished($task) || !isset($task['data']['backupFile'])) { Util::redirect('?do=backup&errtaskid=' . $task['id']); } while ((@ob_get_level()) > 0) @ob_end_clean(); $fh = @fopen($task['data']['backupFile'], 'rb'); if ($fh === false) { Message::addError('main.error-read', $task['data']['backupFile']); Util::redirect('?do=Backup'); } $userFn = 'satellite-backup_' . Property::getServerIp() . '_' . date('Y.m.d-H.i.s') . '.tgz'; if ($password !== null) { $userFn .= '.aes'; } Header('Content-Type: application/octet-stream', true); Header('Content-Disposition: attachment; filename=' . $userFn); 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']); Property::set(BackupRestore::PROP_LAST_BACKUP, time()); 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'); } $password = trim(Request::post('passwd', '', 'string')); if (empty($password)) { $password = null; } $tempfile = '/tmp/bwlp-' . mt_rand(1, 100000) . '-' . crc32($_SERVER['REMOTE_ADDR']) . '.tgz'; if (!move_uploaded_file($_FILES['backupfile']['tmp_name'], $tempfile)) { Message::addError('main.error-write', $tempfile); Util::redirect('?do=Backup'); } copy($tempfile, $tempfile . '2'); // Check if correct password first etc. $task = Taskmanager::submit('BackupRestore', [ 'mode' => 'test', 'password' => $password, 'backupFile' => $tempfile . '2', ]); $task = Taskmanager::waitComplete($task, 5000); @unlink($tempfile . '2'); if (Taskmanager::isFailed($task)) { @unlink($tempfile); Util::redirect('?do=backup&errtaskid=' . $task['id']); } // 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']; } // Finally run restore $task = Taskmanager::submit('BackupRestore', [ 'mode' => 'restore', 'password' => $password, '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' => 6, '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 config() { $password = trim(Request::post('passwd', '', 'string')); if (empty($password)) { $password = null; } $mode = Request::post('auto-backup-mode', false, 'string'); if ($mode !== BackupRestore::BACKUP_MODE_OFF && $mode !== BackupRestore::BACKUP_MODE_ROOTHOME && $mode !== BackupRestore::BACKUP_MODE_VMSTORE) { Message::addError('invalid-auto-backup-mode', $mode); Util::redirect('?do=backup'); } Property::set(BackupRestore::PROP_AUTO_BACKUP_MODE, $mode); Property::set(BackupRestore::PROP_AUTO_BACKUP_PASS, $password); Util::redirect('?do=backup'); } }