v0.78.0: storage register uses the STABLE intermediary path, not the raw path

handleStorageRegister (the "Regisztrálás" action for an already-mounted,
unregistered drive) registered the raw /mnt/<name> path verbatim, unlike
runStorageInit/runStorageAttach which map to the stable /mnt/felhom-drives/<name>
path the agent actually binds the drive at. The controller then watched an empty
placeholder dir on the guest rootfs → "Rendszermeghajtón" + stuck "activation
pending" banner after a re-provision.

Fix: register stablePathForName(path.Base(req.Where)); attachIntoGuest still uses
the raw path (the agent operates on raw). Test + red-proof added.

Diagnosis: felhom.eu/documentation/audits/DIAGNOSE-drive-bind-after-reprovision-2026-06-23.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PsnU2ASocYrvzqE82YDYW
This commit is contained in:
2026-06-23 17:28:07 +02:00
parent 66d84627b8
commit 68e7e07838
4 changed files with 124 additions and 35 deletions
+13 -5
View File
@@ -679,18 +679,26 @@ func (s *Server) handleStorageRegister(w http.ResponseWriter, r *http.Request) {
writeDiskJSON(w, http.StatusBadRequest, false, "érvénytelen csatlakoztatási pont", nil)
return
}
if err := s.registerStoragePath(req.Where, req.Label, req.SetDefault); err != nil {
s.logger.Printf("[WARN] [web] storage register %s failed: %v", req.Where, err)
// req.Where is the RAW /mnt/<name> host mount the agent reports; in the intermediary model the drive
// is actually live in the guest at the STABLE path /mnt/felhom-drives/<name>, so REGISTER the stable
// path (matching runStorageInit/runStorageAttach). Registering the raw path made the controller watch
// an empty rootfs placeholder → "Rendszermeghajtón" + stuck "activation pending" banner
// (DIAGNOSE-drive-bind-after-reprovision-2026-06-23.md). attachIntoGuest still uses the RAW path —
// the agent operates on raw.
stable := stablePathForName(path.Base(req.Where))
if err := s.registerStoragePath(stable, req.Label, req.SetDefault); err != nil {
s.logger.Printf("[WARN] [web] storage register %s (stable %s) failed: %v", req.Where, stable, err)
writeDiskJSON(w, http.StatusBadGateway, false, err.Error(), nil)
return
}
s.logger.Printf("[INFO] [web] storage path registered (existing mount): %s", req.Where)
s.logger.Printf("[INFO] [web] storage path registered (existing mount): %s → %s", req.Where, stable)
// Pass the drive into the guest too (slice 10 P2) — registering a host-only mount otherwise leaves
// it guest-invisible (the exact gap that produced the "nem elérhető" banner).
// it guest-invisible (the exact gap that produced the "nem elérhető" banner). The agent operates on
// the RAW path, so attach with req.Where (NOT the stable path).
if agent, aerr := s.agentClient(); aerr == nil {
s.attachIntoGuest(r.Context(), agent, req.Where)
}
writeDiskJSON(w, http.StatusOK, true, "", map[string]any{"registered": true, "where": req.Where})
writeDiskJSON(w, http.StatusOK, true, "", map[string]any{"registered": true, "where": stable, "raw": req.Where})
}
func (s *Server) handleStorageAttach(w http.ResponseWriter, r *http.Request) {