From cb351a9e8d9193690b4f55ea0a3c13a6d21defe0 Mon Sep 17 00:00:00 2001 From: Valeriy Khorunzhin Date: Tue, 16 Jun 2026 16:49:25 +0300 Subject: [PATCH] precheck Signed-off-by: Valeriy Khorunzhin --- test/e2e/internal/precheck/labels.go | 4 + .../e2e/internal/precheck/target_migration.go | 103 ++++++++++++++++++ test/e2e/vm/target_migration.go | 2 +- 3 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 test/e2e/internal/precheck/target_migration.go diff --git a/test/e2e/internal/precheck/labels.go b/test/e2e/internal/precheck/labels.go index 5d5bf6dbf4..394203d2a8 100644 --- a/test/e2e/internal/precheck/labels.go +++ b/test/e2e/internal/precheck/labels.go @@ -48,6 +48,9 @@ const ( // PrecheckAffinityToleration - test requires enough ready KVM-enabled master/worker nodes. PrecheckAffinityToleration = "affinity-toleration-precheck" + // PrecheckTargetMigration - test requires target migration feature to be available. + PrecheckTargetMigration = "target-migration-precheck" + // PrecheckPostCleanup - test requires postcleanup to be configured. PrecheckPostCleanup = "postcleanup-precheck" @@ -72,6 +75,7 @@ func KnownPrecheckLabels() []string { PrecheckVirtualization, PrecheckUSB, PrecheckAffinityToleration, + PrecheckTargetMigration, PrecheckPostCleanup, PrecheckPrecreatedCVI, NoPrecheck, diff --git a/test/e2e/internal/precheck/target_migration.go b/test/e2e/internal/precheck/target_migration.go new file mode 100644 index 0000000000..906cec5a29 --- /dev/null +++ b/test/e2e/internal/precheck/target_migration.go @@ -0,0 +1,103 @@ +/* +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" + "strings" + + . "github.com/onsi/ginkgo/v2" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/deckhouse/virtualization/api/core/v1alpha2" + "github.com/deckhouse/virtualization/test/e2e/internal/framework" +) + +const ( + targetMigrationPrecheckEnvName = "TARGET_MIGRATION_PRECHECK" + + targetMigrationFeatureName = "TargetMigration" + minReadyTargetMigrationWorkerNodes = 2 +) + +// targetMigrationPrecheck implements Precheck interface for VMOP target migration. +type targetMigrationPrecheck struct{} + +func (t *targetMigrationPrecheck) Label() string { + return PrecheckTargetMigration +} + +func (t *targetMigrationPrecheck) Run(ctx context.Context, f *framework.Framework) error { + if !isCheckEnabled(targetMigrationPrecheckEnvName) { + _, _ = GinkgoWriter.Write([]byte("Target migration precheck is disabled.\n")) + return nil + } + + if err := checkTargetMigrationFeature(ctx, f); err != nil { + return err + } + + workerNodes, err := listReadyNodesByLabels(ctx, f, map[string]string{ + kvmLabelKey: "true", + nodeGroupLabelKey: "worker", + }) + if err != nil { + return fmt.Errorf("%s=no to disable this precheck: failed to list ready KVM-enabled worker nodes: %w", targetMigrationPrecheckEnvName, err) + } + if len(workerNodes) < minReadyTargetMigrationWorkerNodes { + return fmt.Errorf("%s=no to disable this precheck: at least %d ready KVM-enabled worker nodes are required, got %d", targetMigrationPrecheckEnvName, minReadyTargetMigrationWorkerNodes, len(workerNodes)) + } + + return nil +} + +func checkTargetMigrationFeature(ctx context.Context, f *framework.Framework) error { + vmop := &v1alpha2.VirtualMachineOperation{ + ObjectMeta: metav1.ObjectMeta{ + Name: "target-migration-precheck", + Namespace: metav1.NamespaceDefault, + }, + Spec: v1alpha2.VirtualMachineOperationSpec{ + Type: v1alpha2.VMOPTypeMigrate, + VirtualMachine: "target-migration-precheck", + Migrate: &v1alpha2.VirtualMachineOperationMigrateSpec{ + NodeSelector: map[string]string{ + "kubernetes.io/hostname": "target-migration-precheck", + }, + }, + }, + } + + err := f.GenericClient().Create(ctx, vmop, &client.CreateOptions{ + DryRun: []string{metav1.DryRunAll}, + }) + if err == nil { + return nil + } + + if strings.Contains(err.Error(), "nodeSelector") { + return fmt.Errorf("%s=no to disable this precheck: %s feature should be enabled: %w", targetMigrationPrecheckEnvName, targetMigrationFeatureName, err) + } + + return fmt.Errorf("%s=no to disable this precheck: failed to check %s feature availability: %w", targetMigrationPrecheckEnvName, targetMigrationFeatureName, err) +} + +func init() { + RegisterPrecheck(&targetMigrationPrecheck{}, false) +} diff --git a/test/e2e/vm/target_migration.go b/test/e2e/vm/target_migration.go index a6b18bdf96..ba43b1f1c6 100644 --- a/test/e2e/vm/target_migration.go +++ b/test/e2e/vm/target_migration.go @@ -42,7 +42,7 @@ import ( const hostnameLabelKey = "kubernetes.io/hostname" -var _ = Describe("TargetMigration", Label(precheck.NoPrecheck), func() { +var _ = Describe("TargetMigration", Label(precheck.PrecheckTargetMigration), func() { var ( virtualMachine *v1alpha2.VirtualMachine targetMigrationVMOP *v1alpha2.VirtualMachineOperation