From 47ff1c37965776e02e59ac8476aee21abbbcb050 Mon Sep 17 00:00:00 2001 From: Michael Chus Date: Fri, 12 Jun 2026 03:58:55 +0300 Subject: [PATCH] fix(inspur): detect standard Inspur servers via SystemManufacturer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NF-series storage servers (e.g. NF5280M6) have no GPU/outboard-PCIe topology, so the previous score gate (topologyScore==0 || boardScore==0 → return 0) always produced score=0 despite SystemManufacturer="Inspur" being available. These servers fell into mode=fallback, activating the AMI profile and probing /Oem/Ami paths that don't exist on the BMC. Add manufacturer-based detection: SystemManufacturer or ChassisManufacturer containing "inspur" contributes 60 points — enough to enter matched mode on its own. GPU servers with full topology+board signals still score higher as before. Co-Authored-By: Claude Sonnet 4.6 --- .../profile_inspur_group_oem_platforms.go | 12 ++++- ...profile_inspur_group_oem_platforms_test.go | 46 +++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/internal/collector/redfishprofile/profile_inspur_group_oem_platforms.go b/internal/collector/redfishprofile/profile_inspur_group_oem_platforms.go index 9cee549..6c78dbc 100644 --- a/internal/collector/redfishprofile/profile_inspur_group_oem_platforms.go +++ b/internal/collector/redfishprofile/profile_inspur_group_oem_platforms.go @@ -29,6 +29,7 @@ func inspurGroupOEMPlatformsProfile() Profile { matchFn: func(s MatchSignals) int { topologyScore := 0 boardScore := 0 + manufacturerScore := 0 chassisOutboard := matchedPathTokens(s.ResourceHints, "/redfish/v1/Chassis/", outboardCardHintRe) systemOutboard := matchedPathTokens(s.ResourceHints, "/redfish/v1/Systems/", outboardCardHintRe) obDrives := matchedPathTokens(s.ResourceHints, "", obDriveHintRe) @@ -62,10 +63,17 @@ func inspurGroupOEMPlatformsProfile() Profile { if anySignalContains(s, "GetServerAllUSBStatus") { boardScore += 8 } - if topologyScore == 0 || boardScore == 0 { + // Manufacturer alone is sufficient for standard Inspur servers (e.g. NF-series + // storage servers) that lack GPU/outboard-PCIe topology signals. Score 60 is + // the minimum to enter matched mode; topology+board can push it higher. + if containsFold(s.SystemManufacturer, "inspur") || containsFold(s.ChassisManufacturer, "inspur") { + manufacturerScore = 60 + } + total := manufacturerScore + topologyScore + boardScore + if total < 60 { return 0 } - return min(topologyScore+boardScore, 100) + return min(total, 100) }, extendAcquisition: func(plan *AcquisitionPlan, _ MatchSignals) { addPlanNote(plan, "Inspur Group OEM platform fingerprint matched") diff --git a/internal/collector/redfishprofile/profile_inspur_group_oem_platforms_test.go b/internal/collector/redfishprofile/profile_inspur_group_oem_platforms_test.go index 156a4ef..70ee38c 100644 --- a/internal/collector/redfishprofile/profile_inspur_group_oem_platforms_test.go +++ b/internal/collector/redfishprofile/profile_inspur_group_oem_platforms_test.go @@ -118,6 +118,52 @@ func TestCollectSignalsFromTree_InspurGroupOEMPlatformsSelectsMatchedMode(t *tes assertProfileSelected(t, match, "inspur-group-oem-platforms") } +// TestCollectSignalsFromTree_InspurGroupOEMPlatformsMatchesViaManufacturer covers standard +// Inspur storage servers (e.g. NF5280M6) that have no outboard PCIe / GPU topology but +// do expose Manufacturer="Inspur" in their System document. +func TestCollectSignalsFromTree_InspurGroupOEMPlatformsMatchesViaManufacturer(t *testing.T) { + // Minimal tree: no GPU cards, no OEM firmware hints — only System Manufacturer. + tree := map[string]interface{}{ + "/redfish/v1": map[string]interface{}{ + "@odata.id": "/redfish/v1", + }, + "/redfish/v1/Systems": map[string]interface{}{ + "Members": []interface{}{ + map[string]interface{}{"@odata.id": "/redfish/v1/Systems/1"}, + }, + }, + "/redfish/v1/Systems/1": map[string]interface{}{ + "@odata.id": "/redfish/v1/Systems/1", + "Manufacturer": "Inspur", + "Model": "NF5280M6", + }, + "/redfish/v1/Chassis": map[string]interface{}{ + "Members": []interface{}{ + map[string]interface{}{"@odata.id": "/redfish/v1/Chassis/1"}, + }, + }, + "/redfish/v1/Chassis/1": map[string]interface{}{ + "@odata.id": "/redfish/v1/Chassis/1", + }, + "/redfish/v1/Managers": map[string]interface{}{ + "Members": []interface{}{ + map[string]interface{}{"@odata.id": "/redfish/v1/Managers/1"}, + }, + }, + "/redfish/v1/Managers/1": map[string]interface{}{ + "@odata.id": "/redfish/v1/Managers/1", + }, + } + + signals := CollectSignalsFromTree(tree) + match := MatchProfiles(signals) + + if match.Mode != ModeMatched { + t.Fatalf("expected matched mode for Inspur NF-series, got %q (scores: %v)", match.Mode, match.Scores) + } + assertProfileSelected(t, match, "inspur-group-oem-platforms") +} + func TestCollectSignalsFromTree_InspurGroupOEMPlatformsDoesNotFalsePositiveOnExampleRawExports(t *testing.T) { examples := []string{ "2026-03-18 (G5500 V7) - 210619KUGGXGS2000015.zip",