Skip to content

OCPBUGS-109196: fix(nodepool): validate KubeVirt additionalNetworks NAD namespace - #9299

Open
chdeshpa-hue wants to merge 2 commits into
openshift:mainfrom
chdeshpa-hue:OCPBUGS-109196-kubevirt-nad-namespace-validation
Open

OCPBUGS-109196: fix(nodepool): validate KubeVirt additionalNetworks NAD namespace#9299
chdeshpa-hue wants to merge 2 commits into
openshift:mainfrom
chdeshpa-hue:OCPBUGS-109196-kubevirt-nad-namespace-validation

Conversation

@chdeshpa-hue

@chdeshpa-hue chdeshpa-hue commented Aug 13, 2026

Copy link
Copy Markdown

Summary

  • Adds KubeVirt platform validation to validPlatformConfigCondition that checks additionalNetworks NAD namespace against the resolved virt-launcher pod namespace
  • On mismatch, sets ValidPlatformConfig=False with an actionable message telling users where to create the NAD
  • Documents the namespace requirement in the KubeVirt networking how-to guide

Problem

NodePool.spec.platform.kubevirt.additionalNetworks accepts NAD references passed verbatim to Multus via MultusNetwork.NetworkName. Users naturally place NADs in the HostedCluster namespace, but virt-launcher pods run in the HCP namespace ({hc-ns}-{hc-name}). With Multus namespace isolation enabled (OCP default), the cross-namespace reference is rejected — but the only signal is an opaque pod sandbox error buried in virt-launcher events.

Fix

Mirrors the existing AWS platform validation pattern:

case hyperv1.KubevirtPlatform:
    if err := r.validateKubevirtAdditionalNetworkNamespaces(nodePool, hc); err != nil {
        condition.Status = corev1.ConditionFalse
        condition.Reason = hyperv1.NodePoolValidationFailedReason
        condition.Message = err.Error()
    }

The validation resolves the target namespace (HCP ns or Credentials.InfraNamespace) and checks each additionalNetworks entry's namespace portion.

Why not CEL / admission-time validation

This check stays controller-time on purpose. The allowed NAD namespace is the virt-launcher namespace, which comes from the HostedCluster (HostedControlPlaneNamespace / Credentials.InfraNamespace). A NodePool CEL rule cannot see that cross-object data.

The issue's Expected Result asked for an immediate (admission) reject. This PR uses ValidPlatformConfig=False instead — asynchronous, informational, and aligned with the Proposed Fix and the existing AWS platform-validation pattern. There is no admission webhook in this change.

Upgrade note

After this lands, KubeVirt NodePools whose additionalNetworks NAD is not in the virt-launcher namespace (HCP/infra) or default will report ValidPlatformConfig=False. Reconcile is not blocked and VMs are still created.

On OpenShift with default Multus isolation this matches real Multus rejection. If namespace isolation is disabled (or the management cluster is not OpenShift), the condition can be a false positive for monitoring.

Test plan

  • 9 unit test cases covering: HCP namespace match, default namespace, external infra, HC namespace mismatch, dots in name, bare names, empty networks, multi-network mix
  • CI: ci/prow/unit, ci/prow/verify, ci/prow/lint

Verification output

$ git diff --stat origin/main
 docs/content/how-to/kubevirt/configuring-network.md | 25 +-
 hypershift-operator/controllers/nodepool/conditions.go | 45 ++++
 hypershift-operator/controllers/nodepool/conditions_test.go | 280 +++++++++++++++++++++
 3 files changed, 349 insertions(+), 1 deletion(-)

/jira OCPBUGS-109196

Made with Cursor

Summary by CodeRabbit

  • Bug Fixes

    • Added validation for KubeVirt additional network namespaces.
    • Network definitions must now be located in the appropriate HCP infrastructure namespace or the default namespace.
    • Invalid namespace configurations are reported clearly and prevent the platform configuration from being marked valid.
    • Improved handling of valid and invalid network namespace combinations.
  • Documentation

    • Clarified NetworkAttachmentDefinition placement, namespace naming, and commands for identifying the correct namespace.

