controller v0.68.0: storage lifecycle on intermediary model (H2/H3/M1/M3 + boot-id)

H2 decommission UI button (migrate / anyway); H3 one-click re-enroll of a
decommissioned drive; M1 default reassignment (auto-promote + block-if-none);
M3 migrate re-asserts 2775 setgid on userdata dirs; deterministic guest-reboot
recreate via agent boot_id (replaces the timed sample). Fixes the {path}/{where}
H1 JS bug. Non-hollow tests + companions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-15 19:26:02 +02:00
parent bc41acf4da
commit 42f69dadda
10 changed files with 293 additions and 46 deletions
@@ -14,11 +14,18 @@ import (
func TestFinalizeDecommission_SoftMarksAndCallsAgent(t *testing.T) {
s := testServer(t)
_ = s.settings.AddStoragePath(settings.StoragePath{Path: "/mnt/old", Schedulable: true, IsDefault: true})
// The migrate target is a registered schedulable drive (realistic for migrate-then-decommission); M1
// promotes it to default since /mnt/old was the default.
_ = s.settings.AddStoragePath(settings.StoragePath{Path: "/mnt/new", Schedulable: true})
agent := &mockAgent{}
if err := s.finalizeDecommissionWith(context.Background(), agent, "/mnt/old", "/mnt/new"); err != nil {
t.Fatalf("finalize: %v", err)
}
// M1: the default was reassigned to the migrate target (never zero default).
if s.settings.GetDefaultStoragePath() != "/mnt/new" {
t.Errorf("default not reassigned to /mnt/new (M1), got %q", s.settings.GetDefaultStoragePath())
}
// soft-marked, entry retained
if !s.settings.IsDecommissioned("/mnt/old") {
t.Errorf("path not soft-marked decommissioned")