From bc2dcb1570749de56923006095dc420a3ec38975 Mon Sep 17 00:00:00 2001 From: Shay Bratslavsky Date: Thu, 7 May 2026 12:04:18 +0300 Subject: [PATCH] MGMT-24155: Replace LSO with LVM as CNV operator dependency for all supported configurations --- internal/operators/cnv/cnv_operator.go | 26 +++---- internal/operators/cnv/cnv_operator_test.go | 83 ++++++++++++++------- 2 files changed, 68 insertions(+), 41 deletions(-) diff --git a/internal/operators/cnv/cnv_operator.go b/internal/operators/cnv/cnv_operator.go index 8fb19f52e5b4..d9dc74a58b7e 100644 --- a/internal/operators/cnv/cnv_operator.go +++ b/internal/operators/cnv/cnv_operator.go @@ -67,30 +67,30 @@ func (o *operator) GetFullName() string { // GetDependencies provides a list of dependencies of the Operator func (o *operator) GetDependencies(cluster *common.Cluster) ([]string, error) { - lsoOperator := []string{lso.Operator.Name} - lvmOperator := []string{lvm.Operator.Name} - - // Disable lso for ARM deployment as it's not supported - // to allow CNV ARM operator - if cluster.CPUArchitecture == common.ARM64CPUArchitecture || cluster.CPUArchitecture == common.MultiCPUArchitecture { - return make([]string, 0), nil + if !featuresupport.IsFeatureCompatibleWithArchitecture(models.FeatureSupportLevelIDLVM, cluster.OpenshiftVersion, cluster.CPUArchitecture) { + return []string{}, nil } if cluster.OpenshiftVersion == "" { - return lsoOperator, nil + return []string{lvm.Operator.Name}, nil } - // SNO if common.IsSingleNodeCluster(cluster) { - if isGreaterOrEqual, _ := common.BaseVersionGreaterOrEqual(lvm.LvmsMinOpenshiftVersion4_12, cluster.OpenshiftVersion); isGreaterOrEqual { - return lvmOperator, nil + if isSupported, _ := common.BaseVersionGreaterOrEqual(lvm.LvmsMinOpenshiftVersion4_12, cluster.OpenshiftVersion); isSupported { + return []string{lvm.Operator.Name}, nil } + return []string{lso.Operator.Name}, nil + } + + if isSupported, _ := common.BaseVersionGreaterOrEqual(lvm.LvmMinMultiNodeSupportVersion, cluster.OpenshiftVersion); isSupported { + return []string{lvm.Operator.Name}, nil } - return lsoOperator, nil + + return []string{lso.Operator.Name}, nil } func (o *operator) GetDependenciesFeatureSupportID() []models.FeatureSupportLevelID { - return []models.FeatureSupportLevelID{models.FeatureSupportLevelIDLSO, models.FeatureSupportLevelIDLVM} + return []models.FeatureSupportLevelID{models.FeatureSupportLevelIDLVM} } // GetClusterValidationIDs returns cluster validation IDs for the Operator diff --git a/internal/operators/cnv/cnv_operator_test.go b/internal/operators/cnv/cnv_operator_test.go index 4dbd5e5a0d25..ae62462625f3 100644 --- a/internal/operators/cnv/cnv_operator_test.go +++ b/internal/operators/cnv/cnv_operator_test.go @@ -37,23 +37,43 @@ var _ = Describe("CNV operator", func() { operator = cnv.NewCNVOperator(log, cfg) }) - DescribeTable("getDependencies", func(ocpVersion string, haMode int64, expectedOperator string) { - cluster := common.Cluster{ - Cluster: models.Cluster{ControlPlaneCount: haMode, OpenshiftVersion: ocpVersion}, - } - - requirements, err := operator.GetDependencies(&cluster) - Expect(err).ToNot(HaveOccurred()) - Expect(requirements).ToNot(BeNil()) - - Expect(requirements[0]).To(BeEquivalentTo(expectedOperator)) - }, + DescribeTable("getDependencies", + func(ocpVersion string, cpuArch string, haMode int64, expectedDeps []string) { + cluster := common.Cluster{ + Cluster: models.Cluster{ + ControlPlaneCount: haMode, + OpenshiftVersion: ocpVersion, + CPUArchitecture: cpuArch, + }, + } - Entry("LVM, Single node 4.12", "4.12", int64(1), lvm.Operator.Name), - Entry("LSO, Multi node 4.15", "4.15", int64(common.MinMasterHostsNeededForInstallationInHaMode), lso.Operator.Name), - Entry("LSO, Multi node 4.21", "4.21", int64(common.MinMasterHostsNeededForInstallationInHaMode), lso.Operator.Name), - Entry("LSO, Multi node 4.12", "4.12", int64(common.MinMasterHostsNeededForInstallationInHaMode), lso.Operator.Name), - Entry("LSO, Single node 4.11", "4.11", int64(1), lso.Operator.Name), + deps, err := operator.GetDependencies(&cluster) + Expect(err).ToNot(HaveOccurred()) + Expect(deps).To(Equal(expectedDeps)) + }, + // SNO: LVM from 4.12+, LSO fallback for older + Entry("LVM, Single node 4.12", "4.12", common.DefaultCPUArchitecture, int64(1), []string{lvm.Operator.Name}), + Entry("LVM, Single node 4.15", "4.15", common.DefaultCPUArchitecture, int64(1), []string{lvm.Operator.Name}), + Entry("LSO, Single node 4.11", "4.11", common.DefaultCPUArchitecture, int64(1), []string{lso.Operator.Name}), + Entry("LSO, Single node 4.10", "4.10", common.DefaultCPUArchitecture, int64(1), []string{lso.Operator.Name}), + + // Multi-node: LVM from 4.15+, LSO fallback for older + Entry("LVM, Multi node 4.15", "4.15", common.DefaultCPUArchitecture, int64(common.MinMasterHostsNeededForInstallationInHaMode), []string{lvm.Operator.Name}), + Entry("LVM, Multi node 4.21", "4.21", common.DefaultCPUArchitecture, int64(common.MinMasterHostsNeededForInstallationInHaMode), []string{lvm.Operator.Name}), + Entry("LSO, Multi node 4.14", "4.14", common.DefaultCPUArchitecture, int64(common.MinMasterHostsNeededForInstallationInHaMode), []string{lso.Operator.Name}), + Entry("LSO, Multi node 4.12", "4.12", common.DefaultCPUArchitecture, int64(common.MinMasterHostsNeededForInstallationInHaMode), []string{lso.Operator.Name}), + + // Unsupported architectures: no deps regardless of version + Entry("No deps, s390x architecture", "4.15", common.S390xCPUArchitecture, int64(1), []string{}), + Entry("No deps, ppc64le architecture", "4.15", common.PowerCPUArchitecture, int64(1), []string{}), + + // ARM64 and multi-arch: LVM is supported + Entry("LVM, ARM64 SNO 4.15", "4.15", common.ARM64CPUArchitecture, int64(1), []string{lvm.Operator.Name}), + Entry("LVM, ARM64 Multi node 4.15", "4.15", common.ARM64CPUArchitecture, int64(common.MinMasterHostsNeededForInstallationInHaMode), []string{lvm.Operator.Name}), + Entry("LVM, Multi arch Multi node 4.15", "4.15", common.MultiCPUArchitecture, int64(common.MinMasterHostsNeededForInstallationInHaMode), []string{lvm.Operator.Name}), + + // Empty OCP version defaults to LVM + Entry("LVM, empty OCP version", "", common.DefaultCPUArchitecture, int64(1), []string{lvm.Operator.Name}), ) Context("host requirements", func() { @@ -297,18 +317,17 @@ var _ = Describe("CNV operator", func() { ) }) - DescribeTable("GetPreflightRequirements, should be returned", func(cfg cnv.Config, cluster common.Cluster) { + DescribeTable("GetPreflightRequirements, should be returned", func(cfg cnv.Config, cluster common.Cluster, expectedDeps []string) { cnvOperator := cnv.NewCNVOperator(log, cfg) requirements, err := cnvOperator.GetPreflightRequirements(context.TODO(), &cluster) Expect(err).ToNot(HaveOccurred()) - Expect(requirements.Dependencies).To(ConsistOf(lso.Operator.Name)) + Expect(requirements.Dependencies).To(Equal(expectedDeps)) Expect(requirements.OperatorName).To(BeEquivalentTo(cnv.Operator.Name)) numQualitative := 3 workerRequirements := newRequirements(cnv.WorkerCPU, cnv.WorkerMemory) masterRequirements := newRequirements(cnv.MasterCPU, cnv.MasterMemory) if common.IsSingleNodeCluster(&cluster) { - // CNV+SNO installs HPP storage; additional discoverable disk req if cfg.SNOInstallHPP { numQualitative += 1 } @@ -321,18 +340,26 @@ var _ = Describe("CNV operator", func() { Expect(requirements.Requirements.Master.Quantitative).To(BeEquivalentTo(masterRequirements)) Expect(requirements.Requirements.Master.Qualitative).To(BeEquivalentTo(requirements.Requirements.Worker.Qualitative)) }, - Entry("for non-SNO", cnv.Config{SNOPoolSizeRequestHPPGib: 50}, common.Cluster{Cluster: models.Cluster{ - OpenshiftVersion: "4.10", + Entry("for non-SNO 4.15", cnv.Config{SNOPoolSizeRequestHPPGib: 50}, common.Cluster{Cluster: models.Cluster{ + OpenshiftVersion: "4.15", ControlPlaneCount: common.MinMasterHostsNeededForInstallationInHaMode, - }}), - Entry("for SNO", cnv.Config{SNOPoolSizeRequestHPPGib: 50, SNOInstallHPP: true}, common.Cluster{Cluster: models.Cluster{ - OpenshiftVersion: "4.10", + }}, []string{lvm.Operator.Name}), + Entry("for SNO 4.12", cnv.Config{SNOPoolSizeRequestHPPGib: 50}, common.Cluster{Cluster: models.Cluster{ + OpenshiftVersion: "4.12", ControlPlaneCount: sno, - }}), - Entry("for SNO and opt out of HPP via env var", cnv.Config{SNOPoolSizeRequestHPPGib: 50, SNOInstallHPP: false}, common.Cluster{Cluster: models.Cluster{ - OpenshiftVersion: "4.10", + }}, []string{lvm.Operator.Name}), + Entry("for SNO 4.11 with HPP", cnv.Config{SNOPoolSizeRequestHPPGib: 50, SNOInstallHPP: true}, common.Cluster{Cluster: models.Cluster{ + OpenshiftVersion: "4.11", ControlPlaneCount: sno, - }}), + }}, []string{lso.Operator.Name}), + Entry("for SNO 4.11 opt out HPP", cnv.Config{SNOPoolSizeRequestHPPGib: 50, SNOInstallHPP: false}, common.Cluster{Cluster: models.Cluster{ + OpenshiftVersion: "4.11", + ControlPlaneCount: sno, + }}, []string{lso.Operator.Name}), + Entry("for multi-node OCP < 4.15 with LSO fallback", cnv.Config{SNOPoolSizeRequestHPPGib: 50}, common.Cluster{Cluster: models.Cluster{ + OpenshiftVersion: "4.14", + ControlPlaneCount: common.MinMasterHostsNeededForInstallationInHaMode, + }}, []string{lso.Operator.Name}), ) DescribeTable("Validate Cluster", func(ocpVersion []string, cpuArch string, expectedApiStatus api.ValidationStatus, errorMessage string) {