Skip to content

feat(MTV-6088): add MTV-777 combined VM+populator inflight throttling test with DRS VM override - #602

Merged
myakove merged 10 commits into
RedHatQE:mainfrom
prabinovRedhat:feat/MTV-6088-vm-populator-inflight-throttling
Jul 24, 2026
Merged

feat(MTV-6088): add MTV-777 combined VM+populator inflight throttling test with DRS VM override#602
myakove merged 10 commits into
RedHatQE:mainfrom
prabinovRedhat:feat/MTV-6088-vm-populator-inflight-throttling

Conversation

@prabinovRedhat

@prabinovRedhat prabinovRedhat commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Jira / Polarion

What was added

disable_drs_for_vm() on VMWareProvider

Per-VM vSphere DRS automation override using vim.cluster.DrsVmConfigSpec + vim.cluster.ConfigSpecEx. Pins a cloned VM to its current ESXi host by setting DrsVmConfigInfo(enabled=False), preventing DRS from relocating it before migration starts.

TestCopyoffloadVmPopulatorThrottlingMigration (MTV-777, 7-step)

New test class covering combined VM + populator inflight throttling:

  • Sets controller_max_vm_inflight=1 (only 1 VM migrates at a time per ESXi host)
  • Sets controller_max_populator_inflight=2 (only 2 populate pods active per ESXi host)
  • Verifies peak VM concurrency ≤ 1 via verify_vm_inflight_throttling()
  • Verifies XCOPY was used for all disks

Combined monitoring utilities

  • execute_migration_monitoring_vm_and_populator_inflight() — single migration run with 3 simultaneous callbacks: VM concurrency tracker + populator concurrency tracker + log capture
  • verify_vm_inflight_throttling() — pure computation, validates peak ≤ limit AND peak ≥ min(limit, vm_count)
  • _VmConcurrencyTracker — mirrors _PopulatorConcurrencyTracker for VM-level scheduling

VM+populator inflight fixture

vm_populator_inflight_forkliftcontroller (class-scoped) — patches both controller_max_vm_inflight and controller_max_populator_inflight with a single combined file lock. Nested context managers ensure both limits are restored on teardown even after failures.

disable_drs_for_vm in conftest.py prepared_plan

When plan.get("disable_drs_for_vms", False) is set, calls clone_provider.disable_drs_for_vm() after each clone to prevent DRS from moving the VM before migration.

Config

"test_copyoffload_vm_populator_throttling_migration": {
    "virtual_machines": [
        # × 2 VMs, 2 add_disks each (3 total disks per VM including OS)
    ],
    "clone_to_same_host": True,    # pins clones to same ESXi host via runtime.host.name
    "disable_drs_for_vms": True,   # disables DRS per VM after cloning
    "inventory_timeout": 600,
}

CI

Build Config Result
#409 3 VMs × 3 disks ✅ SUCCESS — peak VM concurrency 1/1 (PASS)
#410 2 VMs × 3 disks ✅ SUCCESS — peak VM concurrency 1/1 (PASS)

Same-host cloning pinned to ESXi 10.46.29.136, DRS disabled for all VMs on Eco-Cluster. controller_max_vm_inflight restored from 1→20 on teardown.

Summary by CodeRabbit

  • New Features

    • Added plan options to pin additional cloned VMs to the same ESXi host and to disable DRS per cloned VM.
    • Extended copy-offload test coverage to validate combined VM + populator inflight throttling (including XCOPY and VM correctness checks).
  • Bug Fixes

    • Improved clone behavior to respect same-host placement and apply DRS disabling for each cloned VM.
  • Documentation

    • Updated copy-offload test documentation with a new 8-step VM+populator throttling verification pattern and new plan option details.
  • Tests

    • Added MTV-777 throttling migration scenario plus shared helpers/fixtures for coordinated inflight monitoring across parallel runs.

@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 →

@redhat-qe-bot

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: Disabled for this repository
  • 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: All label categories are enabled (default configuration)

