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
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user