Skip to content

OCPBUGS-98217: fix(kubevirt): stop hardcoding evictionStrategy=External on KubeVirt VMs#8974

Open
tiraboschi wants to merge 1 commit into
openshift:mainfrom
tiraboschi:OCPBUGS-98217
Open

OCPBUGS-98217: fix(kubevirt): stop hardcoding evictionStrategy=External on KubeVirt VMs#8974
tiraboschi wants to merge 1 commit into
openshift:mainfrom
tiraboschi:OCPBUGS-98217

Conversation

@tiraboschi

@tiraboschi tiraboschi commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

What this PR does / why we need it:

PR #6380 unconditionally set evictionStrategy=External on all KubeVirt VMs created for HCP NodePools. This overrides the cluster-level default set by HCO (LiveMigrate on HA clusters), forcing CAPK to drain the guest node and delete the VMI on every infra node drain — even when the VM is live-migratable and KubeVirt could transparently migrate it with zero guest disruption.

With External strategy, KubeVirt's evacuation controller skips the VM entirely (VMIMigratableOnEviction returns false for External), so no live migration is ever attempted. Instead, CAPK cordons and drains the guest node, deletes the VMI, and KubeVirt recreates it on another host. This is a full disruption to all workloads on the guest node.

The External strategy is only appropriate for non-migratable VMs (e.g., with GPU passthrough or SR-IOV) where live migration is impossible and CAPK's drain-then-delete is the only graceful option. For the majority of VMs that are migratable, it is strictly worse than letting KubeVirt handle migration automatically via the cluster default.

This commit removes the hardcoded External strategy and adds an optional EvictionStrategy field to KubevirtNodePoolPlatform. When not set, the cluster-level KubeVirt default applies. Users with non-migratable VMs can explicitly opt into External when needed.

Which issue(s) this PR fixes:

Fixes https://redhat.atlassian.net/browse/OCPBUGS-98217

Special notes for your reviewer:

Exposing this to the user is probably not the smartest or more automated solution. On the other side trying to automate it would require changes on:

  • kubevirt
  • CAPK
  • here

Coordinating three releases.
So in terms of effectiveness this is definitively the low hanging fruit solution.

Checklist:

  • Subject and description added to both, commit and PR.
  • Relevant issues have been referenced.
  • This change includes docs.
  • This change includes unit tests.

Summary by CodeRabbit

  • New Features
    • Added a KubeVirt node pool evictionStrategy option with values: LiveMigrate, LiveMigrateIfPossible, External, and None.
  • Bug Fixes
    • Node templates no longer apply an eviction strategy unless it is explicitly set.
  • Documentation
    • Updated GPU passthrough node pool examples and added guidance on how each evictionStrategy affects VM eviction (including External vs None).
  • Tests
    • Added coverage for eviction strategy propagation and JSON serialization/deep-copy compatibility.

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: LGTM mode

@openshift-ci-robot openshift-ci-robot added jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. labels Jul 9, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@tiraboschi: This pull request references Jira Issue OCPBUGS-98217, which is invalid:

  • expected the bug to target the "5.0.0" version, but no target version was set

Comment /jira refresh to re-evaluate validity if changes to the Jira bug are made, or edit the title of this pull request to link to a different bug.

The bug has been updated to refer to the pull request using the external bug tracker.

Details

In response to this:

What this PR does / why we need it:

PR #6380 unconditionally set evictionStrategy=External on all KubeVirt VMs created for HCP NodePools. This overrides the cluster-level default set by HCO (LiveMigrate on HA clusters), forcing CAPK to drain the guest node and delete the VMI on every infra node drain — even when the VM is live-migratable and KubeVirt could transparently migrate it with zero guest disruption.

With External strategy, KubeVirt's evacuation controller skips the VM entirely (VMIMigratableOnEviction returns false for External), so no live migration is ever attempted. Instead, CAPK cordons and drains the guest node, deletes the VMI, and KubeVirt recreates it on another host. This is a full disruption to all workloads on the guest node.

The External strategy is only appropriate for non-migratable VMs (e.g., with GPU passthrough or SR-IOV) where live migration is impossible and CAPK's drain-then-delete is the only graceful option. For the majority of VMs that are migratable, it is strictly worse than letting KubeVirt handle migration automatically via the cluster default.

This commit removes the hardcoded External strategy and adds an optional EvictionStrategy field to KubevirtNodePoolPlatform. When not set, the cluster-level KubeVirt default applies. Users with non-migratable VMs can explicitly opt into External when needed.

