From 4120f22374aaad18d644e0e01830dfcc6cd015e3 Mon Sep 17 00:00:00 2001 From: "pulse-triage[bot]" <249995291+pulse-triage[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 19:58:58 +0100 Subject: [PATCH] Test linked guest memory after registry reconstruction Keep stale/offline/unavailable controls, diagnostic and alert agreement, and verify isolation with a simultaneous duplicate VMID in another instance. Test-only follow-through for issue #1962. Change-source: pulse-maintainer --- .../monitoring/monitor_additional_test.go | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/internal/monitoring/monitor_additional_test.go b/internal/monitoring/monitor_additional_test.go index f6789035f..4d95c0bb6 100644 --- a/internal/monitoring/monitor_additional_test.go +++ b/internal/monitoring/monitor_additional_test.go @@ -909,7 +909,7 @@ func TestCorrelatedGuestMemoryNextPoll(t *testing.T) { } registry := unifiedresources.NewRegistry(store) total, used := int64(8000), int64(8000) - registry.IngestResources([]unifiedresources.Resource{ + resources := []unifiedresources.Resource{ {ID: "vm-test", Type: unifiedresources.ResourceTypeVM, Name: "firewall", Status: unifiedresources.StatusOnline, LastSeen: now, Sources: []unifiedresources.DataSource{unifiedresources.SourceProxmox}, Proxmox: &unifiedresources.ProxmoxData{SourceID: guestID, Instance: "pve-a", NodeName: "node1", VMID: 111, RuntimeStatus: "running"}, @@ -917,10 +917,35 @@ func TestCorrelatedGuestMemoryNextPoll(t *testing.T) { {ID: "agent-test", Type: unifiedresources.ResourceTypeAgent, Name: "firewall-agent", Status: unifiedresources.ResourceStatus(tc.status), LastSeen: now.Add(-tc.age), Sources: []unifiedresources.DataSource{unifiedresources.SourceAgent}, Agent: &unifiedresources.AgentData{AgentID: "agent-test", Stale: tc.status == "offline", Memory: &unifiedresources.AgentMemoryMeta{Total: 8000, Used: 2800, Free: 5200, UsageUnavailable: tc.unavailable}}}, - }) + } + registry.IngestResources(resources) + if len(registry.VMs()) != 1 || len(registry.Hosts()) != 0 { + t.Fatal("initial registry did not merge linked guest") + } + // Rebuild from source evidence and the retained link store, not a + // previously merged resource or the old in-memory matcher. + registry = unifiedresources.NewRegistry(store) + registry.IngestResources(resources) if len(registry.VMs()) != 1 || len(registry.Hosts()) != 0 { t.Fatalf("expected one merged VM and no standalone hosts") } + + // A simultaneous guest with the same node name and VMID must not + // inherit this instance's agent memory. + registry.IngestRecords(unifiedresources.SourceProxmox, []unifiedresources.IngestRecord{{ + SourceID: makeGuestID("pve-b", "node1", 111), + Resource: unifiedresources.Resource{ + Type: unifiedresources.ResourceTypeVM, Name: "other-firewall", + Status: unifiedresources.StatusOnline, LastSeen: now, + Proxmox: &unifiedresources.ProxmoxData{ + SourceID: makeGuestID("pve-b", "node1", 111), + Instance: "pve-b", NodeName: "node1", VMID: 111, RuntimeStatus: "running", + }, + }, + }}) + if len(registry.VMs()) != 2 { + t.Fatal("duplicate VMIDs from separate instances were not preserved") + } mon := &Monitor{state: models.NewState(), rateTracker: NewRateTracker(), config: &config.Config{}, resourceStore: unifiedresources.NewMonitorAdapter(registry)} prev := mon.previousGuestContextForInstance("pve-a") raw := VMMemoryRaw{} @@ -975,6 +1000,11 @@ func TestCorrelatedGuestMemoryNextPoll(t *testing.T) { if len(other.hostAgentsByVMID) != 0 { t.Fatal("correlated agent crossed instance boundary") } + otherID := makeGuestID("pve-b", "node1", 111) + _, otherUsed, otherSource := mon.resolveGuestStatusMemory(context.Background(), &stubPVEClient{}, "pve-b", "other-firewall", "node1", 111, otherID, &proxmox.VMStatus{MaxMem: 8000, Mem: 8100}, other.hostAgentsByVMID, 8000, "", &VMMemoryRaw{}) + if otherUsed != 8000 || otherSource != "status-mem" { + t.Fatalf("other instance inherited agent memory: used=%d source=%s", otherUsed, otherSource) + } }) } }