Skip to content

net: Nad live-update non-migratable VM test#5212

Open
azhivovk wants to merge 2 commits into
RedHatQE:mainfrom
azhivovk:nad-ref-non-migratable
Open

net: Nad live-update non-migratable VM test#5212
azhivovk wants to merge 2 commits into
RedHatQE:mainfrom
azhivovk:nad-ref-non-migratable

Conversation

@azhivovk

@azhivovk azhivovk commented Jun 14, 2026

Copy link
Copy Markdown
Contributor
What this PR does / why we need it:

Adds test_non_migratable_vm_nad_change_not_applied: verifies that updating the NAD reference on a non-migratable VM does not apply live and the VM reports a RestartRequired condition and retains connectivity to the original VLAN-A.

To support this, the PR also:

  • Extends VMSpec and Volume in libs/vm/spec.py with DataVolumeRef, and adds a data_volume_template parameter to two_secondary_bridge_vm so a RWO DataVolume can be attached to make the VM non-live-migratable
  • Fixes the containerdisk guard in _fill_vm_spec_defaults to check by volume name instead of DataVolume presence, so the containerdisk is not skipped when a DataVolume is attached as an extra disk
  • Adds patch_nad_references: a patch-only variant of update_nad_references for cases where the expected condition is not MigrationRequired
Which issue(s) this PR fixes: -
Special notes for reviewer:

The test is quarantined via @pytest.mark.jira("CNV-87878", run=False): the RestartRequired condition is not yet wired up in KubeVirt.

jira-ticket: https://redhat.atlassian.net/browse/CNV-89745

Summary by CodeRabbit

Release Notes

  • New Features

    • Virtual machine specifications now support named DataVolume references for volumes.
    • VM specs can now include DataVolume-backed disk templates for added storage flexibility.
    • VM disk/volume defaults now avoid duplicating container-disk storage when a container-disk-backed volume already exists.
  • Tests

    • Expanded coverage for non-migratable VMs with DataVolume templates.
    • Added connectivity assertions verifying NAD reference updates don’t move traffic between VLAN-A and VLAN-B in non-migratable scenarios.

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds DataVolumeRef to the VM spec library and guards _fill_vm_spec_defaults against inserting a Fedora container-disk when a DataVolume is already present. Refactors NAD patching into condition-aware and patch-only helpers, extends two_secondary_bridge_vm to accept an optional DataVolume template, adds fixtures for a non-migratable VM, and fully implements the previously disabled test_non_migratable_vm_nad_change_not_applied test.

Changes

Non-migratable VM NAD reference change test

Layer / File(s) Summary
DataVolumeRef spec type and factory guard
libs/vm/spec.py, libs/vm/factory.py
Adds DataVolumeRef(name: str) dataclass and an optional dataVolume: DataVolumeRef | None field to Volume. Guards _fill_vm_spec_defaults so the Fedora container-disk disk/volume is only inserted when no existing volume already references a dataVolume.
NAD patching helpers: condition-aware and patch-only
tests/network/libs/nad_ref.py
Refactors update_nad_references to delegate network patching to _patch_networks helper, preserving the MigrationRequired wait-and-clear flow. Adds patch_nad_references for patch-only NAD updates (deep-copies networks, updates multus.networkName, calls vm.set_networks, but skips condition polling). Exports _patch_networks as the shared deep-copy and multus-update logic.
two_secondary_bridge_vm DataVolume support
tests/network/l2_bridge/nad_ref_change/lib_helpers.py
Extends two_secondary_bridge_vm with data_volume_template: dict[str, Any] | None = None. When provided, derives dv_name from metadata.name, adds a DataVolume-backed disk via add_volume_disk, creates the VM, then appends the template into vm.body["spec"]["dataVolumeTemplates"]. Existing path (cloud-init only) is preserved.
Non-migratable VM fixtures and baseline connectivity
tests/network/l2_bridge/nad_ref_change/conftest.py
Adds non_migratable_under_test_vm fixture that provisions a VM with a generated DataVolume template (Fedora image, default StorageClass), and non_migratable_baseline_connectivity fixture that asserts VLAN-A reachability and VLAN-B unreachability as a pre-test baseline.
test_non_migratable_vm_nad_change_not_applied implementation
tests/network/l2_bridge/nad_ref_change/test_nad_ref_change.py
Re-enables the previously disabled test stub by removing __test__ = False, adding jira(CNV-87878, run=False) and usefixtures("non_migratable_baseline_connectivity") decorators. Test body uses patch_nad_references to move secondary bridge to alternate VLAN, waits for RestartRequired condition, then asserts per-IP connectivity remains on original VLAN and absent on new VLAN.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • RedHatQE/openshift-virtualization-tests#5039: Directly touches tests/network/libs/nad_ref.py NAD update infrastructure that this PR extends with the new patch_nad_references patch-only helper and refactored _patch_networks logic.
  • RedHatQE/openshift-virtualization-tests#4962: Modified tests/network/l2_bridge/nad_ref_change/lib_helpers.py two_secondary_bridge_vm function that this PR further extends with optional DataVolume template parameter.