Which issue(s) this PR fixes:

Fixes https://redhat.atlassian.net/browse/OCPBUGS-98217

Special notes for your reviewer:

Exposing this to the user is probably not the smartest or more automated solution. On the other side trying to automate it would require changes on:

  • kubevirt
  • CAPK
  • here
    Coordinating three releases.
    So in terms of effectiveness this is definitively the low hanging fruit solution.

Checklist:

  • Subject and description added to both, commit and PR.
  • Relevant issues have been referenced.
  • This change includes docs.
  • This change includes unit tests.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds a KubeVirt eviction strategy enum and an optional evictionStrategy field to the NodePool API. The controller now copies that field into generated virtual machine templates only when it is set. Tests cover JSON compatibility, enum handling, deep copy behavior, and template propagation. The GPU NodePool documentation was updated with the new field, example YAML, and supported values.

🚥 Pre-merge checks | ✅ 11
✅ Passed checks (11 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: removing the hardcoded External eviction strategy on KubeVirt VMs.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed No test titles contain runtime-generated data; the only interpolated subtest name uses fixed enum constants and all other names are static.
Test Structure And Quality ✅ Passed No Ginkgo/cluster-interaction tests were added; the new unit tests are table-driven, use explicit failure messages, and have no timeout/cleanup concerns.
Topology-Aware Scheduling Compatibility ✅ Passed Only adds optional KubeVirt evictionStrategy plumbing/docs; no new nodeSelector, affinity, spread, replica, or topology-dependent scheduling logic was introduced.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed Changed tests are plain Go unit tests, not Ginkgo e2e tests, and the new cases contain no IPv4-only parsing or external-network calls.
No-Weak-Crypto ✅ Passed Touched changes only add KubeVirt evictionStrategy API/docs/controller wiring and JSON/deepcopy tests; no weak crypto, custom crypto, or secret comparisons found.
Container-Privileges ✅ Passed The PR diff adds evictionStrategy API/docs/tests only; no added privileged, hostPID/hostNetwork, SYS_ADMIN, or allowPrivilegeEscalation settings appear.
No-Sensitive-Data-In-Logs ✅ Passed Touched files add enum/docs/tests and one control-flow change; no logger calls or sensitive data-bearing log output were added.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@tiraboschi tiraboschi changed the title OCPBUGS-98217: Stop hardcoding evictionStrategy=External on KubeVirt VMs OCPBUGS-98217: fix(kubevirt): stop hardcoding evictionStrategy=External on KubeVirt VMs Jul 9, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
docs/content/how-to/kubevirt/gpu-devices.md (1)

91-114: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor: cluster default also depends on node count.

The doc states the cluster-level default is "typically LiveMigrate on HA clusters managed by HCO," which is accurate for multi-node clusters, but KubeVirt/HCO defaults to None on single-node OpenShift. Worth a brief mention for completeness, though not essential for this PR's GPU-focused scope.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/content/how-to/kubevirt/gpu-devices.md` around lines 91 - 114, Update
the eviction strategy documentation in the GPU NodePools section to mention that
the cluster-level KubeVirt default is not always LiveMigrate; note the
single-node OpenShift case where the default is None. Keep the guidance anchored
around the evictionStrategy explanation and the supported values table, and add
a short clarifying sentence near the description of the default behavior.
api/hypershift/v1beta1/kubevirt.go (1)

194-210: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider a dedicated named type instead of raw *string.

NetworkInterfaceMultiQueue in this same struct uses a dedicated type (*MultiQueueSetting) for its enum. EvictionStrategy instead uses *string, which loses compile-time type safety and forces the controller to blindly cast kubevirtv1.EvictionStrategy(*kvPlatform.EvictionStrategy) without any type-level guarantee that the value belongs to the enum.

♻️ Suggested approach
+// KubevirtEvictionStrategy defines the eviction behavior for KubeVirt VMs.
+// +kubebuilder:validation:Enum=LiveMigrate;LiveMigrateIfPossible;External;None
+type KubevirtEvictionStrategy string
+
 	// +optional
-	// +kubebuilder:validation:Enum=LiveMigrate;LiveMigrateIfPossible;External;None
-	EvictionStrategy *string `json:"evictionStrategy,omitempty"`
+	EvictionStrategy *KubevirtEvictionStrategy `json:"evictionStrategy,omitempty"`
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/hypershift/v1beta1/kubevirt.go` around lines 194 - 210,
`EvictionStrategy` is modeled as a raw `*string`, which loses enum type safety
compared with `NetworkInterfaceMultiQueue`’s dedicated `*MultiQueueSetting`.
Update the `KubevirtPlatformSpec` field to use a named enum type for eviction
strategy, add the corresponding type definition and JSON/schema tags, and adjust
any controller/serialization code that currently casts
`*kvPlatform.EvictionStrategy` so it works directly with the typed value instead
of an unchecked string.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@api/hypershift/v1beta1/kubevirt.go`:
- Around line 194-210: `EvictionStrategy` is modeled as a raw `*string`, which
loses enum type safety compared with `NetworkInterfaceMultiQueue`’s dedicated
`*MultiQueueSetting`. Update the `KubevirtPlatformSpec` field to use a named
enum type for eviction strategy, add the corresponding type definition and
JSON/schema tags, and adjust any controller/serialization code that currently
casts `*kvPlatform.EvictionStrategy` so it works directly with the typed value
instead of an unchecked string.

In `@docs/content/how-to/kubevirt/gpu-devices.md`:
- Around line 91-114: Update the eviction strategy documentation in the GPU
NodePools section to mention that the cluster-level KubeVirt default is not
always LiveMigrate; note the single-node OpenShift case where the default is
None. Keep the guidance anchored around the evictionStrategy explanation and the
supported values table, and add a short clarifying sentence near the description
of the default behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 6e91eb64-982c-4bfc-9fc0-ac7182bb54b6

📥 Commits

Reviewing files that changed from the base of the PR and between 433a404 and c7959bb.

⛔ Files ignored due to path filters (3)
  • api/hypershift/v1beta1/zz_generated.deepcopy.go is excluded by !**/zz_generated*.go, !**/zz_generated*
  • vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/kubevirt.go is excluded by !vendor/**, !**/vendor/**
  • vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.go is excluded by !vendor/**, !**/vendor/**, !**/zz_generated*.go, !**/zz_generated*
📒 Files selected for processing (4)
  • api/hypershift/v1beta1/kubevirt.go
  • docs/content/how-to/kubevirt/gpu-devices.md
  • hypershift-operator/controllers/nodepool/kubevirt/kubevirt.go
  • hypershift-operator/controllers/nodepool/kubevirt/kubevirt_test.go

@openshift-ci openshift-ci Bot requested review from csrwng and nunnatsa July 9, 2026 16:19
@openshift-ci openshift-ci Bot added area/api Indicates the PR includes changes for the API area/documentation Indicates the PR includes changes for documentation labels Jul 9, 2026
@openshift-ci openshift-ci Bot added area/hypershift-operator Indicates the PR includes changes for the hypershift operator and API - outside an OCP release and removed do-not-merge/needs-area labels Jul 9, 2026
@openshift-ci

openshift-ci Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: tiraboschi
Once this PR has been reviewed and has the lgtm label, please assign sjenning for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci Bot added the area/platform/kubevirt PR/issue for KubeVirt (KubevirtPlatform) platform label Jul 9, 2026
@tiraboschi tiraboschi marked this pull request as draft July 9, 2026 16:21
@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jul 9, 2026
@tiraboschi

Copy link
Copy Markdown
Contributor Author

@coderabbitai please review again

@tiraboschi tiraboschi marked this pull request as ready for review July 9, 2026 16:26
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

@tiraboschi Sure, I'll review the PR again.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@openshift-ci openshift-ci Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jul 9, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
api/hypershift/v1beta1/kubevirt.go (1)

206-221: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

New optional field correctly modeled; consider adding a serialization compatibility test.

The pointer + omitempty choice correctly models "unset → cluster default" as a distinct valid state, and the enum values match the upstream KubeVirt EvictionStrategy type used by the controller cast. As per API module guidelines, when modifying API types you should add serialization compatibility tests verifying the field round-trips correctly between old/new struct versions (see api/hypershift/v1beta1/nodepool_types_test.go for the pattern). This isn't strictly required for a purely additive optional field, but would tighten N+1/N-1 guarantees for downstream vendors like ARO-HCP.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/hypershift/v1beta1/kubevirt.go` around lines 206 - 221, The new optional
EvictionStrategy field in KubevirtPlatformSpec should be covered by a
serialization compatibility test. Add a round-trip test in the same API test
pattern as nodepool_types_test.go that verifies the field stays unset when
omitted, preserves explicit enum values when set, and remains compatible across
old/new struct versions for KubevirtPlatformSpec and KubevirtEvictionStrategy.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@api/hypershift/v1beta1/kubevirt.go`:
- Around line 206-221: The new optional EvictionStrategy field in
KubevirtPlatformSpec should be covered by a serialization compatibility test.
Add a round-trip test in the same API test pattern as nodepool_types_test.go
that verifies the field stays unset when omitted, preserves explicit enum values
when set, and remains compatible across old/new struct versions for
KubevirtPlatformSpec and KubevirtEvictionStrategy.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: a12e764d-5960-41e3-a28d-aa42ebda7fcf

📥 Commits

Reviewing files that changed from the base of the PR and between c7959bb and 45f67d8.

⛔ Files ignored due to path filters (3)
  • api/hypershift/v1beta1/zz_generated.deepcopy.go is excluded by !**/zz_generated*.go, !**/zz_generated*
  • vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/kubevirt.go is excluded by !vendor/**, !**/vendor/**
  • vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.go is excluded by !vendor/**, !**/vendor/**, !**/zz_generated*.go, !**/zz_generated*
📒 Files selected for processing (4)
  • api/hypershift/v1beta1/kubevirt.go
  • docs/content/how-to/kubevirt/gpu-devices.md
  • hypershift-operator/controllers/nodepool/kubevirt/kubevirt.go
  • hypershift-operator/controllers/nodepool/kubevirt/kubevirt_test.go
✅ Files skipped from review due to trivial changes (1)
  • docs/content/how-to/kubevirt/gpu-devices.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • hypershift-operator/controllers/nodepool/kubevirt/kubevirt.go
  • hypershift-operator/controllers/nodepool/kubevirt/kubevirt_test.go

@openshift-ci openshift-ci Bot requested a review from orenc1 July 9, 2026 16:31
@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 43.60%. Comparing base (433a404) to head (d776b44).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #8974   +/-   ##
=======================================
  Coverage   43.60%   43.60%           
=======================================
  Files         771      771           
  Lines       95806    95809    +3     
=======================================
+ Hits        41778    41781    +3     
  Misses      51119    51119           
  Partials     2909     2909           
Files with missing lines Coverage Δ
...operator/controllers/nodepool/kubevirt/kubevirt.go 69.69% <100.00%> (+0.23%) ⬆️
Flag Coverage Δ
cmd-support 37.22% <ø> (ø)
cpo-hostedcontrolplane 45.91% <ø> (ø)
cpo-other 45.10% <ø> (ø)
hypershift-operator 53.66% <100.00%> (+<0.01%) ⬆️
other 32.08% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@openshift-ci openshift-ci Bot added the area/cli Indicates the PR includes changes for CLI label Jul 9, 2026
@hypershift-jira-solve-ci

Copy link
Copy Markdown
Contributor

The background agent for the lint job has completed and confirms the same findings I already included in the report above. Both agents' analyses are consistent with the root cause I identified:

  1. Lint failure: Single kubeapilinter violation — EvictionStrategy is declared as a pointer (*KubevirtEvictionStrategy) but the linter says it doesn't need to be, since the zero value ("") is not a valid enum member and already signals "not set."

  2. Verify failure: Three generated files (kubevirtnodepoolplatform.go apply-config, aggregated-docs.md, api.md) were not regenerated after adding the new field.

The full report with all details, recommendations, and evidence is in my previous message.


@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
api/hypershift/v1beta1/nodepool_types_test.go (1)

199-201: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Subtest names should follow "When ... it should ..." format.

t.Run(string(strategy), ...) produces subtest names like LiveMigrate, External, etc., which don't follow the required pattern used elsewhere in this file (e.g., TestKubevirtEvictionStrategySerializationCompatibility's subtests).

🔧 Proposed fix
-		t.Run(string(strategy), func(t *testing.T) {
+		t.Run(fmt.Sprintf("When EvictionStrategy is %s it should round-trip", strategy), func(t *testing.T) {

As per path instructions, **/*_test.go: "Always use "When ... it should ..." format for describing test cases when creating unit tests."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/hypershift/v1beta1/nodepool_types_test.go` around lines 199 - 201, The
subtest naming in the Kubevirt eviction strategy test is too generic and does
not match the required “When ... it should ...” style. Update the `t.Run` call
inside the loop over `expected` in
`TestKubevirtEvictionStrategySerializationCompatibility` to use a descriptive
scenario-based name that includes the strategy and expected behavior, consistent
with the other tests in `nodepool_types_test.go`. Ensure the generated subtest
names follow the “When ... it should ...” convention instead of raw values like
`LiveMigrate` or `External`.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@api/hypershift/v1beta1/nodepool_types_test.go`:
- Around line 199-201: The subtest naming in the Kubevirt eviction strategy test
is too generic and does not match the required “When ... it should ...” style.
Update the `t.Run` call inside the loop over `expected` in
`TestKubevirtEvictionStrategySerializationCompatibility` to use a descriptive
scenario-based name that includes the strategy and expected behavior, consistent
with the other tests in `nodepool_types_test.go`. Ensure the generated subtest
names follow the “When ... it should ...” convention instead of raw values like
`LiveMigrate` or `External`.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 94d6e027-49a3-448b-a613-b8a25c40d329

📥 Commits

Reviewing files that changed from the base of the PR and between c921ef5 and c4a6045.

⛔ Files ignored due to path filters (11)
  • api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/nodepools.hypershift.openshift.io/AAA_ungated.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/nodepools.hypershift.openshift.io/GCPPlatform.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/nodepools.hypershift.openshift.io/OSStreams.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/nodepools.hypershift.openshift.io/OpenStack.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • client/applyconfiguration/hypershift/v1beta1/kubevirtnodepoolplatform.go is excluded by !client/**
  • cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/nodepools-CustomNoUpgrade.crd.yaml is excluded by !**/zz_generated.crd-manifests/**, !cmd/install/assets/**/*.yaml
  • cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/nodepools-Default.crd.yaml is excluded by !**/zz_generated.crd-manifests/**, !cmd/install/assets/**/*.yaml
  • cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/nodepools-TechPreviewNoUpgrade.crd.yaml is excluded by !**/zz_generated.crd-manifests/**, !cmd/install/assets/**/*.yaml
  • docs/content/reference/aggregated-docs.md is excluded by !docs/content/reference/aggregated-docs.md
  • docs/content/reference/api.md is excluded by !docs/content/reference/api.md
  • vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/kubevirt.go is excluded by !vendor/**, !**/vendor/**
📒 Files selected for processing (5)
  • api/hypershift/v1beta1/kubevirt.go
  • api/hypershift/v1beta1/nodepool_types_test.go
  • docs/content/how-to/kubevirt/gpu-devices.md
  • hypershift-operator/controllers/nodepool/kubevirt/kubevirt.go
  • hypershift-operator/controllers/nodepool/kubevirt/kubevirt_test.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • api/hypershift/v1beta1/kubevirt.go
  • hypershift-operator/controllers/nodepool/kubevirt/kubevirt.go
  • docs/content/how-to/kubevirt/gpu-devices.md
  • hypershift-operator/controllers/nodepool/kubevirt/kubevirt_test.go

PR openshift#6380 unconditionally set evictionStrategy=External on all KubeVirt
VMs created for HCP NodePools. This overrides the cluster-level default
set by HCO (LiveMigrate on HA clusters), forcing CAPK to drain the
guest node and delete the VMI on every infra node drain — even when the
VM is live-migratable and KubeVirt could transparently migrate it with
zero guest disruption.

With External strategy, KubeVirt's evacuation controller skips the VM
entirely (VMIMigratableOnEviction returns false for External), so no
live migration is ever attempted. Instead, CAPK cordons and drains the
guest node, deletes the VMI, and KubeVirt recreates it on another host.
This is a full disruption to all workloads on the guest node.

The External strategy is only appropriate for non-migratable VMs (e.g.,
with GPU passthrough or SR-IOV) where live migration is impossible and
CAPK's drain-then-delete is the only graceful option. For the majority
of VMs that are migratable, it is strictly worse than letting KubeVirt
handle migration automatically via the cluster default.

This commit removes the hardcoded External strategy and adds an optional
EvictionStrategy field to KubevirtNodePoolPlatform. When not set, the
cluster-level KubeVirt default applies. Users with non-migratable VMs
can explicitly opt into External when needed.

Fixes: https://redhat.atlassian.net/browse/OCPBUGS-98217

Signed-off-by: Simone Tiraboschi <stirabos@redhat.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
api/hypershift/v1beta1/nodepool_types_test.go (1)

97-178: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider defining an explicit N-1 struct, mirroring the existing pattern.

TestNodePoolAutoScalingSerializationCompatibility above defines a nodePoolAutoScalingNMinus1 struct to model the previous API version explicitly. This new test instead simulates N-1 by deleting a key from a raw JSON map, which is functionally valid but diverges from the established pattern in this file and is slightly less explicit about what "N-1" actually looked like for this type.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/hypershift/v1beta1/nodepool_types_test.go` around lines 97 - 178, The N-1
compatibility part of TestKubevirtEvictionStrategySerializationCompatibility
should use an explicit previous-version struct instead of deleting
evictionStrategy from a raw JSON map. Add a
KubevirtNodePoolPlatformNMinus1-style type that mirrors the older API shape,
marshal that type for the N-1 case, and unmarshal into KubevirtNodePoolPlatform
to verify the zero-value behavior. Keep the existing round-trip checks for
KubevirtNodePoolPlatform and EvictionStrategy, but align the test with the
established pattern used by TestNodePoolAutoScalingSerializationCompatibility.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@api/hypershift/v1beta1/nodepool_types_test.go`:
- Around line 180-207: The subtest names in
TestKubevirtEvictionStrategyEnumValues do not follow the required “When...it
should...” convention. Update the t.Run label in this test to use a descriptive
sentence in that format, consistent with the other test cases in
nodepool_types_test.go, while keeping the existing enum round-trip assertions
unchanged.

---

Nitpick comments:
In `@api/hypershift/v1beta1/nodepool_types_test.go`:
- Around line 97-178: The N-1 compatibility part of
TestKubevirtEvictionStrategySerializationCompatibility should use an explicit
previous-version struct instead of deleting evictionStrategy from a raw JSON
map. Add a KubevirtNodePoolPlatformNMinus1-style type that mirrors the older API
shape, marshal that type for the N-1 case, and unmarshal into
KubevirtNodePoolPlatform to verify the zero-value behavior. Keep the existing
round-trip checks for KubevirtNodePoolPlatform and EvictionStrategy, but align
the test with the established pattern used by
TestNodePoolAutoScalingSerializationCompatibility.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: be6655b1-7711-4806-9fe8-bf74a68f5fe0

📥 Commits

Reviewing files that changed from the base of the PR and between c4a6045 and 430cff4.

⛔ Files ignored due to path filters (11)
  • api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/nodepools.hypershift.openshift.io/AAA_ungated.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/nodepools.hypershift.openshift.io/GCPPlatform.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/nodepools.hypershift.openshift.io/OSStreams.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/nodepools.hypershift.openshift.io/OpenStack.yaml is excluded by !**/zz_generated.featuregated-crd-manifests/**
  • client/applyconfiguration/hypershift/v1beta1/kubevirtnodepoolplatform.go is excluded by !client/**
  • cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/nodepools-CustomNoUpgrade.crd.yaml is excluded by !**/zz_generated.crd-manifests/**, !cmd/install/assets/**/*.yaml
  • cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/nodepools-Default.crd.yaml is excluded by !**/zz_generated.crd-manifests/**, !cmd/install/assets/**/*.yaml
  • cmd/install/assets/crds/hypershift-operator/zz_generated.crd-manifests/nodepools-TechPreviewNoUpgrade.crd.yaml is excluded by !**/zz_generated.crd-manifests/**, !cmd/install/assets/**/*.yaml
  • docs/content/reference/aggregated-docs.md is excluded by !docs/content/reference/aggregated-docs.md
  • docs/content/reference/api.md is excluded by !docs/content/reference/api.md
  • vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/kubevirt.go is excluded by !vendor/**, !**/vendor/**
📒 Files selected for processing (5)
  • api/hypershift/v1beta1/kubevirt.go
  • api/hypershift/v1beta1/nodepool_types_test.go
  • docs/content/how-to/kubevirt/gpu-devices.md
  • hypershift-operator/controllers/nodepool/kubevirt/kubevirt.go
  • hypershift-operator/controllers/nodepool/kubevirt/kubevirt_test.go
✅ Files skipped from review due to trivial changes (1)
  • docs/content/how-to/kubevirt/gpu-devices.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • api/hypershift/v1beta1/kubevirt.go
  • hypershift-operator/controllers/nodepool/kubevirt/kubevirt.go
  • hypershift-operator/controllers/nodepool/kubevirt/kubevirt_test.go

Comment thread api/hypershift/v1beta1/nodepool_types_test.go
@openshift-ci

openshift-ci Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

@tiraboschi: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/api Indicates the PR includes changes for the API area/cli Indicates the PR includes changes for CLI area/documentation Indicates the PR includes changes for documentation area/hypershift-operator Indicates the PR includes changes for the hypershift operator and API - outside an OCP release area/platform/kubevirt PR/issue for KubeVirt (KubevirtPlatform) platform jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants