fix: correct CPU and memory slot deduplication on HP ProLiant

- discovery.cpp: remove K_SERIAL emission from dmidecode CPU "ID" field
  (it is the CPUID instruction result, identical across matching processors
  in a multi-socket system, not a unique per-slot serial number)
  → upsert_part now falls through to K_SOCKET natural key, correctly
    inserting both "Proc 1" and "Proc 2" as separate records

- discovery.cpp: skip memory slot blocks with missing or empty Locator
  (HP ProLiant firmware returns a phantom type-17 block with no Locator;
  this was causing a 19th slot record to be inserted with empty locator
  that could never be deduplicated on subsequent runs)

Verified on HP ProLiant DL360 G7:
  cpu=2, cpu_slots=2, memory_sticks=12, memory_slots=18, disks=5, nics=4

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Dan V 2026-03-31 22:50:33 +02:00
parent b9736266c9
commit 7a8ea3e88f
2 changed files with 6 additions and 2 deletions

View file

@ -486,6 +486,9 @@ std::vector<DiscoveredPart> Discovery::discover_memory_slots() {
} }
for (auto& b : blocks17) { for (auto& b : blocks17) {
// Skip blocks without a Locator — these are malformed/phantom HP firmware entries
if (!b.count("Locator") || b["Locator"].empty()) continue;
DiscoveredPart p; DiscoveredPart p;
p.type_name = PTYPE_MEMORY_SLOT; p.type_name = PTYPE_MEMORY_SLOT;
@ -579,8 +582,9 @@ std::vector<DiscoveredPart> Discovery::discover_cpus() {
DiscoveredPart p; DiscoveredPart p;
p.type_name = PTYPE_CPU; p.type_name = PTYPE_CPU;
if (b.count("ID") && b["ID"] != "Not Specified") // Do NOT use dmidecode "ID" (CPUID family/model/stepping) as serial —
p.kv[K_SERIAL] = b["ID"]; // it is identical across matching CPUs in multi-socket systems.
// Socket designation is the actual unique natural key.
if (b.count("Version") && b["Version"] != "Not Specified") if (b.count("Version") && b["Version"] != "Not Specified")
p.kv[K_NAME] = b["Version"]; p.kv[K_NAME] = b["Version"];
if (b.count("Manufacturer") && b["Manufacturer"] != "Not Specified") if (b.count("Manufacturer") && b["Manufacturer"] != "Not Specified")