📋 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)
  • /automerge - Enable automatic merging when all requirements are met (maintainers and 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 conventional-title - Validate commit message format
  • /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. Status Checks: All required status checks must pass
  3. No Blockers: No wip, hold, has-conflicts labels and PR must be mergeable (no conflicts)
  4. Verified: PR must be marked as verified

📊 Review Process

Approvers and Reviewers

Approvers:

  • krcmarik
  • myakove
  • solenoci

Reviewers:

  • krcmarik
  • myakove
  • solenoci
Available Labels
  • hold
  • verified
  • wip
  • lgtm
  • approve
  • automerge
AI Features
  • Conventional Title: Mode: fix (claude/claude-opus-4-6-1m)
  • Cherry-Pick Conflict Resolution: Enabled (claude/claude-opus-4-6-1m)
  • Test Oracle: Triggers: approved (cursor/gpt-5.4-xhigh-fast); /test-oracle can be used anytime
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.

@prabinovRedhat

Copy link
Copy Markdown
Collaborator Author

/verified

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@prabinovRedhat, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 39 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: fe6005a2-eaa8-4ac1-8bee-73369ca09de2

📥 Commits

Reviewing files that changed from the base of the PR and between d0b8c1e and 000e5e1.

📒 Files selected for processing (2)
  • AGENTS.md
  • conftest.py

Walkthrough

Adds VMware clone placement and DRS controls, VM in-flight controller limit management, combined VM/populator migration monitoring, and a new copy-offload throttling test configuration.

Changes

VM and Populator Throttling

Layer / File(s) Summary
VM clone placement controls
AGENTS.md, conftest.py, libs/providers/vmware.py
Documents clone_to_same_host and disable_drs_for_vms; clone preparation pins VMs to the first ESXi host and can disable per-VM DRS.
Combined controller limit fixture
utilities/copyoffload_constants.py, utilities/forklift_controller_populator.py, tests/copyoffload/conftest.py
Adds VM in-flight limits, deployment/CR reconciliation, shared locking, restoration, and a combined pytest fixture.
VM and populator concurrency monitoring
utilities/copyoffload_migration.py
Maps VMs to ESXi hosts, tracks active VM phases and per-host peaks, combines VM and populator monitoring, and supports explicit throttling expectations.
Copy-offload throttling test
tests/tests_config/config.py, tests/copyoffload/test_copyoffload_migration.py, AGENTS.md
Adds the MTV-777 configuration and test flow for throttling, XCOPY usage, migrated VM validation, and the documented eight-step pattern.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Test
  participant MigrationMonitor
  participant Inventory
  participant Plan
  Test->>MigrationMonitor: Start monitored migration
  MigrationMonitor->>Inventory: Resolve VM ESXi hosts
  MigrationMonitor->>Plan: Poll migration status
  Plan-->>MigrationMonitor: VM and populator activity
  MigrationMonitor-->>Test: Return peak concurrency
Loading

Possibly related PRs

Suggested labels: verified, can-be-merged, lgtm-coderabbitai[bot], cherry-pick-v2.11, cherry-pick-v2.10

Suggested reviewers: myakove, krcmarik, solenoci

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: MTV-777 combined VM+populator inflight throttling coverage with DRS VM override support.
Docstring Coverage ✅ Passed Docstring coverage is 94.44% which is sufficient. The required threshold is 80.00%.
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.
✨ 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.

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

🤖 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 `@conftest.py`:
- Around line 1129-1130: The guaranteed pyVmomi properties are being accessed
through unnecessary getattr-based defensive checks. In conftest.py lines
1129-1130, update the provider VM setup to access provider_vm_api.runtime.host
and runtime_host.name directly; in libs/providers/vmware.py lines 350-353,
access vm.runtime.host and host.parent directly while preserving the existing
host absence handling and error behavior.

In `@tests/copyoffload/test_copyoffload_migration.py`:
- Around line 5605-5638: Remove the unused target_namespace parameter from
test_check_vms and its docstring, leaving the check_vms invocation and all other
fixture parameters unchanged.

In `@utilities/copyoffload_migration.py`:
- Around line 1707-1806: Update the _combined_callback function to catch
ValueError from populator_tracker.poll(status), alongside ApiException, and log
it as a warning so transient migration UID lookup misses do not abort
wait_for_migration_complate. Keep the existing VM tracking and log-capture
behavior unchanged, matching the callback error-isolation pattern used for the
other monitors.

In `@utilities/forklift_controller_populator.py`:
- Around line 520-532: The shared lock helper must return the lock used by all
ForkliftController inflight-limit mutations. Update
get_forkliftcontroller_vm_populator_inflight_lock_path to use the existing
populator-inflight.lock filename, ensuring
vm_populator_inflight_forkliftcontroller and
populator_inflight_forkliftcontroller serialize through the same mutex.
🪄 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: 21d9548a-dca5-404c-bcee-e222cff355fc

📥 Commits

Reviewing files that changed from the base of the PR and between 13e45b2 and 0c5d6e8.

📒 Files selected for processing (9)
  • AGENTS.md
  • conftest.py
  • libs/providers/vmware.py
  • tests/copyoffload/conftest.py
  • tests/copyoffload/test_copyoffload_migration.py
  • tests/tests_config/config.py
  • utilities/copyoffload_constants.py
  • utilities/copyoffload_migration.py
  • utilities/forklift_controller_populator.py

Comment thread conftest.py Outdated
Comment thread tests/copyoffload/test_copyoffload_migration.py
Comment thread utilities/copyoffload_migration.py
Comment thread utilities/forklift_controller_populator.py

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
utilities/forklift_controller_populator.py (1)

534-604: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Do not silently suppress VM-limit restoration failures.

When the test body raises and cleanup also fails, this path logs the restoration error but preserves no actionable failure for the dirty controller state. A later test can inherit test_limit, causing cross-test throttling failures. Surface the cleanup failure while preserving the original exception, or otherwise fail the worker/session when restoration cannot be confirmed.

🤖 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 `@utilities/forklift_controller_populator.py` around lines 534 - 604, The
vm_inflight_limit cleanup in the finally block must not silently suppress
restoration failures when the test body also raised. Update the pending_exc
handling around _ensure_forklift_controller_vm_limit and
wait_for_vm_inflight_deployment so the cleanup error is surfaced while
preserving the original test exception, or terminate the worker/session if
restoration cannot be confirmed; retain the current behavior of raising cleanup
errors when no prior exception exists.
🤖 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 `@utilities/forklift_controller_populator.py`:
- Around line 521-526: Update the docstring for the shared-lock path helper near
get_forkliftcontroller_populator_inflight_lock_path() to state that the VM and
populator fixtures mutate controller_max_vm_inflight and
controller_max_populator_inflight, respectively, while preserving the existing
shared-mutex rationale.

---

Outside diff comments:
In `@utilities/forklift_controller_populator.py`:
- Around line 534-604: The vm_inflight_limit cleanup in the finally block must
not silently suppress restoration failures when the test body also raised.
Update the pending_exc handling around _ensure_forklift_controller_vm_limit and
wait_for_vm_inflight_deployment so the cleanup error is surfaced while
preserving the original test exception, or terminate the worker/session if
restoration cannot be confirmed; retain the current behavior of raising cleanup
errors when no prior exception exists.
🪄 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: f8d925a8-7fcc-4460-a6e8-310ee48d5de0

📥 Commits

Reviewing files that changed from the base of the PR and between 0c5d6e8 and c2c38b6.

📒 Files selected for processing (5)
  • conftest.py
  • libs/providers/vmware.py
  • tests/copyoffload/test_copyoffload_migration.py
  • utilities/copyoffload_migration.py
  • utilities/forklift_controller_populator.py
💤 Files with no reviewable changes (1)
  • tests/copyoffload/test_copyoffload_migration.py

Comment thread utilities/forklift_controller_populator.py
@prabinovRedhat

Copy link
Copy Markdown
Collaborator Author

/verified

… event expectation

Co-authored-by: Cursor <cursoragent@cursor.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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
conftest.py (1)

1113-1121: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

HIGH: Do not let per-VM host overrides defeat clone_to_same_host.

setdefault() preserves an existing target_esxi_host, including a conflicting host or None, so the resulting clones may not share first_vm_esxi_host. That invalidates the downstream per-host throttling assertions. Reject conflicting overrides or assign the captured host unconditionally when clone_to_same_host=True.

The follow-up commits added same-host lookup and DRS controls, but this override remains an escape hatch from that contract.

🤖 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 `@conftest.py` around lines 1113 - 1121, Update the clone-options logic in the
virtual-machine loop so that when plan["clone_to_same_host"] is enabled and
first_vm_esxi_host is set, target_esxi_host is assigned unconditionally to
first_vm_esxi_host. Do not preserve per-VM overrides in this mode, ensuring
every clone uses the captured host.
utilities/copyoffload_migration.py (1)

1821-1835: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Catch ValueError in the VM tracker branch of _combined_callback too.

_count_active_vms_by_host() (called via vm_tracker.poll()) explicitly documents Raises: ValueError: If an active VM cannot be resolved to a host in vm_host_map, but the vm_tracker.poll(status) branch here only catches ApiException. This is the exact same hazard that was already found and fixed for the populator branch two lines below (except (ApiException, ValueError) as err:), which exists precisely because _resolve_migration_uid() could raise ValueError. An uncaught ValueError here would abort wait_for_migration_complate's entire poll loop instead of just skipping a transient VM-status/host-mapping miss.

🐛 Proposed fix
         try:
             vm_tracker.poll(status)
-        except ApiException as err:
+        except (ApiException, ValueError) as err:
             LOGGER.warning(f"VM concurrency tracking failed during poll: {err}")
🤖 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 `@utilities/copyoffload_migration.py` around lines 1821 - 1835, Update the
vm_tracker.poll(status) exception handler in _combined_callback to catch both
ApiException and ValueError, matching the populator_tracker.poll(status) branch.
Preserve the existing warning message and allow the callback to continue to log
status after either expected tracking failure.
🤖 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 `@conftest.py`:
- Around line 1097-1100: Move the disable_drs_for_vms validation out of the
source_provider.type != Provider.ProviderType.OVA branch so it also runs for OVA
plans. Reject any OVA plan with disable_drs_for_vms enabled, while preserving
the existing VMware clone-provider requirement for non-OVA plans and failing
before provider-specific processing.

---

Outside diff comments:
In `@conftest.py`:
- Around line 1113-1121: Update the clone-options logic in the virtual-machine
loop so that when plan["clone_to_same_host"] is enabled and first_vm_esxi_host
is set, target_esxi_host is assigned unconditionally to first_vm_esxi_host. Do
not preserve per-VM overrides in this mode, ensuring every clone uses the
captured host.

In `@utilities/copyoffload_migration.py`:
- Around line 1821-1835: Update the vm_tracker.poll(status) exception handler in
_combined_callback to catch both ApiException and ValueError, matching the
populator_tracker.poll(status) branch. Preserve the existing warning message and
allow the callback to continue to log status after either expected tracking
failure.
🪄 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 Plus

Run ID: de06b744-946e-4a01-ac79-9156a96215dc

📥 Commits

Reviewing files that changed from the base of the PR and between b0404be and d0b8c1e.

📒 Files selected for processing (4)
  • AGENTS.md
  • conftest.py
  • tests/copyoffload/test_copyoffload_migration.py
  • utilities/copyoffload_migration.py

Comment thread conftest.py
Raise ValueError in prepared_plan for OVA providers and document that the flag is unsupported for OVA.

Co-authored-by: Cursor <cursoragent@cursor.com>
@prabinovRedhat

Copy link
Copy Markdown
Collaborator Author

/verified

@prabinovRedhat

Copy link
Copy Markdown
Collaborator Author

@myakove can we merge this PR?

@myakove

myakove commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

/lgtm
/approve

@redhat-qe-bot2

Copy link
Copy Markdown

New container for ghcr.io/redhatqe/mtv-api-tests:latest published

@prabinovRedhat

Copy link
Copy Markdown
Collaborator Author

/cherry-pick v2.11

@redhat-qe-bot

Copy link
Copy Markdown

Cherry-pick conflicts were resolved by AI

Cherry-picked PR feat(MTV-6088): add MTV-777 combined VM+populator inflight throttling test with DRS VM override into v2.11: #613
Conflicts were automatically resolved by AI (claude/claude-opus-4-6-1m).

@prabinovRedhat Manual verification is required — please review the changes and test before merging.

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.

6 participants