Migration Toolkit for Virtualization¶
Migration Toolkit for Virtualization Documentation
The Migration Toolkit for Virtualization (MTV) enables migration of virtual machines from VMware vSphere, Red Hat Virtualization, OpenStack, or other OpenShift Virtualization clusters into your OpenShift Virtualization environment. It provides a web-based wizard for planning and executing migrations at scale.
Prerequisites¶
- OpenShift Virtualization operator installed and configured
- Storage configured with a default StorageClass (RWX recommended)
- Network connectivity between the OpenShift cluster and the source hypervisor (vCenter, RHV Manager, etc.)
- Cluster administrator privileges
- If performing OVA conversion, an NFS share is required
- VMware Virtual Disk Development Kit (VDDK) image — see Obtaining the VDDK below
Obtaining the VDDK¶
Action Required Before Migration
Broadcom withdrew public VDDK downloads in August 2026. Access is now available only through select TAP (Technology Alliance Program) partners. Customer support tickets are no longer a reliable path to obtain the archive. Confirm you already have a VDDK archive (or a TAP partner path) before scoping warm or vSAN migrations.
VDDK is optional for cold migrations of non-vSAN VMs (transfer is slower without it) and required for warm migrations and vSAN-backed VMs. The virt-v2v tool always performs guest conversion regardless of whether VDDK is configured. Cold migrations of non-vSAN VMs can proceed without VDDK at reduced transfer speeds.
If you cannot obtain VDDK and the source VMs sit on a supported SAN that OpenShift also reaches via CSI, storage copy offload can migrate those disks without VDDK (and usually much faster than the non-VDDK network path). Offload does not cover vSAN-backed VMs.
Red Hat Engineering is currently working on an open source solution. (as of 9/10)
Install the Operator via WebUI¶
- Go to Ecosystem -> Software Catalog -> filter for "Migration Toolkit for Virtualization" -> click the tile
- Click Install
- Leave all the defaults (installs to
openshift-mtvnamespace) and click Install - Wait for the Operator to install
- Go to Ecosystem -> Installed Operators -> click "Migration Toolkit for Virtualization Operator"
- Click on the "ForkliftController" tab and then click "Create ForkliftController"
- Leave all the defaults and click Create
- Wait for all MTV pods to reach Running state
Install the Operator via YAML (click to expand)
apiVersion: v1
kind: Namespace
metadata:
name: openshift-mtv
---
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
name: migration
namespace: openshift-mtv
spec:
targetNamespaces:
- openshift-mtv
---
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: mtv-operator
namespace: openshift-mtv
spec:
channel: release-v2.12
installPlanApproval: Automatic
name: mtv-operator
source: redhat-operators
sourceNamespace: openshift-marketplace
Note
The MTV channel is version-specific and may not match your environment. Verify the default channel before applying: oc get packagemanifest mtv-operator -o jsonpath='{.status.defaultChannel}'
Wait for the operator:
The PHASE should show Succeeded.
Create the ForkliftController¶
apiVersion: forklift.konveyor.io/v1beta1
kind: ForkliftController
metadata:
name: forklift-controller
namespace: openshift-mtv
spec:
olm_managed: true
feature_ui_plugin: "true"
feature_validation: "true"
feature_volume_populator: "true"
Verify¶
All pods should be Running. The Migration menu item will appear in the left navigation of the WebUI.
Add a Source Provider¶
A source provider is the hypervisor environment you are migrating VMs from. A default host provider (representing the local OpenShift Virtualization cluster) is created automatically.
Add vSphere Provider via WebUI¶
- Go to Migration -> Providers for virtualization
- Click "Create Provider"
- Select "vSphere"
-
Fill in the details:
- Name: a friendly name for this provider
- vCenter host or ESXi host: the FQDN or IP of the vCenter server
- Username: a vCenter user with at least read access to the VMs
- Password: the vCenter password
- Certificate validation — MTV 2.12 supports three options:
- Use a custom CA certificate — paste or upload the vCenter CA cert
- Use the system CA certificate — uses the cluster's trusted CA bundle
- Skip certificate validation (recommended for POC) — disables TLS verification for the vCenter connection
- VDDK init image: upload the VDDK archive or paste an existing image URL (see Upload the VDDK Image via WebUI)
-
Click Create
Add vSphere Provider via YAML¶
-
Create the vCenter credentials secret:
-
Create the Provider resource:
apiVersion: forklift.konveyor.io/v1beta1 kind: Provider metadata: name: vsphere-source namespace: openshift-mtv spec: type: vsphere url: "https://{{ vcenter_fqdn }}/sdk" secret: name: vsphere-credentials namespace: openshift-mtv settings: vddkInitImage: {{ registry_host }}/openshift-mtv/vddk:latest sdkEndpoint: vcenter -
Verify the provider is ready:
The
READYcolumn should showTrue.
vSphere Provider Inventory — Why Only a Subset of VMs Appears¶
The MTV vSphere provider connects to vCenter, not to a single cluster. The list of virtual machines it shows is whatever the service account is allowed to enumerate through vCenter's VM folder tree. That is not the same as "VMs running on this cluster," and it is not the same as what the vSphere Client shows under Hosts and Clusters.
Typical observed behavior:
| Permission scope | VMs visible in MTV |
|---|---|
| Cluster-level Admin | A small subset (e.g. 8), spread across the ESXi hosts in that cluster |
| Datacenter-level Admin (propagate) | All VMs in that datacenter, including VMs on other clusters |
| Cluster + specific VM folders + datastores + networks | Only the intended cluster's VMs, without exposing other clusters |
This behavior is expected.
How MTV Discovers VMs¶
MTV (Forklift) logs into vCenter with the provider credentials and walks inventory via the vSphere SOAP API (PropertyCollector). It starts at the vCenter root folder and follows two different trees under the datacenter:
| vCenter tree | What MTV uses it for |
|---|---|
Hosts and Clusters (hostFolder) |
Clusters, ESXi hosts |
VMs and Templates (vmFolder) |
Virtual machines |
| Storage / Networking folders | Datastores, networks, switches |
Virtual machines are not children of the cluster in vCenter's inventory model. They run on hosts in the cluster, but their inventory location is almost always a VM folder at the datacenter level (for example Discovered virtual machine or an application folder).
MTV lists a VM only if it can walk down to that VM through VMs and Templates (or a vApp). It does not ask each host "which VMs are on you?"
Therefore:
- Cluster Admin is enough to see hosts and a few VMs whose inventory parent is actually under the cluster (resource pool, vApp, or a reachable folder). It is not enough to list VMs that live in datacenter VM folders, even if those VMs are running on that cluster's hosts.
- Datacenter Admin with propagate unlocks all four trees (VM folders, clusters, datastores, networks) — which is why MTV then shows VMs on other clusters too.
MTV also hides templates and incomplete "ghost" VMs (no UUID and no host). That usually accounts for a few objects, not most of the inventory.
Why the vSphere Client and MTV Disagree¶
The vSphere HTML5 Client and MTV do not use the same view:
| Tool | Path used | Result with cluster-level Admin |
|---|---|---|
| vSphere Client (Hosts and Clusters) | VMs shown as related to hosts/cluster — VMs inherit rights from cluster/host | All ~127 VMs can appear |
| MTV provider inventory | Walk of VMs and Templates folders | Only VMs in folders the account can enumerate |
Seeing every VM in the vSphere Client with a service account does not mean MTV can inventory them. Confirm by logging in as the same user stored in the MTV provider secret and switching to VMs and Templates, not Hosts and Clusters.
Recommended Permission Layout¶
Do not grant Admin on the whole datacenter if other clusters must stay hidden. Use a dedicated MTV role with the documented VMware privileges (interaction, provisioning, snapshot, datastore browse/low-level file, session validate, crypto if disks are encrypted).
| vCenter object | Permission | Propagate |
|---|---|---|
| vCenter root | Read-only | No |
| Datacenter | Read-only | No — lets MTV traverse without inheriting every cluster, folder, datastore, and network |
| Intended cluster | MTV role (or Admin) | Yes — covers hosts and compute |
| VM folder(s) containing the target VMs | MTV role (or Admin) | Yes — this grant is what makes VMs appear in MTV |
| Datastores used by those VMs | MTV role (or Admin) | Yes |
| Networks / distributed switches / port groups | MTV role (or Admin) | Yes |
If the VMs are spread across many folders, either grant on each folder or move in-scope VMs into one dedicated folder and grant only there.
Warning
Do not grant rights only on the VM objects. MTV still needs parent folders, datastores, and networks. Red Hat requires rights on the objects a VM uses, not only on the VM itself.
After changing permissions, wait for MTV to refresh provider inventory (or reconnect/reconcile the provider) and confirm the VM count.
How to Verify¶
- Log into the vSphere Client as the exact account in the MTV provider secret
- Open VMs and Templates (not Hosts and Clusters)
- Compare a VM that MTV shows vs. one it does not — the missing VM will typically sit in a datacenter VM folder that has no grant for this account
Optionally check MTV inventory logs for skipped or permission-related objects:
oc logs -n openshift-mtv deploy/forklift-controller -c inventory \
| grep -E 'ghost VM|Skipping template|NoPermission|permission'
On newer MTV versions, also review the Provider resource for reported missing vSphere privileges:
Set Up the VMware Virtual Disk Development Kit (VDDK)¶
It is strongly recommended that MTV be used with the VMware Virtual Disk Development Kit (VDDK) SDK when transferring virtual disks from VMware vSphere. Without the VDDK, disk transfer is significantly slower. The virt-v2v tool always performs guest conversion regardless of whether VDDK is configured.
Download the VDDK archive from VMware, then either upload it through the MTV WebUI (MTV builds the init image for you) or build and push the container image yourself with podman.
VMware License
Storing the VDDK image in a public registry might violate the VMware license terms.
Obtain VDDK¶
Match the VDDK version to your source vSphere (vCenter/ESXi) version. Broadcom aligns VDDK version numbers with vSphere (for example, use VDDK 8.0.x with vSphere 8.0).
VDDK Availability (September 2026)
Public VDDK downloads were withdrawn by Broadcom in August 2026. Access is now limited to select TAP (Technology Alliance Program) partners. Customer support tickets are no longer a reliable path. If you do not already have a VDDK archive, confirm a TAP partner path before planning warm or vSAN migrations. For supported SAN-backed cold migrations, storage copy offload is an alternative that does not require VDDK.
If you have an existing VDDK archive (VMware-vix-disklib-<version>.x86_64.tar.gz), proceed to Upload the VDDK Image via WebUI or Build and Push the VDDK Image via CLI.
Upload the VDDK Image via WebUI¶
The MTV console can upload the VDDK archive and build the init image when you create or edit a vSphere provider. This is the simplest path for POC environments.
- Go to Migration -> Providers for virtualization
- Click Create Provider (or open an existing vSphere provider and edit it)
- Select vSphere / VMware
- Fill in the provider details (name, URL, credentials, certificate options)
-
In the VDDK init image section, either:
- Upload the archive (recommended for POC):
- Click Browse next to the VDDK init image archive field
- Select your downloaded
VMware-vix-disklib-<version>.x86_64.tar.gzand click Select - Click Upload
- Wait for the upload to finish — MTV builds the init image and populates the image URL
- Use an existing image: paste the image path (for example,
image-registry.openshift-image-registry.svc:5000/openshift-mtv/vddk:latest) 6. Click Create provider (or save the edit) 7. Wait until the provider status isReady(this can take a few minutes while the image is built)
- Upload the archive (recommended for POC):
Tip
Prefer creating the provider in the openshift-mtv project so the built VDDK image lands in that namespace. If you migrate VMs into other namespaces, grant those namespaces pull access as described in Allow Target Namespaces to Pull the VDDK Image.
Build and Push the VDDK Image via CLI¶
Use this path when you need to push the VDDK image to a specific registry yourself, or when you want to set a cluster-wide default on the ForkliftController.
Prerequisites¶
- OpenShift image registry (internal or external accessible from OpenShift Virtualization)
podmaninstalled- You are working on a file system that preserves symbolic links (symlinks) — the VDDK package contains symlinks
Create a Working Directory¶
Extract the VDDK Archive¶
Verify the extracted directory:
Create the VDDK Container Image¶
Create a Dockerfile:
cat > Dockerfile <<'EOF'
FROM registry.access.redhat.com/ubi8/ubi-minimal
USER 1001
COPY vmware-vix-disklib-distrib /vmware-vix-disklib-distrib
RUN mkdir -p /opt
ENTRYPOINT ["cp", "-r", "/vmware-vix-disklib-distrib", "/opt"]
EOF
Push to the OpenShift Internal Registry¶
Enable the default registry route if it is not already exposed:
oc patch configs.imageregistry.operator.openshift.io/cluster --type merge \
-p '{"spec":{"defaultRoute":true}}'
Get the registry hostname:
Create the target namespace (if it does not already exist):
Authenticate podman to the internal registry:
Build and push the VDDK image:
podman build . -t $REGISTRY/openshift-mtv/vddk:latest
podman push $REGISTRY/openshift-mtv/vddk:latest --tls-verify=false
Ensure the image is accessible to your OpenShift Virtualization environment. If you are using an external registry, verify that OpenShift can pull from it.
You can also set the VDDK image URL on a vSphere provider's settings.vddkInitImage field (see Add vSphere Provider via YAML) instead of building a separate init image.
Allow Target Namespaces to Pull the VDDK Image¶
MTV runs VDDK init and disk-transfer pods in the target namespace of the migration plan (where the VMs are created), not in openshift-mtv. When the VDDK image is stored in the OpenShift internal registry under openshift-mtv, those pods cannot pull it until service accounts in the target namespace are granted the system:image-puller role in the image's namespace.
Single target namespace¶
Grant pull access to all service accounts in the migration target namespace (recommended — MTV/CDI may use more than the default service account):
TARGET_NAMESPACE={{ target_namespace }}
oc adm policy add-role-to-group system:image-puller \
system:serviceaccounts:${TARGET_NAMESPACE} \
-n openshift-mtv
Or grant pull access to only the default service account:
oc adm policy add-role-to-user system:image-puller \
system:serviceaccount:${TARGET_NAMESPACE}:default \
-n openshift-mtv
Repeat for each additional target namespace that will receive migrated VMs.
All namespaces (POC / lab)¶
To allow service accounts in every namespace to pull the VDDK image:
Warning
Granting system:image-puller to system:serviceaccounts lets any service account on the cluster pull images from openshift-mtv. Prefer the per-namespace form outside of POC environments.
Verify the role bindings:
Storage Copy Offload¶
Storage copy offload migrates vSphere disks by cloning on the storage array (VAAI / vmkfstools / XCOPY) instead of streaming disk data over the IP network through VDDK or the slower non-VDDK path. MTV uses the vsphere-xcopy-volume-populator Volume Populator for this path.
Use offload when:
- You cannot obtain a VDDK archive, or you want faster SAN-backed migrations
- Source VMs are on a supported array that OpenShift Virtualization also consumes via CSI
- You are not migrating vSAN-backed VMs (vSAN still requires VDDK)
When offload does not apply
Many POC labs place OpenShift on different storage than vSphere (for example local disks or ODF-only). Offload needs the same supported array (or array family with a working CSI path) reachable from both ESXi and the OpenShift workers. If that is not true, stay on the network transfer path (with or without VDDK).
Prerequisites¶
- MTV 2.9+ with copy offload available (this guide uses the
release-v2.12channel) - A configured vSphere provider
- A working CSI driver on OpenShift for one of the supported products:
| Vendor | storageVendorProduct value |
|---|---|
| Hitachi Vantara | vantara |
| NetApp ONTAP | ontap |
| Pure Storage FlashArray | pureFlashArray |
| Dell PowerMax | powermax |
| Dell PowerFlex | powerflex |
| Dell PowerStore | powerstore |
| HPE 3PAR / Primera | primera3par |
| Infinidat InfiniBox | infinibox |
| IBM FlashSystem | flashsystem |
- Extra vSphere privileges for offload (suggested role name
StorageOffloader): Global Settings; Datastore Browse / Low level file operations; Host Configuration Advanced settings, Query patch, and Storage partition configuration - Delete preexisting snapshots on source VMs before performance-sensitive offload runs (warm-migration snapshots created by MTV itself are fine; older snapshots force a slower software clone)
Official planning and procedure: About storage copy offload and Running a VMware vSphere migration by using storage copy offload.
Enable the Feature¶
oc patch forkliftcontrollers.forklift.konveyor.io forklift-controller \
--type merge -p '{"spec":{"feature_copy_offload":"true"}}' -n openshift-mtv
Or set feature_copy_offload: "true" when you create the ForkliftController.
Configure a Storage Map for Offload¶
- Create a
Secretinopenshift-mtvwith the vendor-specific keys from the MTV docs (hostname, credentials, and product fields such asONTAP_SVMorPOWERMAX_SYMMETRIX_ID). - Create a
StorageMapthat references that secret and product:
apiVersion: forklift.konveyor.io/v1beta1
kind: StorageMap
metadata:
name: copy-offload
namespace: openshift-mtv
spec:
map:
- destination:
accessMode: ReadWriteMany
storageClass: {{ storage_class }}
offloadPlugin:
vsphereXcopyConfig:
secretRef: {{ storage_offload_secret }}
storageVendorProduct: {{ storage_vendor_product }}
source:
id: {{ datastore_moref }}
provider:
destination:
apiVersion: forklift.konveyor.io/v1beta1
kind: Provider
name: host
namespace: openshift-mtv
source:
apiVersion: forklift.konveyor.io/v1beta1
kind: Provider
name: vsphere-source
namespace: openshift-mtv
In the WebUI, the same options appear when you create or edit a storage map: Offload plugin = vSphere XCOPY, plus the storage secret and storage product.
- Point the migration plan at that
StorageMap(do not add a second mapping that uses VDDK/CDI for the same plan).
Do not mix VDDK and offload in one plan
Every storage pair in a plan must either include copy-offload details (Secret + product) or omit them entirely. Mixing CDI/VDDK mappings with Volume Populator offload mappings causes the plan to fail.
ESXi Access for Offload¶
Offload runs vmkfstools on the ESXi hosts. MTV supports:
- VIB (default) — install the MTV
vmkfstoolswrapper VIB on every ESXi host used for offload - SSH — configure automatic or manually generated offload SSH keys for the vSphere provider
Follow the VIB or SSH setup steps in the official offload planning topic. Prefer VIB for POC unless SSH is already required by site policy.
Create a Migration Plan¶
Once providers are configured, create a migration plan using the WebUI wizard:
- Go to Migration -> Plans for virtualization
- Click "Create Plan"
- Select the source provider (e.g.,
vsphere-source) - Select the target provider (
host— the local OpenShift Virtualization cluster) -
Select the VMs to migrate
ESXi NFC Connection Limit
If migrating more than 10 VMs from the same ESXi host in a single plan, increase the NFC service memory on that host (
nfcsvc maxMemoryto1000000000in/etc/vmware/hostd/config.xml) and restarthostd. The default NFC service supports only 10 parallel connections. -
Configure network mappings (source network -> target network)
- Configure storage mappings (source datastore -> target StorageClass)
- Review and click "Create"
Migration Types¶
| Type | Description |
|---|---|
| Cold | VM is powered off before migration. Simplest and most reliable. |
| Warm | Pre-copies data while VM is running, then does a final cutover (less downtime) |
Start with Cold Migrations
For POC environments, start with cold migrations. They are simpler to troubleshoot and do not require VMware Changed Block Tracking (CBT).
Migrations can run without VDDK but will use a slower disk-transfer path. VDDK is strongly recommended for acceptable transfer speeds. See Obtaining the VDDK. On a supported SAN shared with OpenShift, prefer storage copy offload instead of the slow non-VDDK path.
Warm Migration Prerequisites
Warm migrations pre-copy disk data while the VM is still running. They require:
- VDDK image must be configured on the vSphere Provider (
settings.vddkInitImage) - Changed Block Tracking (CBT) must be enabled on each source VM and each VM disk
- VMware Tools must be installed on the source VM
Run the Migration¶
- Go to Migration -> Plans for virtualization
- Click the "Start" button on your plan
- Monitor progress in the plan details view
Each VM will go through: Pending -> Disk Transfer -> Convert -> Succeeded
Post-Migration¶
After migration completes:
- Verify the VM is running in Virtualization -> VirtualMachines
- Check that networking and storage are attached correctly
- Remove VMware Tools from the guest OS (if applicable)
- Install the QEMU guest agent for better integration with OpenShift Virtualization