@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 Aug 13, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@chdeshpa-hue: This pull request references Jira Issue OCPBUGS-109196, 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:

Summary

  • Adds KubeVirt platform validation to validPlatformConfigCondition that checks additionalNetworks NAD namespace against the resolved virt-launcher pod namespace
  • On mismatch, sets ValidPlatformConfig=False with an actionable message telling users where to create the NAD
  • Documents the namespace requirement in the KubeVirt networking how-to guide

Problem

NodePool.spec.platform.kubevirt.additionalNetworks accepts NAD references passed verbatim to Multus via MultusNetwork.NetworkName. Users naturally place NADs in the HostedCluster namespace, but virt-launcher pods run in the HCP namespace ({hc-ns}-{hc-name}). With Multus namespace isolation enabled (OCP default), the cross-namespace reference is rejected — but the only signal is an opaque pod sandbox error buried in virt-launcher events.

Fix

Mirrors the existing AWS platform validation pattern:

case hyperv1.KubevirtPlatform:
   if err := r.validateKubevirtAdditionalNetworkNamespaces(nodePool, hc); err != nil {
       condition.Status = corev1.ConditionFalse
       condition.Reason = hyperv1.NodePoolValidationFailedReason
       condition.Message = err.Error()
   }

The validation resolves the target namespace (HCP ns or Credentials.InfraNamespace) and checks each additionalNetworks entry's namespace portion.

Test plan

  • 9 unit test cases covering: HCP namespace match, default namespace, external infra, HC namespace mismatch, dots in name, bare names, empty networks, multi-network mix
  • CI: ci/prow/unit, ci/prow/verify, ci/prow/lint

Verification output

$ git diff --stat origin/main
docs/content/how-to/kubevirt/configuring-network.md | 25 +-
hypershift-operator/controllers/nodepool/conditions.go | 45 ++++
hypershift-operator/controllers/nodepool/conditions_test.go | 280 +++++++++++++++++++++
3 files changed, 349 insertions(+), 1 deletion(-)

/jira OCPBUGS-109196

Made with Cursor

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 Aug 13, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Pro Plus

Run ID: ec523813-303f-441e-88de-b8b21fa19020

📥 Commits

Reviewing files that changed from the base of the PR and between e6cefe8 and ffc16da.

📒 Files selected for processing (1)
  • hypershift-operator/controllers/nodepool/conditions.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • hypershift-operator/controllers/nodepool/conditions.go

Included review availability: Your plan includes up to 4 reviews per rolling hour; 3 remain after this review.


📝 Walkthrough

Walkthrough

The documentation defines the required namespace for namespaced NetworkAttachmentDefinitions. KubeVirt validation accepts the virt-launcher infrastructure namespace and default, ignores unqualified names, and marks ValidPlatformConfig false for other namespaces. Tests cover centralized and external infrastructure, derived namespaces, valid and invalid references, empty networks, mixed entries, and error messages.


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
No-Sensitive-Data-In-Logs ❓ Inconclusive Need determine whether the new condition error is emitted to logs and whether namespace or NAD names are treated as sensitive data. Confirm the runtime path for ValidPlatformConfig.Message and classify these Kubernetes names under the check.
✅ Passed checks (10 passed)
Check name Status Explanation
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 The added subtest titles are fixed string literals, and t.Run only consumes those literals; no timestamps, generated identifiers, namespaces with random suffixes, IPs, or other run-varying values a...
Test Structure And Quality ✅ Passed The added test is a standard testing.T table-driven unit test, not Ginkgo. It creates no cluster resources, uses no waits, follows local t.Run/NewWithT patterns, and supplies case-name messages.
Topology-Aware Scheduling Compatibility ✅ Passed The diff adds KubeVirt NAD namespace validation, tests, and documentation. It adds no affinity, topology spread, replica, node selector, toleration, or PDB scheduling constraints.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed The added tests are standard Go table-driven unit tests using Test..., t.Run, and NewWithT; the exact diff adds no Ginkgo APIs, IPv4 assumptions, or external connectivity.
No-Weak-Crypto ✅ Passed The complete feature-range diff adds namespace validation, documentation, and tests; searches found no MD5, SHA1, DES, RC4, Blowfish, ECB, custom crypto, or secret-comparison usage.
Container-Privileges ✅ Passed The diff changes documentation, namespace validation, and tests only; no added privileged, hostPID, hostNetwork, hostIPC, SYS_ADMIN, root, or allowPrivilegeEscalation configuration appears.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the KubeVirt node pool validation change for additionalNetworks NAD namespaces.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@openshift-ci openshift-ci Bot added 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 and removed do-not-merge/needs-area labels Aug 13, 2026
@openshift-ci
openshift-ci Bot requested review from bryan-cox and jparrill August 13, 2026 08:38
@openshift-ci