Suggested reviewers

  • EdDev
  • dshchedr
  • Anatw
  • vsibirsk
  • rnetser

Caution

Pre-merge checks failed

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

  • Ignore

❌ Failed checks (1 error)

Check name Status Explanation Resolution
Stp Link Required ❌ Error 300+ newly added test files under tests/ lack STP/RFE/Jira links in module docstrings. Only test files related to nad_ref_change have the required STP link (e.g., tests/network/l2_bridge/nad_ref_ch... Add STP/RFE/Jira links to module docstrings of all newly added test files, or ensure they are added only where required per project standards.
✅ Passed checks (4 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.
Title check ✅ Passed The title clearly describes the main change: adding a test for NAD live-update behavior on non-migratable VMs, and is well under the 120-character limit.
Description check ✅ Passed The description includes all required sections with substantive content: what the PR does, which issues it fixes, special reviewer notes, and the JIRA ticket URL.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Linked repositories: Your configuration references 1 linked repositories, but your current plan allows 0. Analyzed ``, skipped RedHatQE/openshift-virtualization-tests-design-docs.


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 and usage tips.

@openshift-virtualization-qe-bot-6

Copy link
Copy Markdown

Report bugs in Issues

Welcome! 🎉

This pull request will be automatically processed with the following features:

🔄 Automatic Actions

  • Reviewer Assignment: Reviewers are automatically assigned based on the OWNERS file in the repository root
  • Size Labeling: PR size labels (XS, S, M, L, XL, XXL) are automatically applied based on changes
  • Issue Creation: A tracking issue is created for this PR and will be closed when the PR is merged or closed
  • Branch Labeling: Branch-specific labels are applied to track the target branch
  • Auto-verification: Auto-verified users have their PRs automatically marked as verified
  • Labels: Enabled categories: branch, can-be-merged, cherry-pick, has-conflicts, hold, needs-rebase, size, verified, wip

📋 Available Commands

PR Status Management

  • /wip - Mark PR as work in progress (adds WIP: prefix to title)
  • /wip cancel - Remove work in progress status
  • /hold - Block PR merging (approvers only)
  • /hold cancel - Unblock PR merging
  • /verified - Mark PR as verified
  • /verified cancel - Remove verification status
  • /reprocess - Trigger complete PR workflow reprocessing (useful if webhook failed or configuration changed)
  • /regenerate-welcome - Regenerate this welcome message
  • /security-override - Set security check runs to pass (maintainers only)
  • /security-override cancel - Re-run security checks

Review & Approval

  • /lgtm - Approve changes (looks good to me)
  • /approve - Approve PR (approvers only)
  • /assign-reviewers - Assign reviewers based on OWNERS file
  • /assign-reviewer @username - Assign specific reviewer
  • /check-can-merge - Check if PR meets merge requirements

Testing & Validation

  • /retest tox - Run Python test suite with tox
  • /retest build-container - Rebuild and test container image
  • /retest verify-bugs-are-open - verify-bugs-are-open
  • /retest all - Run all available tests

Container Operations

  • /build-and-push-container - Build and push container image (tagged with PR number)
    • Supports additional build arguments: /build-and-push-container --build-arg KEY=value

Cherry-pick Operations

  • /cherry-pick <branch> - Schedule cherry-pick to target branch when PR is merged
    • Multiple branches: /cherry-pick branch1 branch2 branch3
  • /cherry-pick-retry <branch> - Retry a failed cherry-pick (merged PRs only)

Branch Management

  • /rebase - Rebase this PR branch onto its base branch

Label Management

  • /<label-name> - Add a label to the PR
  • /<label-name> cancel - Remove a label from the PR

✅ Merge Requirements

This PR will be automatically approved when the following conditions are met:

  1. Approval: /approve from at least one approver
  2. LGTM Count: Minimum 2 /lgtm from reviewers
  3. Status Checks: All required status checks must pass
  4. No Blockers: No wip, hold, has-conflicts labels and PR must be mergeable (no conflicts)
  5. Verified: PR must be marked as verified

📊 Review Process

Approvers and Reviewers

Approvers:

  • EdDev
  • dshchedr
  • myakove
  • rnetser
  • vsibirsk

Reviewers:

  • Anatw
  • EdDev
  • RoniKishner
  • azhivovk
  • dshchedr
  • frenzyfriday
  • nirdothan
  • orelmisan
  • rnetser
  • servolkov
  • vsibirsk
  • yossisegev
Available Labels
  • hold
  • verified
  • wip
  • lgtm
  • approve
AI Features
  • Cherry-Pick Conflict Resolution: Enabled (claude/claude-opus-4-6[1m])
Security Checks
  • Suspicious Path Detection: Monitors paths: .claude/, .vscode/, .cursor/, .devcontainer/, .pi/, .github/workflows/, .github/actions/
  • Committer Identity Check: Verifies last committer matches PR author
  • Mandatory: Security checks block merge (use /security-override to bypass — maintainers only)

💡 Tips

  • WIP Status: Use /wip when your PR is not ready for review
  • Verification: The verified label is removed on new commits unless the push is detected as a clean rebase
  • Cherry-picking: Cherry-pick labels are processed when the PR is merged
  • Container Builds: Container images are automatically tagged with the PR number
  • Permission Levels: Some commands require approver permissions
  • Auto-verified Users: Certain users have automatic verification and merge privileges

For more information, please refer to the project documentation or contact the maintainers.

@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: 3

🤖 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 `@libs/vm/factory.py`:
- Around line 44-47: The condition on line 44 incorrectly suppresses the default
containerdisk insertion whenever any DataVolume is present, breaking the ability
to use DataVolumes as additional disks alongside a boot disk. Replace the logic
that checks for any DataVolume with a check that determines whether a boot disk
or containerdisk already exists. The containerdisk should be inserted by default
unless a boot disk is already present, allowing DataVolumes to coexist as
additional disks. Modify the condition in the containerdisk_storage function
call to verify the absence of an actual boot disk rather than the absence of any
DataVolume.

In `@tests/network/l2_bridge/nad_ref_change/test_nad_ref_change.py`:
- Around line 244-248: The wait_for_vmi_condition_status call needs to be
anchored to the pre-patch resource state to ensure it validates the
RestartRequired condition is set as a result of the current patch operation, not
from a stale previous state. Capture the resourceVersion of
non_migratable_under_test_vm before calling patch_nad_references, then pass this
resourceVersion to the wait_for_vmi_condition_status call so it waits for a
condition transition that occurs after the patch, not a pre-existing condition
state.

In `@tests/network/libs/nad_ref.py`:
- Around line 27-40: The patch_nad_references function contains duplicate
network mutation logic that is already present in update_nad_references,
specifically the block that iterates through networks and updates the
multus.networkName based on the nad_name_by_net mapping. Extract this common
logic (the deepcopy, the for loop iterating through networks, and the
conditional update of network.multus.networkName) into a separate shared helper
function, then refactor both patch_nad_references and update_nad_references to
call this new helper function instead of duplicating the code.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 70873300-8c28-46c1-a952-0a736d2105fb

📥 Commits

Reviewing files that changed from the base of the PR and between c5e4a14 and 524eef8.

📒 Files selected for processing (6)
  • libs/vm/factory.py
  • libs/vm/spec.py
  • tests/network/l2_bridge/nad_ref_change/conftest.py
  • tests/network/l2_bridge/nad_ref_change/lib_helpers.py
  • tests/network/l2_bridge/nad_ref_change/test_nad_ref_change.py
  • tests/network/libs/nad_ref.py

Comment thread libs/vm/factory.py Outdated
Comment thread tests/network/l2_bridge/nad_ref_change/test_nad_ref_change.py
Comment thread tests/network/libs/nad_ref.py Outdated
Add DataVolumeRef dataclass and dataVolume field to Volume so VM
factories can reference DataVolume-backed disks.

Add dataVolumeTemplates to VMSpec so a VM can inline DataVolume
templates at spec level, enabling ReadWriteOnce-backed VMs that are
not live-migratable.

Guard containerdisk insertion in _fill_vm_spec_defaults so it is
skipped when the spec already carries a DataVolume volume, preventing
a duplicate boot disk.

Signed-off-by: Asia Khromov <azhivovk@redhat.com>
Assisted-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@azhivovk

Copy link
Copy Markdown
Contributor Author

Change: apply bot's suggestions

@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: 2

🤖 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 `@tests/network/l2_bridge/nad_ref_change/lib_helpers.py`:
- Around line 88-89: The data_volume_template parameter currently accepts raw
dict objects, which bypasses typed resource composition and is brittle for
schema drift. Replace the dict[str, Any] type annotation and contract to use a
structured, typed builder or ocp-resources class instead. Identify or create an
appropriate typed class from the ocp-resources library that represents the data
volume template structure, update the parameter type accordingly, and ensure
callers pass structured instances instead of raw YAML-like dictionaries. This
centralizes serialization logic and maintains type safety across the API
contract.
- Around line 135-136: Replace the truthiness checks with explicit `is not None`
checks to ensure fail-fast behavior on malformed input. At line 135, change the
condition that checks `data_volume_template` from a truthiness check to
`data_volume_template is not None`. Apply the same change at line 144 for the
analogous variable (likely `vm_template` based on the context), replacing its
truthiness check with an explicit `is not None` comparison. This prevents empty
dictionaries from being silently skipped and ensures that malformed input fails
loudly as intended by the coding guidelines.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: cec88a75-1765-44d8-b547-12f714e844a2

📥 Commits

Reviewing files that changed from the base of the PR and between 524eef8 and 3ab53f3.

📒 Files selected for processing (6)
  • libs/vm/factory.py
  • libs/vm/spec.py
  • tests/network/l2_bridge/nad_ref_change/conftest.py
  • tests/network/l2_bridge/nad_ref_change/lib_helpers.py
  • tests/network/l2_bridge/nad_ref_change/test_nad_ref_change.py
  • tests/network/libs/nad_ref.py

Comment thread tests/network/l2_bridge/nad_ref_change/lib_helpers.py
Comment thread tests/network/l2_bridge/nad_ref_change/lib_helpers.py
Comment thread tests/network/l2_bridge/nad_ref_change/conftest.py Outdated
Comment thread tests/network/l2_bridge/nad_ref_change/conftest.py Outdated
Comment thread tests/network/l2_bridge/nad_ref_change/conftest.py Outdated
Implement test_non_migratable_vm_nad_change_not_applied (CNV-15947):
verifies that updating the NAD reference on a non-migratable VM does
not apply live — the VM reports a RestartRequired condition and retains
connectivity to the original VLAN-A.

A blank 20Gi RWO DataVolume is attached via two_secondary_bridge_vm's
new data_volume_template parameter, making the VM non-live-migratable.
Connectivity to VLAN-A is verified as a fixture precondition.

Quarantined via CNV-87878: the RestartRequired condition is not yet
wired up in KubeVirt — the wait_for_condition call will be unblocked
when the product fix lands.

Signed-off-by: Asia Khromov <azhivovk@redhat.com>
Assisted-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@azhivovk

Copy link
Copy Markdown
Contributor Author

Change: apply requested DV changes after CR

@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

🤖 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 `@tests/network/l2_bridge/nad_ref_change/conftest.py`:
- Around line 191-219: The non_migratable_baseline_connectivity fixture
duplicates connectivity verification logic from another fixture, with only the
client VM parameter differing. Extract the duplicated logic (the two
filter_link_local_addresses and poll_tcp_connectivity loops that verify baseline
connectivity) into a shared helper function called assert_baseline_connectivity
in lib_helpers.py that accepts client_vm and ref_vm as parameters. Then refactor
the non_migratable_baseline_connectivity fixture to call this helper function
instead of containing the inline logic. Also refactor the original baseline
connectivity fixture at lines 122-149 to use the same extracted helper function
to eliminate duplication and ensure a single maintenance path.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 95eb4872-74f4-4318-8741-5b24f85a610a

📥 Commits

Reviewing files that changed from the base of the PR and between 3ab53f3 and 1cf99bd.

📒 Files selected for processing (4)
  • tests/network/l2_bridge/nad_ref_change/conftest.py
  • tests/network/l2_bridge/nad_ref_change/lib_helpers.py
  • tests/network/l2_bridge/nad_ref_change/test_nad_ref_change.py
  • tests/network/libs/nad_ref.py

Comment thread tests/network/l2_bridge/nad_ref_change/conftest.py
@jpeimer

jpeimer commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

/lgtm
(for the storage part)

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

/lgtm thanks!
The comments that I have are nits

)
blank_dv.to_dict()
dv_template = blank_dv.res
with two_secondary_bridge_vm(

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.

[nit]: Is there a fixture for creating secondary bridge vm with one secondary nw? The name two_secondary_bridge_vm confused me initially a bit because this VM has only one secondary iface. maybe it would be better to use a different fixture that creates a VM with 1 secondary net or rename the two_secondary_bridge_vm to something like one_or_more_secondary_bridge_vm?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I can change it to use secondary_network_vm under tests/network/l2_bridge/libl2bridge.py which has 1 secondary Linux bridge network
I implemented it like this since two_secondary_bridge_vm already has runcmd which is required for the arp ignore commands

ip_addresses=lookup_iface_status(vm=ref_vm, iface_name=LINUX_BRIDGE_IFACE_NAME_1).ipAddresses
):
with subtests.test(msg=f"IPv{server_ip.version} on {bridge_nad_a.name}"):
assert_connectivity(

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.

[question]: Why does the non_migratable_baseline_connectivity use poll_tcp_connectivity but the test use assert_connectivity ?

@azhivovk azhivovk Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

assert is for usage in test only and we use this helper to align with the existing tests
This was requested when the existing NAD live update tests merged, for clearance about the test flow
I used the polling helper since it's part of the setup

@openshift-virtualization-qe-bot-3

Copy link
Copy Markdown
Contributor

/retest all

Auto-triggered: Files in this PR were modified by merged PR #4810.

Overlapping files

libs/vm/factory.py
libs/vm/spec.py

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants