Files
felhom-controller/controller/internal/web/r25_fsuuid_mount_test.go
T
admin 1355391c78 R-25 (controller half): drive init mounts the filesystem UUID the agent verified
agentapi FormatResult / FormatStatusResult gain fs_uuid (agent R-25 half). runStorageInit mounts
it — from the synchronous answer or the polled status — instead of re-resolving the UUID from the
/dev path, so a node that moved between format and mount cannot redirect the mount. An agent that
sends no field keeps the old resolve, logged as a WARN each time (the window is open then).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-05 21:55:37 +02:00

59 lines
2.4 KiB
Go

package web
import (
"context"
"testing"
"gitea.dooplex.hu/admin/felhom-controller/internal/agentapi"
)
// R-25: the init flow mounts the filesystem UUID the AGENT verified it made, not one re-resolved from
// the /dev path. The fixture makes the two DISAGREE — the device path now resolves to another
// filesystem (the node moved) — so only the agent's value is right.
func TestR25_InitMountsTheAgentsFSUUID(t *testing.T) {
moved := agentapi.DisksResponse{Disks: []agentapi.DiskInfo{
{Name: "other", BackingDevice: "/dev/sdb1", DurableID: "uuid:SOMEONE-ELSES"},
}}
t.Run("synchronous format answer", func(t *testing.T) {
s := testServer(t)
agent := &mockAgent{
formatRes: agentapi.FormatResult{Device: "/dev/sdb1", Formatted: true, FSUUID: "AGENT-VERIFIED"},
disks: moved,
}
if _, err := s.runStorageInit(context.Background(), agent, "/dev/sdb1", "ext4", "/mnt/hdd1", "HDD", false, false, "", nil); err != nil {
t.Fatal(err)
}
if len(agent.assignCalls) != 1 || agent.assignCalls[0].uuid != "AGENT-VERIFIED" {
t.Fatalf("R-25: mounted %+v, want the agent-verified UUID", agent.assignCalls)
}
})
t.Run("detached format, polled status", func(t *testing.T) {
s := testServer(t)
agent := &mockAgent{
formatRes: agentapi.FormatResult{Device: "/dev/sdb1", Formatted: false},
formatErr: context.DeadlineExceeded,
formatStatus: agentapi.FormatStatusResult{Phase: "done", Device: "/dev/sdb1", FSUUID: "AGENT-VERIFIED"},
disks: moved,
}
if _, err := s.runStorageInit(context.Background(), agent, "/dev/sdb1", "ext4", "/mnt/hdd1", "HDD", false, false, "", nil); err != nil {
t.Fatal(err)
}
if len(agent.assignCalls) != 1 || agent.assignCalls[0].uuid != "AGENT-VERIFIED" {
t.Fatalf("R-25: the polled path mounted %+v, want the agent-verified UUID", agent.assignCalls)
}
})
t.Run("older agent sends no field: path fallback", func(t *testing.T) {
s := testServer(t)
agent := &mockAgent{
formatRes: agentapi.FormatResult{Device: "/dev/sdb1", Formatted: true},
disks: moved,
}
if _, err := s.runStorageInit(context.Background(), agent, "/dev/sdb1", "ext4", "/mnt/hdd1", "HDD", false, false, "", nil); err != nil {
t.Fatal(err)
}
if len(agent.assignCalls) != 1 || agent.assignCalls[0].uuid != "SOMEONE-ELSES" {
t.Fatalf("an agent with no fs_uuid must keep the old path resolve, mounted %+v", agent.assignCalls)
}
})
}