openshift-ci Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: chdeshpa-hue
Once this PR has been reviewed and has the lgtm label, please assign bryan-cox 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

@github-actions
github-actions Bot temporarily deployed to docs-preview/pr-9299 August 13, 2026 08:39 Inactive
@chdeshpa-hue

Copy link
Copy Markdown
Author

/jira refreshed

@codecov

codecov Bot commented Aug 13, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 81.81818% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 45.74%. Comparing base (d32a262) to head (e6cefe8).
⚠️ Report is 46 commits behind head on main.

⚠️ Current head e6cefe8 differs from pull request most recent head ffc16da

Please upload reports for the commit ffc16da to get more accurate results.

Files with missing lines Patch % Lines
...rshift-operator/controllers/nodepool/conditions.go 81.81% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9299      +/-   ##
==========================================
+ Coverage   45.73%   45.74%   +0.01%     
==========================================
  Files         781      781              
  Lines       97828    97861      +33     
==========================================
+ Hits        44738    44765      +27     
- Misses      50019    50025       +6     
  Partials     3071     3071              
Files with missing lines Coverage Δ
...rshift-operator/controllers/nodepool/conditions.go 60.67% <81.81%> (+0.78%) ⬆️
Flag Coverage Δ
cmd-support 38.79% <ø> (ø)
cpo-hostedcontrolplane 48.08% <ø> (ø)
cpo-other 45.93% <ø> (ø)
hypershift-operator 57.00% <81.81%> (+0.03%) ⬆️
other 34.38% <ø> (ø)

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.

With Multus namespace isolation enabled (OpenShift default),
virt-launcher pods can only reference NetworkAttachmentDefinitions in
their own namespace or "default". Users naturally place NADs in the
HostedCluster namespace, but virt-launcher runs in the HCP namespace.

Add validation in validPlatformConfigCondition that checks the NAD
namespace in each additionalNetworks entry against the resolved
virt-launcher namespace. On mismatch, set ValidPlatformConfig=False
with an actionable message telling the user the correct namespace.

Also documents the namespace requirement in the KubeVirt networking
how-to guide.

Co-authored-by: Cursor <cursoragent@cursor.com>
@chdeshpa-hue
chdeshpa-hue force-pushed the OCPBUGS-109196-kubevirt-nad-namespace-validation branch from bbcfd7b to e6cefe8 Compare August 13, 2026 09:17
@chdeshpa-hue chdeshpa-hue changed the title OCPBUGS-109196: validate KubeVirt additionalNetworks NAD namespace OCPBUGS-109196: fix(nodepool): validate KubeVirt additionalNetworks NAD namespace Aug 13, 2026
@github-actions
github-actions Bot temporarily deployed to docs-preview/pr-9299 August 13, 2026 09:23 Inactive

@bryan-cox bryan-cox left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Two-axis review (Standards + Spec) of e6cefe830a against main.

