R-356: the off-site restore refused every app that has no data drive
gates / gates (push) Failing after 12s
gates / gates (push) Failing after 12s
ReconstituteFromOffsite and PlaceOffsiteRestore both resolved the restore destination with the RAW HDD_PATH and read an empty answer as "the app is not installed". For 40 of the 53 catalogue apps that answer is correctly empty and permanent, so both actions refused forever for a running, healthy app — and told the customer to reinstall it "in the same place", which those apps never offer. Separate the two questions. "Installed?" is asked of ListDeployedStacks via a new Manager.isStackDeployed that fails CLOSED on a nil provider. "Where?" is answered by GetAppDrivePath — the same resolver CaptureRecoveryUnit wrote the snapshot with, so the restore aims at the place the backup came from. The 13 drive apps are unchanged: own drive, mismatch check, ack still required. A third refusal, with its own sentence, covers installed-but-no-resolvable-root. Fixtures that marked an app "installed" by giving it an HDD path now state deployment as its own fact. No assertion weakened.
This commit is contained in:
@@ -407,16 +407,21 @@ func (m *Manager) PlaceOffsiteRestore(ctx context.Context, stack string) error {
|
||||
return err
|
||||
}
|
||||
_ = id
|
||||
// F-3a-1a: the live target uses the RAW HDD path (mirrors offboxCaptureSet). NOT AppNamespaceRoot —
|
||||
// its systemDataPath fallback would merge userdata onto the SSD system namespace. Empty HDD ⇒
|
||||
// undeployed ⇒ refuse: the app must be restored first, then its data placed under its live drive.
|
||||
hdd := ""
|
||||
if m.stackProvider != nil {
|
||||
hdd = strings.TrimSpace(m.stackProvider.GetStackHDDPath(stack))
|
||||
}
|
||||
if hdd == "" {
|
||||
// F-3a-1a said: the live target uses the RAW HDD path, and an empty HDD means undeployed.
|
||||
// R-356 split that: "undeployed" is now asked directly, and the destination is resolved by the
|
||||
// SAME rule the capture side wrote this snapshot with (GetAppDrivePath — drive if the app has
|
||||
// one, system data path otherwise). For the 13 needs_hdd apps nothing changes; for the 40 that
|
||||
// were never offered a drive the old test was permanently true and this merge was unreachable.
|
||||
if !m.isStackDeployed(stack) {
|
||||
return fmt.Errorf("a(z) %s nincs telepítve — előbb állítsd helyre az alkalmazást, utána az adatokat", stack)
|
||||
}
|
||||
hdd := strings.TrimSpace(m.GetAppDrivePath(stack))
|
||||
if hdd == "" {
|
||||
// Installed, but the box cannot name its own data root. Distinct reason ⇒ distinct sentence:
|
||||
// telling the customer to reinstall a running app would hide the real fault.
|
||||
return fmt.Errorf("a(z) %s telepítve van, de a vezérlő nem tudja megállapítani, hová tartoznak az adatai "+
|
||||
"(nincs beállítva rendszer-adatterület). Ellenőrizd a tárhely beállításait (Tárhely), utána indítsd újra a visszaállítást", stack)
|
||||
}
|
||||
liveNs := m.namespaceRoot(hdd)
|
||||
// F-3a-1b: headroom gate — a missing-only merge copies at most the scratch size; refuse before any
|
||||
// copy if the live drive lacks that (conservative — scratch and live often share a drive).
|
||||
|
||||
Reference in New Issue
Block a user