Supported Providers And Scenarios
mtv-api-tests is an integration test suite for real MTV migrations into OpenShift Virtualization. The support matrix in this repository comes from three places: provider profiles in .providers.json, scenario definitions in tests/tests_config/config.py, and pytest markers in pytest.ini.
Supported Source Providers
The source_provider setting points to a named profile in .providers.json. That means you can keep multiple profiles for the same platform, such as different vSphere versions or labs, and select the one you want by profile name.
"vsphere": {
"type": "vsphere",
"version": "<SERVER VERSION>",
"fqdn": "SERVER FQDN/IP",
"api_url": "<SERVER FQDN/IP>/sdk",
"username": "USERNAME",
"password": "PASSWORD", # pragma: allowlist secret
"guest_vm_linux_user": "LINUX VMS USERNAME",
"guest_vm_linux_password": "LINUX VMS PASSWORD", # pragma: allowlist secret
"guest_vm_win_user": "WINDOWS VMS USERNAME",
"guest_vm_win_password": "WINDOWS VMS PASSWORD", # pragma: allowlist secret
"vddk_init_image": "<PATH TO VDDK INIT IMAGE>"
},
"vsphere-copy-offload": {
"type": "vsphere",
"version": "<SERVER VERSION>",
"fqdn": "SERVER FQDN/IP",
"api_url": "<SERVER FQDN/IP>/sdk",
"username": "USERNAME",
"password": "PASSWORD", # pragma: allowlist secret
// ... same guest credentials ...
"copyoffload": {
The shipped example file also includes profiles for ovirt, openstack, openshift, and ova.
| Source provider | type value |
Cold migration | Warm migration | Copy-offload | Notes |
|---|---|---|---|---|---|
| VMware vSphere | vsphere |
Yes | Yes | Yes | This is the broadest coverage area in the suite. Copy-offload is implemented as a vSphere profile with an extra copyoffload section. |
| RHV / oVirt | ovirt |
Yes | Yes, with extra suite gating | No | Standard MTV cold and warm scenarios exist in the codebase. |
| OpenStack | openstack |
Yes | No | No | Warm tests explicitly skip this provider family. |
| OpenShift | openshift |
Yes | No | No | Supported as a source provider, but not for warm scenarios. |
| OVA | ova |
Yes | No | No | Supported for cold-style scenarios. The built-in OVA path uses a fixed imported VM name during plan preparation. |
Note:
vsphere-copy-offloadis not a separate provider family. It is stilltype: "vsphere"with additional copy-offload settings.Warning: Warm migration is not available for every source provider. The warm test modules explicitly skip
openstack,openshift, andova.
pytestmark = [
pytest.mark.skipif(
_SOURCE_PROVIDER_TYPE
in (Provider.ProviderType.OPENSTACK, Provider.ProviderType.OPENSHIFT, Provider.ProviderType.OVA),
reason=f"{_SOURCE_PROVIDER_TYPE} warm migration is not supported.",
),
]
Migration Modes
This suite exercises three practical migration modes:
- Cold migration: the default path, represented by scenarios where
warm_migrationisFalse. - Warm migration: the precopy and cutover path, represented by scenarios where
warm_migrationisTrue. - Copy-offload: the accelerated vSphere path, represented by scenarios where
copyoffloadisTrue.
A simple warm scenario in the built-in test matrix looks like this:
"test_sanity_warm_mtv_migration": {
"virtual_machines": [
{
"name": "mtv-tests-rhel8",
"source_vm_power": "on",
"guest_agent": True,
},
],
"warm_migration": True,
},
There is no separate cold marker. In this repository, “cold” is the normal case when warm_migration is not enabled.
Copy-offload specifics
Copy-offload is the most specialized mode in the suite. It is vSphere-only, and the repository includes both cold copy-offload coverage and a dedicated warm copy-offload scenario.
The accepted storage_vendor_product values in the code are:
ontapvantaraprimera3parpureFlashArraypowerflexpowermaxpowerstoreinfiniboxflashsystem
Base copy-offload storage credentials are always required:
storage_hostnamestorage_usernamestorage_password
Some vendors also require extra fields:
ontap:ontap_svmvantara:vantara_storage_id,vantara_storage_port,vantara_hostgroup_id_listpureFlashArray:pure_cluster_prefixpowerflex:powerflex_system_idpowermax:powermax_symmetrix_idprimera3par,powerstore,infinibox,flashsystem: no extra vendor-specific fields beyond the base storage credentials
If you use SSH-based ESXi cloning for copy-offload, the suite also expects esxi_clone_method: "ssh" plus esxi_host, esxi_user, and esxi_password.
Tip: Copy-offload credentials can come from
.providers.jsonor fromCOPYOFFLOAD_...environment variables. Environment variables win, which is useful when you do not want secrets stored in files.
def get_copyoffload_credential(
credential_name: str,
copyoffload_config: dict[str, Any],
) -> str | None:
"""
Get a copyoffload credential from environment variable or config file.
Environment variables take precedence over config file values.
Environment variable names are constructed as COPYOFFLOAD_{credential_name.upper()}.
"""
env_var_name = f"COPYOFFLOAD_{credential_name.upper()}"
return os.getenv(env_var_name) or copyoffload_config.get(credential_name)
Pytest Markers
The repository defines these markers in pytest.ini:
markers =
tier0: Core functionality tests (smoke tests)
remote: Remote cluster migration tests
warm: Warm migration tests
copyoffload: Copy-offload (XCOPY) tests
incremental: marks tests as incremental (xfail on previous failure)
min_mtv_version: mark test to require minimum MTV version (e.g., @pytest.mark.min_mtv_version("2.6.0"))
In practice:
tier0is the smoke or core regression slice.warm,remote, andcopyoffloadare the main user-facing selectors for scenario families.incrementalis execution behavior, not a functional feature area. These class-based tests move step by step through StorageMap, NetworkMap, Plan, migration execution, and validation.min_mtv_versionis available when a scenario needs a newer MTV version.
Note:
comprehensiveis a scenario family in this repository, not a pytest marker. You select it by file or class, not with-m comprehensive.Note: Remote scenarios are opt-in. They are skipped unless
remote_ocp_clusteris set.
Major Scenario Families
| Family | How you identify it | What it covers |
|---|---|---|
| Tier0 | @pytest.mark.tier0 |
Core smoke coverage: sanity cold, sanity warm, comprehensive cold, comprehensive warm, and the post-hook retention failure scenario |
| Warm | @pytest.mark.warm |
Standard warm flows, a 2-disks/2-NICs case, remote warm, comprehensive warm, and warm copy-offload |
| Remote | @pytest.mark.remote |
Remote OpenShift destination scenarios for both cold and warm flows |
| Comprehensive | Dedicated files and classes | Advanced plan options such as static IP preservation, custom VM namespaces, PVC naming templates, labels, affinity, and node placement |
| Copy-offload | @pytest.mark.copyoffload |
XCOPY/offload coverage across disk types, snapshots, datastores, naming behavior, scale, and concurrency |
Scenario families are intentionally allowed to overlap. For example, comprehensive warm coverage is both tier0 and warm, and warm copy-offload belongs to both warm and copyoffload.
Tier0 coverage
The tier0 slice in this repository is broader than a single smoke test. It includes:
TestSanityColdMtvMigrationTestSanityWarmMtvMigrationTestColdMigrationComprehensiveTestWarmMigrationComprehensiveTestPostHookRetainFailedVm
That last case matters because it covers a failure path: the migration is expected to fail in the post-hook stage while the migrated VMs are retained for verification.
Remote coverage
The built-in remote scenarios are:
TestColdRemoteOcpTestWarmRemoteOcp
These are gated by the remote marker and the remote_ocp_cluster setting. If you do not provide that setting, pytest skips them instead of failing later during migration setup.
Comprehensive coverage
The comprehensive tests are the best place to look when you want end-to-end coverage of plan options beyond “can the VM migrate.”
A warm comprehensive scenario is configured like this:
"test_warm_migration_comprehensive": {
"virtual_machines": [
{
"name": "mtv-win2022-ip-3disks",
"source_vm_power": "on",
"guest_agent": True,
},
],
"warm_migration": True,
"target_power_state": "on",
"preserve_static_ips": True,
"vm_target_namespace": "custom-vm-namespace",
"multus_namespace": "default", # Cross-namespace NAD access
"pvc_name_template": '{{ .FileName | trimSuffix ".vmdk" | replace "_" "-" }}-{{.DiskIndex}}',
"pvc_name_template_use_generate_name": True,
"target_labels": {
"mtv-comprehensive-test": None, # None = auto-generate with session_uuid
"static-label": "static-value",
},
"target_affinity": {
"podAffinity": {
"preferredDuringSchedulingIgnoredDuringExecution": [
{
"podAffinityTerm": {
"labelSelector": {"matchLabels": {"app": "comprehensive-test"}},
"topologyKey": "kubernetes.io/hostname",
},
"weight": 75,
}
]
}
},
},
The cold comprehensive scenario follows the same idea, but adds cold-specific scheduling and naming checks such as target_node_selector, fixed PVC naming, and warm_migration: False.
Copy-offload coverage
tests/test_copyoffload_migration.py is the largest single scenario matrix in the repository. It covers:
- Thin and thick-lazy disk migrations
- Snapshot-based cases, including a 2 TB VM with snapshots
- Multi-disk and multi-datastore layouts
- Mixed XCOPY and non-XCOPY datastore behavior, including fallback paths
- RDM virtual disks
- Independent persistent and independent nonpersistent disks
- Nonconforming source VM names
- Warm copy-offload
- Scale coverage with 5 VMs in one run
- Simultaneous copy-offload plans
- Concurrent XCOPY and VDDK plans in the same suite
Warning: Copy-offload is intentionally strict about prerequisites. The suite fails early if the source provider is not vSphere or if required copy-offload fields are missing.
Practical Tip
Tip: Before running live migrations, use
uv run pytest --collect-onlyto confirm what your current provider profile and markers will collect. The repository already uses that pattern intox.toml, and the container image defaults to it.
[env.pytest-check]
commands = [
[
"uv",
"run",
"pytest",
"--setup-plan",
],
[
"uv",
"run",
"pytest",
"--collect-only",
],
]
If you only remember one rule for this page, make it this: vSphere has the broadest coverage, copy-offload is vSphere-only, warm migration is not supported for every provider, and tier0, warm, remote, and copyoffload are the markers you will use most often to slice the suite.