Full restore: maintenance mode on before the checks (off again when they refuse); the printed retry command is complete

This commit is contained in:
2026-10-22 00:53:08 +02:00
parent 7ed53ad0eb
commit 61e2a28b67
3 changed files with 24 additions and 7 deletions
+4 -1
View File
@@ -95,7 +95,10 @@ HELP);
if (\OCP\Server::get(\OCP\IConfig::class)->getSystemValueBool('maintenance', false)) {
$output->writeln('The restore had started: the instance may be partly restored, and maintenance mode stays on so that nobody uses it like that.');
$output->writeln('Fix the cause, then switch maintenance mode off and run the same command again with --force, in one line:');
$output->writeln(' occ maintenance:mode --off && occ backup:restore:full ' . (string)$input->getArgument('target') . ' ' . (string)$input->getArgument('snapshot') . ' --force ...');
$again = 'occ backup:restore:full ' . escapeshellarg((string)$input->getArgument('target')) . ' ' . escapeshellarg((string)$input->getArgument('snapshot'))
. ($input->getOption('skip-missing-tables') ? ' --skip-missing-tables' : '') . ' --force --no-interaction';
$output->writeln(' occ maintenance:mode --off && ' . $again);
$output->writeln('(Without --install-apps: the apps are installed already, and the instance is open again only for the seconds until the restore starts.)');
} else {
$output->writeln('If this happened after the restore had started, the instance may be partly restored: fix the cause and run the same command again with --force.');
}
+16 -4
View File
@@ -89,10 +89,6 @@ final class RestoreFullService {
/** @return array{dbReport:array, dataFiles:int, configKeys:int, dbConsistent:bool, missingApps:list<string>, maintenanceLeftOn:bool} */
public function restoreFull(Target $target, string $snapshotId, bool $skipMissingTables = false): array {
$check = $this->checkCompatibility($target, $snapshotId, $skipMissingTables);
if (!$check['ok']) {
throw new \RuntimeException($this->describeBlockers($check));
}
// Maintenance mode for the whole restore: background jobs (cron.php stops in maintenance
// mode), page visits (AJAX cron) and users must not write into tables or the data
// directory while they are being replaced; a row written in between would collide with a
@@ -100,8 +96,24 @@ final class RestoreFullService {
// error it stays on: the instance may be partly restored, and must not be used like that.
// occ only offers app commands outside maintenance mode, so the admin switches it off
// right before running the restore again (see RestoreFull). Already on before: left on.
// On before the checks below, so that a run again after an error leaves the partly
// restored instance open for seconds at most; off again when they refuse (nothing changed).
$wasInMaintenance = $this->config->getSystemValueBool('maintenance', false);
$this->config->setSystemValue('maintenance', true);
try {
$check = $this->checkCompatibility($target, $snapshotId, $skipMissingTables);
} catch (\Throwable $e) {
if (!$wasInMaintenance) {
$this->config->setSystemValue('maintenance', false);
}
throw $e;
}
if (!$check['ok']) {
if (!$wasInMaintenance) {
$this->config->setSystemValue('maintenance', false);
}
throw new \RuntimeException($this->describeBlockers($check));
}
$result = $this->restoreInMaintenance($target, $snapshotId, $skipMissingTables, $check);
if (!$wasInMaintenance) {
$this->config->setSystemValue('maintenance', false);