package storage import ( "context" "testing" "gitea.dooplex.hu/admin/felhom-agent/internal/hub" "gitea.dooplex.hu/admin/felhom-agent/internal/proxmox" ) // Fix A (A2): the builtin `local` dir lives on the LVM root, so its backing is empty by design — but // enrich now resolves the containing filesystem (/ → /dev/mapper/pve-root) and, via the dm sysfs // slaves, the physical disk (/dev/sda). The system disk stops reading "Nincs adat". // Red-proof: drop the `smartDev = ob.smartHint` fallback in enrich → local stays UNKNOWN and SMART // is never called on /dev/sda. func TestObserve_SystemDirSMARTViaContainingFS(t *testing.T) { fixtureSysfs(t, map[string][]string{"dm-1": {"sda3"}}, map[string]string{"dm-1": "pve-root"}) api := &fakeStorageAPI{ node: "demo-felhom", cluster: []proxmox.Storage{{Storage: "local", Type: "dir", Path: "/var/lib/vz"}}, nodeSt: []proxmox.Storage{{Storage: "local", Type: "dir", Path: "/var/lib/vz", Active: 1}}, } host := &fakeHostReader{ mounts: []Mount{{Device: "/dev/mapper/pve-root", MountPoint: "/", FSType: "ext4"}}, } ops := &fakeHostOps{smartByDevice: map[string]hub.SmartSummary{"/dev/sda": {Health: hub.SmartPassed, ModelName: strptr("AirDisk 512GB SSD")}}} got, err := NewObserver(api, host, ops, quietLogger()).Observe(context.Background()) if err != nil { t.Fatal(err) } local := byName(got)["local"] if local.Smart.Health != hub.SmartPassed { t.Errorf("system disk SMART not enriched via the containing fs: health=%q", local.Smart.Health) } if local.Smart.ModelName == nil || *local.Smart.ModelName != "AirDisk 512GB SSD" { t.Errorf("model not carried: %v", local.Smart.ModelName) } // SMART must have run on the resolved PHYSICAL disk, never the dm/mapper node. if len(ops.smartDevices) != 1 || ops.smartDevices[0] != "/dev/sda" { t.Errorf("SMART should target /dev/sda, got %v", ops.smartDevices) } // The backing device / durable_id must stay untouched by the SMART-only resolution. if local.BackingDevice != "" { t.Errorf("system-dir SMART resolution leaked into BackingDevice: %q", local.BackingDevice) } } // The watchdog Known() path MUST remain enrich-free (its slow root-shelling reads are the reason it // exists as a separate fast path). Known must never invoke SMART. // Red-proof: route Known through enrich → smartDevices is non-empty and this fails. func TestKnown_NeverInvokesSMART(t *testing.T) { fixtureSysfs(t, map[string][]string{"dm-1": {"sda3"}}, map[string]string{"dm-1": "pve-root"}) api := &fakeStorageAPI{ node: "demo-felhom", cluster: []proxmox.Storage{{Storage: "local", Type: "dir", Path: "/var/lib/vz"}}, nodeSt: []proxmox.Storage{{Storage: "local", Type: "dir", Path: "/var/lib/vz", Active: 1}}, } host := &fakeHostReader{mounts: []Mount{{Device: "/dev/mapper/pve-root", MountPoint: "/", FSType: "ext4"}}} ops := &fakeHostOps{smartByDevice: map[string]hub.SmartSummary{"/dev/sda": {Health: hub.SmartPassed}}} if _, err := NewObserver(api, host, ops, quietLogger()).Known(context.Background()); err != nil { t.Fatal(err) } if len(ops.smartDevices) != 0 { t.Errorf("Known() invoked SMART %d time(s) — it must stay enrich-free: %v", len(ops.smartDevices), ops.smartDevices) } } func strptr(s string) *string { return &s }