v0.51.0: offsite-backup UI (felhom-pbs DR) + Model-A double-nest fix
- Backups page: whole-guest backup shown as real DR — target label "Biztonsági szerver – külön hardver (PBS)"; app-data "Távoli mentés" card now reflects the PBS offsite tier (guestBackupView.Offsite) instead of "nincs beállítva". - Model-A double-nest fix: appbackup path helpers take a felhom-data NAMESPACE ROOT (no internal felhom-data join); backup.Manager.namespaceRoot/AppNamespaceRoot resolve HDD-vs-systemDataPath provenance so a drive-resident app's backups land single-nested (<drive>/backups/... on the guest = <drive>/felhom-data/backups/... on the host) instead of .../felhom-data/felhom-data/.... Writes, deletion (GetStackBackupData/RemoveStack/ ProtectedHDDPaths), wipe-warning scan, and export updated coherently; legacy double-nest dirs kept protected. New appbackup test asserts no doubled segment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -93,6 +93,26 @@ func (m *Manager) GetAppDrivePath(stackName string) string {
|
||||
return m.systemDataPath
|
||||
}
|
||||
|
||||
// namespaceRoot maps an app's drive path to its felhom-data namespace ROOT (the dir that directly
|
||||
// holds backups/ and appdata/). A drive-resident app's in-guest mount IS the namespace already
|
||||
// (Model A, slice 10 — the agent binds <drive>/felhom-data onto the guest mountpoint), so it is used
|
||||
// as-is; only the SSD-only system-data fallback gets the felhom-data subdir appended. This is what
|
||||
// keeps a drive-resident app's backups single-nested instead of .../felhom-data/felhom-data/... .
|
||||
func (m *Manager) namespaceRoot(drivePath string) string {
|
||||
return NamespaceRoot(drivePath, drivePath != m.systemDataPath)
|
||||
}
|
||||
|
||||
// AppNamespaceRoot returns the felhom-data namespace root for a stack's keep-side backups, resolving
|
||||
// HDD-vs-system provenance internally. For callers outside this package that only know the stack
|
||||
// name (e.g. the API router) so they don't double-nest the felhom-data segment.
|
||||
func (m *Manager) AppNamespaceRoot(stackName string) string {
|
||||
drivePath := m.GetAppDrivePath(stackName)
|
||||
if drivePath == "" {
|
||||
return ""
|
||||
}
|
||||
return m.namespaceRoot(drivePath)
|
||||
}
|
||||
|
||||
// groupStacksByDrive groups deployed stacks by their home drive path.
|
||||
func (m *Manager) groupStacksByDrive() map[string][]StackSummary {
|
||||
if m.stackProvider == nil {
|
||||
@@ -170,7 +190,7 @@ func (m *Manager) runDBDumpsInternal(ctx context.Context) error {
|
||||
continue
|
||||
}
|
||||
|
||||
dumpDir := AppDBDumpPath(drivePath, db.StackName)
|
||||
dumpDir := AppDBDumpPath(m.namespaceRoot(drivePath), db.StackName)
|
||||
|
||||
result := DumpOne(ctx, db, dumpDir, m.logger, m.isDebug())
|
||||
results = append(results, result)
|
||||
@@ -239,7 +259,7 @@ func (m *Manager) DumpAppVolumes(stackName string) error {
|
||||
return fmt.Errorf("cannot determine drive path for %s", stackName)
|
||||
}
|
||||
|
||||
dumpDir := AppVolumeDumpPath(drivePath, stackName)
|
||||
dumpDir := AppVolumeDumpPath(m.namespaceRoot(drivePath), stackName)
|
||||
if err := os.MkdirAll(dumpDir, 0755); err != nil {
|
||||
return fmt.Errorf("creating volume dump dir: %w", err)
|
||||
}
|
||||
@@ -395,7 +415,7 @@ 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)
|
||||
}
|
||||
dumpDir := AppDBDumpPath(drivePath, stackName)
|
||||
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)
|
||||
|
||||
@@ -428,7 +448,7 @@ func (m *Manager) listAllDumpFiles() []DumpFileInfo {
|
||||
var allFiles []DumpFileInfo
|
||||
for drive, stacks := range m.groupStacksByDrive() {
|
||||
for _, stack := range stacks {
|
||||
dumpDir := AppDBDumpPath(drive, stack.Name)
|
||||
dumpDir := AppDBDumpPath(m.namespaceRoot(drive), stack.Name)
|
||||
if files, err := ListDumpFiles(dumpDir); err == nil {
|
||||
allFiles = append(allFiles, files...)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user