Before proceeding with the migration, ensure both source and destination hosts meet these requirements:
- Identical or compatible kernel versions
- Same versions of libvirt and QEMU
- Identical network bridge configuration
- Available LVM volume groups with sufficient space
On the source host, gather critical information about your VM:
# List all VMs
virsh list --all
# Dump VM configuration to XML
virsh dumpxml vm_name > vm_name.xml
# Check block device paths
virsh domblklist vm_name
For each LVM volume used by the VM, create snapshots and transfer them:
# Create LVM snapshot on source host
lvcreate -s -n vm_disk_snapshot -L 10G /dev/vg_name/vm_disk
# Transfer snapshot to destination host
dd if=/dev/vg_name/vm_disk_snapshot | ssh root@destination_host "dd of=/dev/vg_name/vm_disk"
Update the XML file to reflect new paths on destination host:
<disk type='block' device='disk'>
<driver name='qemu' type='raw'/>
<source dev='/dev/destination_vg/vm_disk'/>
<target dev='vda' bus='virtio'/>
</disk>
# Copy XML file to destination host
scp vm_name.xml root@destination_host:/etc/libvirt/qemu/
# Define the VM
virsh define /etc/libvirt/qemu/vm_name.xml
# Verify configuration
virsh edit vm_name
For more complex scenarios, consider these options:
- Virsh migrate:
virsh migrate --live vm_name qemu+ssh://destination_host/system
- Storage migration:
virsh migrate --copy-storage-all vm_name qemu+ssh://destination_host/system
- Offline backup/restore: Use virt-manager's export/import feature
Common pitfalls and their solutions:
# Error: "Unable to resolve address"
# Solution: Ensure /etc/hosts contains correct entries
# Error: "Permission denied"
# Solution: Verify SELinux contexts on LVM volumes:
restorecon -R /dev/vg_name/
When migrating KVM guests between hosts with LVM-backed storage, we need to handle three core components:
- The virtual disk data (LVM logical volumes)
- The VM configuration (libvirt XML)
- Network bridge configuration
1. Transferring LVM Volumes
First, identify the LVM volumes on the source host:
# On source host
lvdisplay | grep "LV Path"
sudo lvs -o lv_name,vg_name,size
Then transfer them to the destination host. For offline migration, you can use either dd
or lvconvert
:
# Using dd (simple but slower)
sudo dd if=/dev/vg_name/lv_name | ssh user@destination_host "dd of=/dev/vg_name/lv_name"
# Using LVM's native tools (faster)
sudo lvconvert --merge vg_name/lv_snapshot
2. Handling the VM Configuration
Export the XML configuration from the source host:
virsh dumpxml vm_name > vm_name.xml
Key elements to modify in the XML before importing:
<disk type='block' device='disk'>
<source dev='/dev/vg_name/lv_name'/>
</disk>
3. Finalizing the Migration
On the destination host, define and start the VM:
virsh define vm_name.xml
virsh start vm_name
For larger environments, consider these more scalable methods:
# Using virt-v2v for conversion between hosts
virt-v2v -i libvirt -ic qemu:///system vm_name -o local -os /var/lib/libvirt/images
# Using shared storage (NFS/iSCSI)
<disk type='network' device='disk'>
<source protocol='nbd' name='vm_image'>
<host name='storage_host' port='10809'/>
</source>
</disk>
- Permission errors: Ensure consistent UID/GID for qemu processes
- Network connectivity: Verify bridge names match between hosts
- Storage paths: Double-check LVM volume names in the XML
For automated migrations in production environments, consider using tools like virt-manager
or writing a custom script using libvirt's Python bindings.