For the complete documentation index, see llms.txt. This page is also available as Markdown.

VM Stuck in Migrating State After Live Migration

Problem

A virtual machine remains in MIGRATING state in the PCD UI indefinitely after a live migration attempt. No VM operations can be initiated on the instance, and the state does not transition to ACTIVE or ERROR on its own. Refreshing the PCD UI does not resolve the condition.

Environment

  • Private Cloud Director Virtualization — v2025.10 and Higher

  • Self-Hosted Private Cloud Director Virtualization — v2025.10-180 and Higher

  • Component: Compute Service

Cause

A live migration interacts with three layers that must stay in sync: the libvirt driver on the source and destination hypervisors, the Nova database (instances and migrations tables), and the OpenStack Placement service (which tracks VCPU and MEMORY_MB allocations per resource provider). When any layer falls out of sync, the VM can become permanently stuck in task_state = migrating.

Two distinct failure modes produce this symptom:

  • Migration accepted but failed before starting (VM still on source) — the destination compute service accepted the migration but failed before memory transfer began. The migration record is in accepted status. An orphaned Placement allocation exists under the migration UUID pointing to the destination RP.

  • Migration completed at hypervisor level but management plane desynced (VM on destination) — the VM successfully transferred to the destination at the libvirt level, but the Nova conductor did not process the completion event. The migration record is stuck in running status. The Nova instances table still references the source host, and the Placement service holds a stale allocation under the migration UUID on the source RP while the instance UUID has zero allocation.

Diagnostics

1. Get the libvirt domain name for the VM:

OpenStack CLI
$ openstack server show <VM_UUID> -c OS-EXT-SRV-ATTR:instance_name

2. SSH into both the source and destination compute hosts and check whether the VM domain is running:

3. Confirm the migration record status:

Self-Hosted only: The Nova DB query below requires direct access to the control plane. SaaS customers cannot perform this step independently — contact Platform9 Support to have this completed on their behalf.

Retrieve the database password and MySQL pod IP, then open an interactive session:

Note the uuid value from the output — referred to as <MIGRATION_UUID> throughout the Workaround steps.

Use the migration status and the virsh result to identify the correct method:

Migration status

VM location (virsh)

Method

accepted

Source host only

running

Destination host

If the checks above match, proceed to the Workaround.

Workaround

Apply the method that matches the diagnostic results above.

Method 1 — Migration Failed Before Completing (VM on Source)

The migration record is in accepted status and the VM is still running on the source host.

Self-Hosted only: Steps 1 and 3 require direct access to the control plane. SaaS customers cannot perform these steps independently — contact Platform9 Support to have this completed on their behalf.

1

Step 1 — Mark the Migration Record as Error

Retrieve database credentials and open a Nova DB session:

Verify:

2

Step 2 — Reset the VM Task State

Verify:

3

Step 3 — Delete the Orphaned Migration Placement Allocation

The migration UUID holds a provisional Placement allocation created when the migration was accepted. Remove this orphaned allocation:

Verify the allocation is removed:

An empty table confirms the orphaned allocation has been cleared.

4

Step 4 — Verify Final State

The VM should show status = ACTIVE, task_state = None, and host pointing to the source compute node. The VM is now fully recovered and available for operations.

Method 2 — Migration Completed at Hypervisor Level (VM on Destination)

The migration record is stuck in running status. The VM is running on the destination hypervisor, but the Nova instances table still points to the source host and the Placement service holds a stale allocation for the migration UUID on the source RP while the instance UUID has zero allocation.

Self-Hosted only: This entire procedure requires direct access to the control plane. SaaS customers cannot perform these steps independently — contact Platform9 Support to have this completed on their behalf.

1

Step 1 — Verify VM Accessibility on the Destination

SSH into the destination compute host and confirm the VM domain is running:

Also confirm the VM is reachable over the network from the assigned IP before proceeding.

2

Step 2 — Retrieve Database Credentials and Take a Nova Database Backup

Retrieve the database password and MySQL pod IP. The $DB_PASS and $IP shell variables set here are reused in Steps 4 and 8.

Take a backup of the relevant Nova tables:

3

Step 3 — Collect Required Values

Collect all variable values needed for subsequent steps before making any changes.

Get the destination RP UUID (this value is also used as the node field in the Nova instances table):

Get the project ID, user ID, and flavor resource requirements for the VM:

Note the vcpus and ram (in MB) values from the flavor output — these are the <VCPU_COUNT> and <MEMORY_MB> values used in Step 6.

Confirm the destination RP has sufficient remaining capacity:

Verify the destination RP can accommodate the VM's VCPU and MEMORY_MB requirements before proceeding.

4

Step 4 — Update the Instance Record in Nova DB

Update the instances table to point to the destination host. Use <DEST_RP_UUID> as the node value (the Nova instances.node field stores the compute node's RP UUID).

Connect to the Nova DB using the credentials retrieved in Step 2:

Verify:

5

Step 5 — Reset the VM State via OpenStack API

Verify:

6

Step 6 — Set the Instance Placement Allocation on the Destination RP

Create the correct Placement allocation for the instance UUID on the destination RP. Include all resources tracked by Placement for the VM's flavor (at minimum VCPU and MEMORY_MB; add DISK_GB if local storage is tracked in the environment):

Verify the instance allocation is now on the destination RP:

The output should show <DEST_RP_UUID> with the correct VCPU and MEMORY_MB values.

7

Step 7 — Delete the Stale Migration Placement Allocation

Remove the migration consumer's orphaned allocation from the source RP:

Verify the allocation is removed:

An empty table confirms the stale source RP allocation has been cleared.

8

Step 8 — Mark the Migration Record as Completed

With the instances table and Placement state now consistent with the destination, mark the migration as completed.

Connect to the Nova DB using the credentials retrieved in Step 2:

Verify:

9

Step 9 — Final Verification

Run all three checks to confirm a clean recovery:

Expected results:

  • status = ACTIVE, task_state = None, host = [DEST_HOSTNAME], progress = 0

  • Instance allocation references [DEST_RP_UUID] with correct resource values

  • Migration allocation returns an empty table

If these steps prove insufficient to resolve the issue, reach out to the Platform9 Support team for additional assistance.

Additional Information

Related Articles:

Last updated