D48: a restore downloads first — every restore path resolves and pulls every image of the definition that will run before the stop, under the image-work lock held until the restore returns; a failed pull refuses with the app untouched (a deleted version and a busy registry read differently), one operator line. Red-proved. Commit only.
gates / gates (push) Successful in 1m26s

This commit is contained in:
admin committed 2026-10-25 09:38:28 +01:00
1 parent b680db85cb
commit 2d71270858
16 files changed
+404 -3

No files matched your search

@@ -12,6 +12,7 @@ import (
"syscall"
"time"
"gitea.dooplex.hu/admin/felhom-controller/internal/dockerexec"
"gitea.dooplex.hu/admin/felhom-controller/internal/util"
)
@@ -307,6 +308,8 @@ func (m *Manager) RestoreTier2Whole(stackName string) (WholeRestoreResult, error
// R-1178: the unit half's refusals are asked HERE, before the file half — measured before: files merged, then the
// unit refused (a cut-off database copy) and the app was left STOPPED under a page that said „untouched".
unitDir := tier2UnitDir(destBase)
// D48: the images the unit half pulls in its check stay on the box through the file half and the unit half.
defer dockerexec.HoldImageWork()()
if _, err := m.RestoreFromRecoveryUnitAtWith(stackName, unitDir, UnitRestoreOptions{AcceptMissingFiles: true, CheckOnly: true}); err != nil {
m.logger.Printf("[WARN] [backup] whole restore REFUSED for %s before the file half: the unit half would refuse (%v) — nothing moved", stackName, err)
return res, err