diff --git a/test/e2e/internal/framework/mc.go b/test/e2e/internal/framework/mc.go index eeb66d35a9..d68babf65f 100644 --- a/test/e2e/internal/framework/mc.go +++ b/test/e2e/internal/framework/mc.go @@ -71,6 +71,7 @@ type VirtualizationModuleConfigSettings struct { VirtualMachineCIDRs []string `json:"virtualMachineCIDRs"` Dvcr Dvcr `json:"dvcr"` HighAvailability bool `json:"highAvailability,omitempty"` + FeatureGates []string `json:"featureGates,omitempty"` } type Dvcr struct { diff --git a/test/e2e/internal/precheck/hotplug_featuregates.go b/test/e2e/internal/precheck/hotplug_featuregates.go new file mode 100644 index 0000000000..199a563849 --- /dev/null +++ b/test/e2e/internal/precheck/hotplug_featuregates.go @@ -0,0 +1,86 @@ +/* +Copyright 2026 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package precheck + +import ( + "context" + "fmt" + + . "github.com/onsi/ginkgo/v2" + + "github.com/deckhouse/virtualization/test/e2e/internal/framework" +) + +const ( + hotplugCPUPrecheckEnvName = "HOTPLUG_CPU_PRECHECK" + hotplugMemoryPrecheckEnvName = "HOTPLUG_MEMORY_PRECHECK" + + hotplugCPUWithLiveMigration = "HotplugCPUWithLiveMigration" + hotplugMemoryWithLiveMigration = "HotplugMemoryWithLiveMigration" +) + +type moduleConfigFeatureGatePrecheck struct { + label string + envName string + featureGate string +} + +func (p *moduleConfigFeatureGatePrecheck) Label() string { + return p.label +} + +func (p *moduleConfigFeatureGatePrecheck) Run(ctx context.Context, f *framework.Framework) error { + if !isCheckEnabled(p.envName) { + GinkgoWriter.Printf("%s check is disabled.\n", p.featureGate) + return nil + } + + moduleConfig, err := f.GetVirtualizationModuleConfig(ctx) + if err != nil { + return fmt.Errorf("%s=no to disable this precheck: failed to get ModuleConfig/%s: %w", p.envName, virtualizationModuleName, err) + } + + featureGates := moduleConfig.Spec.Settings.FeatureGates + hasFeatureGate := false + for _, fg := range featureGates { + if fg == p.featureGate { + hasFeatureGate = true + break + } + } + + if !hasFeatureGate { + return fmt.Errorf("%s=no to disable this precheck: ModuleConfig/%s does not contain %q in .spec.settings.featureGates", + p.envName, p.featureGate, virtualizationModuleName) + } + + return nil +} + +func init() { + RegisterPrecheck(&moduleConfigFeatureGatePrecheck{ + label: PrecheckHotplugCPU, + envName: hotplugCPUPrecheckEnvName, + featureGate: hotplugCPUWithLiveMigration, + }, false) + + RegisterPrecheck(&moduleConfigFeatureGatePrecheck{ + label: PrecheckHotplugMemory, + envName: hotplugMemoryPrecheckEnvName, + featureGate: hotplugMemoryWithLiveMigration, + }, false) +} diff --git a/test/e2e/internal/precheck/labels.go b/test/e2e/internal/precheck/labels.go index 5d5bf6dbf4..9d20c89122 100644 --- a/test/e2e/internal/precheck/labels.go +++ b/test/e2e/internal/precheck/labels.go @@ -45,6 +45,12 @@ const ( // PrecheckUSB - test requires USB device with dummy_hcd to be configured. PrecheckUSB = "usb-precheck" + // PrecheckHotplugCPU - test requires HotplugCPUWithLiveMigration feature gate to be enabled in ModuleConfig/virtualization. + PrecheckHotplugCPU = "hotplug-cpu-precheck" + + // PrecheckHotplugMemory - test requires HotplugMemoryWithLiveMigration feature gate to be enabled in ModuleConfig/virtualization. + PrecheckHotplugMemory = "hotplug-memory-precheck" + // PrecheckAffinityToleration - test requires enough ready KVM-enabled master/worker nodes. PrecheckAffinityToleration = "affinity-toleration-precheck" @@ -71,6 +77,8 @@ func KnownPrecheckLabels() []string { PrecheckSnapshot, PrecheckVirtualization, PrecheckUSB, + PrecheckHotplugCPU, + PrecheckHotplugMemory, PrecheckAffinityToleration, PrecheckPostCleanup, PrecheckPrecreatedCVI, diff --git a/test/e2e/vm/hotplug_cpu.go b/test/e2e/vm/hotplug_cpu.go index 426b484ce4..390f741004 100644 --- a/test/e2e/vm/hotplug_cpu.go +++ b/test/e2e/vm/hotplug_cpu.go @@ -38,14 +38,13 @@ import ( "github.com/deckhouse/virtualization/test/e2e/internal/util" ) -var _ = Describe("HotplugCPU", Label(precheck.NoPrecheck), func() { +var _ = Describe("HotplugCPU", Label(precheck.PrecheckHotplugCPU), func() { var ( f *framework.Framework t *cpuHotplugTest ) BeforeEach(func() { - Skip("Hotplug CPU requires enabled feature gates in ModuleConfig. Skip until prechecks are implemented.") f = framework.NewFramework("cpu-hotplug") DeferCleanup(f.After) f.Before() diff --git a/test/e2e/vm/hotplug_memory.go b/test/e2e/vm/hotplug_memory.go index 190b7637d1..355f1d458b 100644 --- a/test/e2e/vm/hotplug_memory.go +++ b/test/e2e/vm/hotplug_memory.go @@ -40,14 +40,13 @@ import ( "github.com/deckhouse/virtualization/test/e2e/internal/util" ) -var _ = Describe("HotplugMemory", Label(precheck.NoPrecheck), func() { +var _ = Describe("HotplugMemory", Label(precheck.PrecheckHotplugMemory), func() { var ( f *framework.Framework t *memoryHotplugTest ) BeforeEach(func() { - Skip("Hotplug memory requires enabling feature gate 'HotplugMemoryWithLiveMigration' in ModuleConfig. Skip until prechecks are implemented.") f = framework.NewFramework("memory-hotplug") DeferCleanup(f.After) f.Before()