blob: 299a0d769afef4da74dceecbd8de5ede406f1819 [file] [view]
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# VMware CBT migration architecture
This document describes the implemented Apache CloudStack architecture for
warm VMware-to-KVM migration based on VMware Changed Block Tracking (CBT).
Detailed API, database, configuration, and operational information is in
[`README.md`](README.md). KVM host preparation is documented in
[`../vmware-cbt-migration.md`](../vmware-cbt-migration.md).
## Design invariant
The KVM-side replica remains byte-compatible with the VMware source disk until
the final CBT cycle has completed. Raw VMware CBT ranges are never applied to a
disk after guest conversion has changed its layout.
The migration therefore has two distinct phases:
1. Replication: copy the initial source-equivalent baseline and apply CBT delta
ranges to it.
2. Finalization: after the source VM is powered off, apply one final delta and
run `virt-v2v` locally against the current KVM-side replica.
This avoids a second full VMware read during cutover. CloudStack does not power
off the source VM; shutdown remains an explicit operator action.
## Components
### Management server
The API commands are:
- `checkVmwareCbtMigrationPrerequisites`
- `startVmwareCbtMigration`
- `listVmwareCbtMigrations`
- `syncVmwareCbtMigration`
- `cutoverVmwareCbtMigration`
- `cancelVmwareCbtMigration`
- `deleteVmwareCbtMigration`
`VmwareCbtMigrationManagerImpl` owns migration orchestration, host and storage
validation, state transitions, cutover policy, agent command dispatch, import,
and cleanup. `VmwareCbtMigrationServiceImpl` performs VMware inventory,
snapshot, power-state, CBT enablement, and changed-area operations.
`VmwareCbtStorageTarget` classifies the selected primary storage and determines
the target representation and finalization constraints.
### Persistence
The feature persists its state in three CloudStack tables:
- `cloud.vmware_cbt_migration`: one row per migration session.
- `cloud.vmware_cbt_migration_disk`: source and target metadata for each disk,
including the current per-disk VMware `changeId`.
- `cloud.vmware_cbt_migration_cycle`: metrics and status for each delta cycle.
The schema and configuration entries are delivered through the standard
4.23.0.0-to-24.0.0 database upgrade path:
- `engine/schema/src/main/resources/META-INF/db/schema-42300to2400.sql`
- `engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade42300to2400.java`
### KVM agent
The management server sends these commands to the selected conversion host:
- `VmwareCbtPrepareCommand`: create or resolve target disks and perform the
initial VDDK full copy.
- `VmwareCbtSyncCommand`: read and apply VMware CBT ranges.
- `VmwareCbtCutoverCommand`: finalize the current replica with `virt-v2v`.
- `VmwareCbtCleanupCommand`: terminate migration-owned processes and remove
migration-owned temporary artifacts.
- `VmwareCbtRbdProbeCommand`: actively validate RBD create/write/read/delete
access for the selected pool.
The corresponding KVM wrappers are
`LibvirtVmwareCbtPrepareCommandWrapper`,
`LibvirtVmwareCbtSyncCommandWrapper`,
`LibvirtVmwareCbtCutoverCommandWrapper`,
`LibvirtVmwareCbtCleanupCommandWrapper`, and
`LibvirtVmwareCbtRbdProbeCommandWrapper`.
### User interface
The workflow is integrated into Import/Export Instances. The UI starts async
operations through the API and uses `listVmwareCbtMigrations` as the detailed
source for migration, disk, and cycle state.
## End-to-end flow
```text
VMware source VM
|
| preflight and source discovery
v
baseline VMware snapshot
|
| nbdkit-vddk full logical disk read
v
source-equivalent replica on KVM primary storage
|
| repeated VMware snapshots + QueryChangedDiskAreas
| changed ranges copied through VDDK and patched in place
v
ReadyForCutover
|
| operator powers off the VMware VM
| final CBT delta
| local virt-v2v finalization
v
CloudStack KVM import
```
### Preflight
Preflight resolves the source, destination cluster, conversion host, and
primary storage. It validates source CBT state, source disks, snapshots,
storage support, host block-copy and in-place-finalization capabilities, RBD or
LINSTOR access where applicable, Windows conversion dependencies, and optional
compute-offering sizing.
The selected conversion host reports capability through host details. The
principal gates are:
- `host.vddk.blockcopy.support`
- `host.vddk.blockcopy.inplace.finalization.support`
- `host.vddk.blockcopy.rbd.support`
- `vddk.lib.dir`
- `host.vddk.version`
- qemu and `virt-v2v` version details
### Initial synchronization
Start creates the migration and disk records, enables CBT when required,
creates a baseline VMware snapshot, prepares destination targets, and dispatches
`VmwareCbtPrepareCommand`.
The KVM agent exposes each snapshot disk with `nbdkit-vddk`. It uses
`qemu-img convert` for the general copy path and can use `nbdcopy` as an
optional accelerator for supported pre-created or NBD-bridged targets. The
result remains source-equivalent; `virt-v2v` is not run during initial sync.
After a successful copy, CloudStack records the baseline per-disk `changeId`
and removes the baseline snapshot when possible.
### Delta synchronization
Each synchronization cycle:
1. Creates a VMware snapshot.
2. Calls VMware `QueryChangedDiskAreas` from the previous per-disk `changeId`.
3. Persists the changed ranges and cycle state.
4. Opens the snapshot disk through `nbdkit-vddk` on the KVM host.
5. Copies only the changed ranges and writes them at their original byte
offsets with `qemu-io`.
6. Records changed bytes, duration, dirty rate, and the new `changeId`.
7. Removes the cycle snapshot when possible.
`VmwareCbtMigrationCutoverPolicy` evaluates the configured minimum, maximum,
and quiet-cycle thresholds and moves the migration to `ReadyForCutover` when
the policy boundary is reached.
### Cutover
Cutover is accepted only when the source VM is powered off. CloudStack runs one
final CBT cycle, then finalizes the current KVM-side replica with one of these
paths:
- `virt-v2v-in-place`;
- `virt-v2v --in-place`; or
- regular `virt-v2v -o local` for QCOW2 file targets only, when the explicit
non-in-place fallback configuration is enabled.
After finalization, CloudStack imports the disks through the shared external
KVM import path. A successful import sets the migration to `Completed`. If
finalization succeeds but import fails, the migration remains `ReadyForImport`
and a retry repeats only the import stage.
## Storage targets
| Primary storage | Replica | Initial copy | Delta writes | Finalization |
| --- | --- | --- | --- | --- |
| NFS, filesystem, shared mount | QCOW2 file | `qemu-img` | `qemu-io -f qcow2` | In-place preferred; explicitly gated local fallback supported |
| Ceph/RBD | Raw RBD image | Direct qemu RBD path or `nbdcopy` through a local NBD bridge | `qemu-io -f raw` | In-place only |
| LINSTOR | Pre-created raw DRBD block device | `nbdcopy` when available, otherwise `qemu-img` | `qemu-io -f raw` | In-place only |
For filesystem targets, temporary replicas are stored under a migration-owned
`cloudstack-cbt/<migration-uuid>/` directory. RBD and LINSTOR resources use
CloudStack-owned migration markers. Cleanup is restricted to these owned paths
and resource names.
## State model
Migration states:
```text
Created
-> InitialSync
-> Replicating
-> ReadyForCutover
-> CuttingOver
-> ReadyForImport
-> Completed
```
`Failed` and `Cancelled` are terminal states. `ReadyForImport` is deliberately
retryable.
Disk states are `Created`, `Prepared`, `Syncing`, `Ready`, and `Failed`.
Cycle states are `Created`, `QueryingChangedAreas`, `CopyingChangedBlocks`,
`Completed`, and `Failed`.
## Concurrency and cleanup
Sync and cutover commands are serialized by migration ID. Cancellation sends a
best-effort agent cleanup command before marking a non-terminal migration as
cancelled. Failed and cancelled migrations can delete their migration-owned
temporary replicas when cleanup is requested.
Deleting a completed migration is record-only. It removes CBT bookkeeping but
does not delete the imported VM, its CloudStack volumes, or finalized primary
storage artifacts.
VMware snapshots are removed after initial and delta attempts when possible.
Snapshot identifiers and cleanup errors remain visible in migration state so
operators can identify VMware-side cleanup work.
## Credential handling
Existing registered vCenter credentials are resolved from CloudStack's VMware
datacenter record. External-source credentials are accepted by sensitive API
commands and the password is stored through CloudStack's encrypted DAO field
handling until the migration no longer needs it.
On the KVM host, the password is written to a temporary owner-only file and
passed to `nbdkit` with `password=+<file>`. It is not placed directly in the
process command line. Returned errors are sanitized before persistence.
## Operational boundaries
- The operator is responsible for shutting down the source VM before cutover.
- Initial baseline transfer size depends on the extents exposed by VMware VDDK
and the source datastore; CBT optimization applies to subsequent cycles.
- Invalidated VMware CBT state requires a new baseline migration.
- RBD and LINSTOR require in-place finalization and active backend access from
the selected conversion host.
- Windows guests require a usable `virtio-win` driver bundle on that host.
- The source VMware VM remains authoritative until cutover succeeds.