diff --git a/internal/collector/redfishprofile/fixture_test.go b/internal/collector/redfishprofile/fixture_test.go index e3ef6a2..f41f03f 100644 --- a/internal/collector/redfishprofile/fixture_test.go +++ b/internal/collector/redfishprofile/fixture_test.go @@ -304,6 +304,51 @@ func TestBuildAcquisitionPlan_Fixture_UnknownVendor(t *testing.T) { } } +func TestBuildAcquisitionPlan_Fixture_xFusion_G5500V7(t *testing.T) { + signals := loadProfileFixtureSignals(t, "xfusion-g5500v7.json") + match := MatchProfiles(signals) + plan := BuildAcquisitionPlan(signals) + resolved := ResolveAcquisitionPlan(match, plan, DiscoveredResources{ + SystemPaths: []string{"/redfish/v1/Systems/1"}, + ChassisPaths: []string{"/redfish/v1/Chassis/1"}, + ManagerPaths: []string{"/redfish/v1/Managers/1"}, + }, signals) + + if match.Mode != ModeMatched { + t.Fatalf("expected matched mode for xFusion, got %q", match.Mode) + } + assertProfileSelected(t, match, "xfusion") + assertProfileNotSelected(t, match, "supermicro") + assertProfileNotSelected(t, match, "hgx-topology") + assertProfileNotSelected(t, match, "msi") + assertProfileNotSelected(t, match, "dell") + + if plan.Tuning.SnapshotMaxDocuments > 150000 { + t.Fatalf("expected xfusion snapshot cap <= 150000, got %d", plan.Tuning.SnapshotMaxDocuments) + } + if plan.Tuning.PrefetchEnabled == nil || !*plan.Tuning.PrefetchEnabled { + t.Fatal("expected xfusion fixture to enable prefetch") + } + if plan.Tuning.ETABaseline.SnapshotSeconds <= 0 { + t.Fatal("expected xfusion snapshot eta baseline") + } + if !containsString(resolved.CriticalPaths, "/redfish/v1/Systems/1") { + t.Fatal("expected system path in critical paths") + } + + analysisPlan := ResolveAnalysisPlan(match, map[string]interface{}{ + "/redfish/v1/Systems/1/Processors/Gpu1": map[string]interface{}{"ProcessorType": "GPU"}, + }, DiscoveredResources{ + SystemPaths: []string{"/redfish/v1/Systems/1"}, + }, signals) + if !analysisPlan.Directives.EnableProcessorGPUFallback { + t.Fatal("expected xfusion analysis to enable processor GPU fallback when GPU processors present") + } + if !analysisPlan.Directives.EnableGenericGraphicsControllerDedup { + t.Fatal("expected xfusion analysis to enable graphics controller dedup") + } +} + func loadProfileFixtureSignals(t *testing.T, fixtureName string) MatchSignals { t.Helper() path := filepath.Join("testdata", fixtureName) diff --git a/internal/collector/redfishprofile/profile_xfusion.go b/internal/collector/redfishprofile/profile_xfusion.go new file mode 100644 index 0000000..ecee301 --- /dev/null +++ b/internal/collector/redfishprofile/profile_xfusion.go @@ -0,0 +1,55 @@ +package redfishprofile + +func xfusionProfile() Profile { + return staticProfile{ + name: "xfusion", + priority: 20, + safeForFallback: true, + matchFn: func(s MatchSignals) int { + score := 0 + if containsFold(s.ServiceRootVendor, "xfusion") { + score += 90 + } + for _, ns := range s.OEMNamespaces { + if containsFold(ns, "xfusion") { + score += 20 + break + } + } + if containsFold(s.SystemManufacturer, "xfusion") || containsFold(s.ChassisManufacturer, "xfusion") { + score += 40 + } + return min(score, 100) + }, + extendAcquisition: func(plan *AcquisitionPlan, _ MatchSignals) { + ensureSnapshotMaxDocuments(plan, 120000) + ensureSnapshotWorkers(plan, 4) + ensurePrefetchWorkers(plan, 4) + ensurePrefetchEnabled(plan, true) + ensureETABaseline(plan, AcquisitionETABaseline{ + DiscoverySeconds: 10, + SnapshotSeconds: 90, + PrefetchSeconds: 20, + CriticalPlanBSeconds: 30, + ProfilePlanBSeconds: 20, + }) + ensureRatePolicy(plan, AcquisitionRatePolicy{ + TargetP95LatencyMS: 800, + ThrottleP95LatencyMS: 1800, + MinSnapshotWorkers: 2, + MinPrefetchWorkers: 1, + DisablePrefetchOnErrors: true, + }) + addPlanNote(plan, "xfusion ibmc acquisition extensions enabled") + }, + applyAnalysisDirectives: func(d *AnalysisDirectives, _ MatchSignals) { + d.EnableGenericGraphicsControllerDedup = true + }, + refineAnalysis: func(plan *ResolvedAnalysisPlan, snapshot map[string]interface{}, discovered DiscoveredResources, _ MatchSignals) { + if snapshotHasGPUProcessor(snapshot, discovered.SystemPaths) { + plan.Directives.EnableProcessorGPUFallback = true + addAnalysisNote(plan, "xfusion analysis enables processor-gpu fallback from snapshot topology") + } + }, + } +} diff --git a/internal/collector/redfishprofile/profiles_common.go b/internal/collector/redfishprofile/profiles_common.go index f6789f0..cfa13ee 100644 --- a/internal/collector/redfishprofile/profiles_common.go +++ b/internal/collector/redfishprofile/profiles_common.go @@ -56,6 +56,7 @@ func BuiltinProfiles() []Profile { supermicroProfile(), dellProfile(), hgxProfile(), + xfusionProfile(), } } diff --git a/internal/collector/redfishprofile/testdata/xfusion-g5500v7.json b/internal/collector/redfishprofile/testdata/xfusion-g5500v7.json new file mode 100644 index 0000000..912bbd3 --- /dev/null +++ b/internal/collector/redfishprofile/testdata/xfusion-g5500v7.json @@ -0,0 +1,24 @@ +{ + "ServiceRootVendor": "xFusion", + "ServiceRootProduct": "G5500 V7", + "SystemManufacturer": "OEM", + "SystemModel": "G5500 V7", + "SystemSKU": "", + "ChassisManufacturer": "OEM", + "ChassisModel": "G5500 V7", + "ManagerManufacturer": "XFUSION", + "OEMNamespaces": ["xFusion"], + "ResourceHints": [ + "/redfish/v1/Chassis/1", + "/redfish/v1/Chassis/1/Drives", + "/redfish/v1/Chassis/1/PCIeDevices", + "/redfish/v1/Chassis/1/Sensors", + "/redfish/v1/Managers/1", + "/redfish/v1/Systems/1", + "/redfish/v1/Systems/1/GraphicsControllers", + "/redfish/v1/Systems/1/Processors", + "/redfish/v1/Systems/1/Processors/Gpu1", + "/redfish/v1/Systems/1/Storages", + "/redfish/v1/UpdateService/FirmwareInventory" + ] +}