Solid, well-tested fix that maps cleanly onto the OCPBUGS-109196 proposed fix — the namespace resolution (HCP ns with dot→hyphen, Credentials.InfraNamespace override for external infra) and the actionable error message are correct, and the 9 table-test cases match the described scenarios. Two things worth a look before merge:

Standards

  1. (discussion, not blocking) This adds controller-time validation where api/AGENTS.md steers new validation to admission-time CEL. Namespace-string comparison is CEL-expressible, unlike the AWS case this mirrors (AWS needs live subnet lookups). The mitigation is real — the "correct" namespace derives from cross-object data (HostedControlPlaneNamespace / Credentials.InfraNamespace) a NodePool CEL rule can't see — but the PR should state why CEL was rejected. If it stays controller-time, api/AGENTS.md's envtest requirement is moot.
  2. Minor: the comment enumerates openshift-multus/openshift-sriov-network-operator as exempt, but the code only exempts default. Comment describes behavior the code doesn't implement.
  3. Minor (Primitive Obsession): network.Name carries a namespace/name domain concept parsed inline; consider a small accessor on KubevirtNetwork.

Spec

  • Faithful to the Proposed Fix. One nuance: the issue's Expected Result says validation should reject "immediately" (admission), but this rejects asynchronously via ValidPlatformConfig=False. That's explicitly sanctioned by the Proposed Fix line, so acceptable — flagging only so it's a conscious choice.
  • No scope creep. The default exemption is explicitly required by the issue; aggregated-docs.md is generated.

Nothing here is a hard blocker on its own; the CEL-vs-controller question is the one worth a reviewer decision.

condition.Reason = hyperv1.AWSErrorReason
condition.Message = err.Error()
}
case hyperv1.KubevirtPlatform:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Per api/AGENTS.md ("prefer admission-time via CEL over controller-time validation"), consider whether this belongs as a CEL rule on the API type rather than a reconcile-time condition. Namespace-string comparison is CEL-expressible (unlike the AWS case above, which needs live subnet lookups). If controller-time is intentional because the target namespace derives from cross-object data (HostedControlPlaneNamespace / Credentials.InfraNamespace) that a NodePool CEL rule can't reach, please note that rationale in the PR description.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Controller-time is intentional here.

The allowed NAD namespace is not a NodePool field — it is the virt-launcher namespace, derived from the HostedCluster (HostedControlPlaneNamespace(hc.Namespace, hc.Name), or Credentials.InfraNamespace for external infra). A NodePool CEL rule can only see NodePool spec, so it cannot express this constraint.

I've added that rationale to the PR description, including why this is ValidPlatformConfig=False rather than an immediate admission reject. api/AGENTS.md's envtest/CEL requirement does not apply while this stays reconcile-time.

}

for _, network := range kvPlatform.AdditionalNetworks {
parts := strings.SplitN(network.Name, "/", 2)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

(Optional) network.Name encodes a namespace/name domain concept that's documented on KubevirtNetwork but parsed ad-hoc here. A small namespace() accessor on the type would keep this split in one place and avoid re-implementing it if another caller needs it.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Leaving the split inline for this PR. This is the only call site, and KubevirtNetwork.Name is already documented as namespace/name. I'd rather not add an API helper until a second caller needs it.


for _, network := range kvPlatform.AdditionalNetworks {
parts := strings.SplitN(network.Name, "/", 2)
if len(parts) != 2 {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Worth a one-line comment that bare names (no /) are intentionally skipped because Multus resolves them in the pod's own namespace, which is already safe. Makes the "why" explicit for the next reader.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done — added a comment above the len(parts) != 2 continue: bare names (no /) are skipped because Multus resolves them in the pod's own namespace, which is already the virt-launcher namespace.

Comment on lines +1059 to +1061
// "default" is always in Multus globalNamespaces on OCP. Other global namespaces
// (openshift-multus, openshift-sriov-network-operator) are also exempt from isolation
// but are operator-internal — user NADs should not be placed there.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The comment says openshift-multus/openshift-sriov-network-operator "are also exempt from isolation," but the code only exempts "default". Reads as behavior the code doesn't implement — suggest trimming the aside to just explain the default exemption to avoid misleading future readers.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done — trimmed the comment to only explain the default exemption. The code does not special-case openshift-multus / openshift-sriov-network-operator, so listing them as exempt was misleading.

@jparrill jparrill 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.

Good, focused fix — clear problem, minimal scope, solid tests. A few suggestions inline.

// references a NAD in the namespace where virt-launcher pods will run, or in "default".
// With Multus namespace isolation enabled (OpenShift default), pods cannot reference NADs
// in other namespaces.
func (r *NodePoolReconciler) validateKubevirtAdditionalNetworkNamespaces(nodePool *hyperv1.NodePool, hc *hyperv1.HostedCluster) error {

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.

The existing validateAWSPlatformConfig and the caller validPlatformConfigCondition both use a value receiver NodePoolReconciler. This function doesn't use r at all — could you switch it to a value receiver for consistency? Or even make it a standalone function since it's a pure validation.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done — switched to a value receiver to match validateAWSPlatformConfig and validPlatformConfigCondition. Left it as a method rather than a standalone function so the call site stays r.validate…, same as the AWS case.

condition.Reason = hyperv1.AWSErrorReason
condition.Message = err.Error()
}
case hyperv1.KubevirtPlatform:

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.

Have you considered what happens to existing clusters after the operator upgrades? If someone has a working setup where NADs are in a non-HCP namespace (e.g., Multus isolation is disabled, or they're on a non-OCP management cluster), this will start surfacing ValidPlatformConfig=False after the upgrade. The condition is informational so it won't break anything, but it could trigger monitoring alerts. Worth mentioning in the PR description or adding a release note?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yes — this is condition-only. validPlatformConfigCondition still returns nil, so reconcile and VM create are not blocked.

Two cases after upgrade:

  • OpenShift with default Multus isolation: ValidPlatformConfig=False is the real failure becoming visible (today it only shows up as an opaque virt-launcher/Multus error).
  • Isolation disabled, or a non-OCP management cluster: NADs outside the HCP/infra namespace can still work, so the False condition can be a false positive for anyone alerting on it.

I've added an upgrade note to the PR description covering both.

// (openshift-multus, openshift-sriov-network-operator) are also exempt from isolation
// but are operator-internal — user NADs should not be placed there.
if nadNamespace != infraNS && nadNamespace != "default" {
return fmt.Errorf(

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.

The error message says "this is likely to be rejected" (hedging) but the condition status is ConditionFalse (definitive). These two signals disagree — either make the message definitive ("this will be rejected") or consider whether a warning-level response would be more appropriate for cases where isolation might be disabled.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Keeping ConditionFalse and the hedge.

False means the NAD namespace does not match the virt-launcher namespace under default Multus isolation — not that VM create is blocked. The message says "likely" because isolation can be disabled (or the management cluster may not be OpenShift); in those cases the VM can still start.

A warning-level / ConditionUnknown would change semantics for ValidPlatformConfig and is out of scope for this fix. The condition is the signal; reconcile does not short-circuit on it.

infraNS = hc.Spec.Platform.Kubevirt.Credentials.InfraNamespace
}

for _, network := range kvPlatform.AdditionalNetworks {

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.

Minor: with multiple additionalNetworks, this returns on the first invalid one. If a user has 3 NADs in the wrong namespace, they fix one, re-reconcile, see the next error, fix, repeat. Would collecting all invalid entries into a single error message be better UX? Not blocking — just a thought.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Leaving fail-on-first to match validateAWSPlatformConfig. The user still gets an actionable namespace in the message; remaining entries show up on the next reconcile after they fix the current one. Happy to collect them in a follow-up if you want it in this PR.

Use a value receiver to match validateAWSPlatformConfig, document why
bare NAD names are skipped, and trim the default-exemption comment to
behavior the code actually implements.

Co-authored-by: Cursor <cursoragent@cursor.com>
@openshift-ci-robot openshift-ci-robot added jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. and removed jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. labels Aug 18, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@chdeshpa-hue: This pull request references Jira Issue OCPBUGS-109196, which is valid. The bug has been moved to the POST state.

3 validation(s) were run on this bug
  • bug is open, matching expected state (open)
  • bug target version (5.1.0) matches configured target version for branch (5.1.0)
  • bug is in the state ASSIGNED, which is one of the valid states (NEW, ASSIGNED, POST)
Details

In response to this:

Summary

  • Adds KubeVirt platform validation to validPlatformConfigCondition that checks additionalNetworks NAD namespace against the resolved virt-launcher pod namespace
  • On mismatch, sets ValidPlatformConfig=False with an actionable message telling users where to create the NAD
  • Documents the namespace requirement in the KubeVirt networking how-to guide

Problem

NodePool.spec.platform.kubevirt.additionalNetworks accepts NAD references passed verbatim to Multus via MultusNetwork.NetworkName. Users naturally place NADs in the HostedCluster namespace, but virt-launcher pods run in the HCP namespace ({hc-ns}-{hc-name}). With Multus namespace isolation enabled (OCP default), the cross-namespace reference is rejected — but the only signal is an opaque pod sandbox error buried in virt-launcher events.

Fix

Mirrors the existing AWS platform validation pattern:

case hyperv1.KubevirtPlatform:
   if err := r.validateKubevirtAdditionalNetworkNamespaces(nodePool, hc); err != nil {
       condition.Status = corev1.ConditionFalse
       condition.Reason = hyperv1.NodePoolValidationFailedReason
       condition.Message = err.Error()
   }

The validation resolves the target namespace (HCP ns or Credentials.InfraNamespace) and checks each additionalNetworks entry's namespace portion.

Why not CEL / admission-time validation

This check stays controller-time on purpose. The allowed NAD namespace is the virt-launcher namespace, which comes from the HostedCluster (HostedControlPlaneNamespace / Credentials.InfraNamespace). A NodePool CEL rule cannot see that cross-object data.

The issue's Expected Result asked for an immediate (admission) reject. This PR uses ValidPlatformConfig=False instead — asynchronous, informational, and aligned with the Proposed Fix and the existing AWS platform-validation pattern. There is no admission webhook in this change.

Upgrade note

After this lands, KubeVirt NodePools whose additionalNetworks NAD is not in the virt-launcher namespace (HCP/infra) or default will report ValidPlatformConfig=False. Reconcile is not blocked and VMs are still created.

On OpenShift with default Multus isolation this matches real Multus rejection. If namespace isolation is disabled (or the management cluster is not OpenShift), the condition can be a false positive for monitoring.

Test plan

  • 9 unit test cases covering: HCP namespace match, default namespace, external infra, HC namespace mismatch, dots in name, bare names, empty networks, multi-network mix
  • CI: ci/prow/unit, ci/prow/verify, ci/prow/lint

Verification output

$ git diff --stat origin/main
docs/content/how-to/kubevirt/configuring-network.md | 25 +-
hypershift-operator/controllers/nodepool/conditions.go | 45 ++++
hypershift-operator/controllers/nodepool/conditions_test.go | 280 +++++++++++++++++++++
3 files changed, 349 insertions(+), 1 deletion(-)

/jira OCPBUGS-109196

Made with Cursor

Summary by CodeRabbit

  • Bug Fixes

  • Added validation for KubeVirt additional network namespaces.

  • Network definitions must now be located in the appropriate HCP infrastructure namespace or the default namespace.

  • Invalid namespace configurations are reported clearly and prevent the platform configuration from being marked valid.

  • Improved handling of valid and invalid network namespace combinations.

  • Documentation

  • Clarified NetworkAttachmentDefinition placement, namespace naming, and commands for identifying the correct namespace.

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.

@openshift-ci

openshift-ci Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

@chdeshpa-hue: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/security ffc16da link true /test security

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/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/valid-bug Indicates that a referenced Jira bug is valid 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.

4 participants