package redfishprofile import "strings" func ResolveAcquisitionPlan(match MatchResult, plan AcquisitionPlan, discovered DiscoveredResources, signals MatchSignals) ResolvedAcquisitionPlan { seedGroups := [][]string{ baselineSeedPaths(discovered), expandScopedSuffixes(discovered.SystemPaths, plan.ScopedPaths.SystemSeedSuffixes), expandScopedSuffixes(discovered.ChassisPaths, plan.ScopedPaths.ChassisSeedSuffixes), expandScopedSuffixes(discovered.ManagerPaths, plan.ScopedPaths.ManagerSeedSuffixes), plan.SeedPaths, } if plan.Mode == ModeFallback { seedGroups = append(seedGroups, plan.PlanBPaths) } criticalGroups := [][]string{ baselineCriticalPaths(discovered), expandScopedSuffixes(discovered.SystemPaths, plan.ScopedPaths.SystemCriticalSuffixes), expandScopedSuffixes(discovered.ChassisPaths, plan.ScopedPaths.ChassisCriticalSuffixes), expandScopedSuffixes(discovered.ManagerPaths, plan.ScopedPaths.ManagerCriticalSuffixes), plan.CriticalPaths, } resolved := ResolvedAcquisitionPlan{ Plan: plan, SeedPaths: mergeResolvedPaths(seedGroups...), CriticalPaths: mergeResolvedPaths(criticalGroups...), } for _, profile := range match.Profiles { profile.RefineAcquisitionPlan(&resolved, discovered, signals) } resolved.SeedPaths = mergeResolvedPaths(resolved.SeedPaths) resolved.CriticalPaths = mergeResolvedPaths(resolved.CriticalPaths, resolved.Plan.CriticalPaths) resolved.Plan.SeedPaths = mergeResolvedPaths(resolved.Plan.SeedPaths) resolved.Plan.CriticalPaths = mergeResolvedPaths(resolved.Plan.CriticalPaths) resolved.Plan.PlanBPaths = mergeResolvedPaths(resolved.Plan.PlanBPaths) return resolved } func baselineSeedPaths(discovered DiscoveredResources) []string { var out []string add := func(p string) { if p = normalizePath(p); p != "" { out = append(out, p) } } add("/redfish/v1/UpdateService") add("/redfish/v1/UpdateService/FirmwareInventory") for _, p := range discovered.SystemPaths { add(p) add(joinPath(p, "/Bios")) add(joinPath(p, "/Oem/Public")) add(joinPath(p, "/Oem/Public/FRU")) add(joinPath(p, "/Processors")) add(joinPath(p, "/Memory")) add(joinPath(p, "/EthernetInterfaces")) add(joinPath(p, "/NetworkInterfaces")) add(joinPath(p, "/PCIeDevices")) add(joinPath(p, "/PCIeFunctions")) add(joinPath(p, "/Accelerators")) add(joinPath(p, "/GraphicsControllers")) add(joinPath(p, "/Storage")) } for _, p := range discovered.ChassisPaths { add(p) add(joinPath(p, "/Oem/Public")) add(joinPath(p, "/Oem/Public/FRU")) add(joinPath(p, "/PCIeDevices")) add(joinPath(p, "/PCIeSlots")) add(joinPath(p, "/NetworkAdapters")) add(joinPath(p, "/Drives")) add(joinPath(p, "/Power")) } for _, p := range discovered.ManagerPaths { add(p) add(joinPath(p, "/EthernetInterfaces")) add(joinPath(p, "/NetworkProtocol")) } return mergeResolvedPaths(out) } func baselineCriticalPaths(discovered DiscoveredResources) []string { var out []string for _, group := range [][]string{ {"/redfish/v1"}, discovered.SystemPaths, discovered.ChassisPaths, discovered.ManagerPaths, } { out = append(out, group...) } return mergeResolvedPaths(out) } func expandScopedSuffixes(basePaths, suffixes []string) []string { if len(basePaths) == 0 || len(suffixes) == 0 { return nil } out := make([]string, 0, len(basePaths)*len(suffixes)) for _, basePath := range basePaths { basePath = normalizePath(basePath) if basePath == "" { continue } for _, suffix := range suffixes { suffix = strings.TrimSpace(suffix) if suffix == "" { continue } out = append(out, joinPath(basePath, suffix)) } } return mergeResolvedPaths(out) } func mergeResolvedPaths(groups ...[]string) []string { seen := make(map[string]struct{}) out := make([]string, 0) for _, group := range groups { for _, path := range group { path = normalizePath(path) if path == "" { continue } if _, ok := seen[path]; ok { continue } seen[path] = struct{}{} out = append(out, path) } } return out } func normalizePath(path string) string { path = strings.TrimSpace(path) if path == "" { return "" } if !strings.HasPrefix(path, "/") { path = "/" + path } return strings.TrimRight(path, "/") } func joinPath(base, rel string) string { base = normalizePath(base) rel = strings.TrimSpace(rel) if base == "" { return normalizePath(rel) } if rel == "" { return base } if !strings.HasPrefix(rel, "/") { rel = "/" + rel } return normalizePath(base + rel) }