Volume Migration Fails with Cannot Acquire State Change Lock Error
Problem
Block Storage volume migration via openstack volume migrate fails and the volume transitions to error state. The failure occurs during the final swap phase after the data copy has already completed. The Compute Service log on the source compute host shows:
Timed out during operation: cannot acquire state change lock (held by monitor=remoteDispatchConnectGetAllDomainStats)The migration appears to complete the data copy successfully but then fails at the point where the Compute Service signals the volume attachment swap.
Environment
Private Cloud Director Virtualization - All versions
Self-Hosted Private Cloud Director Virtualization - All versions
Component: Block Storage Service, Compute Service
Cause
When a live volume migration runs, the Block Storage Service issues a swap_volume call to the Compute Service. The Compute Service responds by executing a _swap_volume operation in the Compute Service libvirt driver, which calls blockJobInfo() periodically to check whether the block copy is complete.
libvirt holds a global per-domain state lock during the execution of remoteDispatchConnectGetAllDomainStats — a routine that iterates through every running VM on the hypervisor to collect statistics. This routine is triggered by the Compute Service get_diagnostics API call and by other monitoring clients that poll the hypervisor for VM state.
If blockJobInfo() attempts to acquire this same lock while remoteDispatchConnectGetAllDomainStats is still running, the call waits up to 30 seconds. If the stats collection does not finish within 30 seconds, blockJobInfo() raises a libvirtError. Nova's original code treats this as a fatal error and marks the migration as error state, even though the underlying block copy completed successfully.
The issue is more likely to occur when:
The hypervisor is running a large number of VMs (more VMs = longer stats collection cycle = longer lock hold time)
Monitoring tooling or automation is polling
get_diagnosticsat high frequencyThe storage backend is under elevated I/O load, which slows the stats collection cycle
Diagnostics
Step 2 — Identify the source compute host
Retrieve the hypervisor where the attached VM is running.
SSH into [COMPUTE_HOST] to check the Hostagent log in Step 3.
Step 3 — Confirm the lock contention error in the Hostagent log
Search the Hostagent log on the source compute host for the failed VM UUID. Confirm the cannot acquire state change lock error is present.
The presence of remoteDispatchConnectGetAllDomainStats in the error confirms libvirt lock contention as the root cause. The block copy itself completed — the failure occurred only during the status check.
Workaround
The workaround patches the Compute Service libvirt driver on each compute host to handle lock contention gracefully. Instead of treating the 30-second timeout as a fatal error, the patched code catches the libvirtError and retries the status check after a short wait. Once remoteDispatchConnectGetAllDomainStats finishes and releases the lock, the retry succeeds and the migration completes normally.
Apply this patch to every compute host in the region where volume migration failures are occurring — not just the compute host where the last failure was observed. Any hypervisor running VMs with attached volumes can be the source host for a future migration.
Patch guest.py to Compute Hosts
Step 3 — Restart the Hostagent and libvirt services
Restart both services to load the patched file.
Restarting pf9-ostackhost briefly interrupts the Compute Service worker on this host. Confirm no critical VM operations are in flight before proceeding. Restarting libvirtd briefly disconnects libvirt from running VMs but does not affect VM uptime.
Step 5 — Test a volume migration to confirm the fix
After patching all compute hosts, retry a migration for one of the previously failing volumes.
Monitor the migration status until it reaches success and the volume migstat field clears:
A successful migration with no VolumeRebaseFailed error in the Hostagent log confirms the patch is working.
Resolution
This is a known issue that was reported as PCD-7824. The patch guest.py mentioned in this article is an interim workaround validated in production environments. Contact Platform9 Support for the latest status on the official fix or for assistance applying the patch across a large number of compute hosts.
Additional Information
Please ensure that the changes are reapplied after each PCD upgrade, as they will be reverted during the upgrade process. This will be necessary until a permanent fix is included in a future release.
Last updated
