D47 / R-1269 (P2): a new install never writes into an earlier install's backup — every install has an identity (install_id), the unit records it, every unit writer asks first; another install's unit is set aside whole (backups/set-aside/<app>/<stamp>, a D25 kept copy, „Visszaállítás” + „Eltávolítás” on the restore page); a move that fails refuses the write. Red-proved. Commit only.
gates / gates (push) Successful in 1m33s

This commit is contained in:
2026-10-25 09:27:48 +01:00
parent e1613aea8d
commit 02daebe9c5
30 changed files with 1990 additions and 17 deletions
+21
View File
@@ -663,6 +663,13 @@ func (m *Manager) runDBDumpsInternal(ctx context.Context) error {
continue
}
// D47 (R-1269): never a dump into another install's unit — it is set aside whole first, or nothing is written.
if gErr := m.guardUnitWrite(db.StackName, m.namespaceRoot(drivePath), "database dump"); gErr != nil {
allOK = false
summary = append(summary, fmt.Sprintf("FAIL %s: %v", db.ContainerName, gErr))
m.noteFailure(db.StackName, "database dump", gErr.Error())
continue
}
dumpDir := AppDBDumpPath(m.namespaceRoot(drivePath), db.StackName)
result := m.dumpOneOrDefault(ctx, db, dumpDir)
@@ -870,6 +877,9 @@ func (m *Manager) DumpAppVolumes(stackName string) error {
return fmt.Errorf("cannot determine drive path for %s", stackName)
}
if err := m.guardUnitWrite(stackName, m.namespaceRoot(drivePath), "volume dump"); err != nil { // D47 (R-1269)
return err
}
dumpDir := AppVolumeDumpPath(m.namespaceRoot(drivePath), stackName)
if err := os.MkdirAll(dumpDir, 0755); err != nil {
return fmt.Errorf("creating volume dump dir: %w", err)
@@ -1142,6 +1152,9 @@ func (m *Manager) DumpStackDB(ctx context.Context, stackName string) error {
if drivePath == "" || !filepath.IsAbs(drivePath) {
return fmt.Errorf("cannot determine absolute drive path for %s (systemDataPath not configured?)", stackName)
}
if err := m.guardUnitWrite(stackName, m.namespaceRoot(drivePath), "pre-backup database dump"); err != nil { // D47
return err
}
dumpDir := AppDBDumpPath(m.namespaceRoot(drivePath), stackName)
m.logger.Printf("[INFO] [backup] Running pre-backup DB dump for %s (%d database(s)) → %s", stackName, len(stackDBs), dumpDir)
@@ -1570,6 +1583,14 @@ func (m *Manager) pruneStalePrimaryDirs() {
filepath.Clean(primaryDir)+string(filepath.Separator)) {
continue
}
// D47: a unit of ANOTHER install on the old drive is not this app's moved unit — it is set aside whole
// (never deleted); a guard that cannot decide leaves it as it is.
if gErr := m.guardUnitDir(app, stalePath, nsRoot, "stale-drive prune"); gErr != nil {
continue
}
if _, sErr := os.Stat(stalePath); os.IsNotExist(sErr) {
continue // set aside just now
}
if err := os.RemoveAll(stalePath); err != nil {
m.logger.Printf("[WARN] [backup] F5: could not remove stale primary dir for %s on old drive: %v", app, err)
} else {