1355391c78
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
59 lines
2.4 KiB
Go
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)
|
|
}
|
|
})
|
|
}
|