(Example: Moving a Windows 10 VM from a3520 → a1550)
This note records how we moved win10-cht-pro-basic from a3520 (CentOS 7) to a1550 (Ubuntu 24), including common operations, the cold-migration flow, XML adjustments, RDP/console access, ways to get the guest IP, and frequent errors. Reuse this as a checklist for future cases.
1) Handy virsh Command Cheat Sheet
# Start / graceful shutdown / hard power-off
virsh start <vm>
virsh shutdown <vm>
virsh destroy <vm> # like pulling the plug (last resort)
# Status / info
virsh list --all
virsh domstate <vm>
virsh dominfo <vm>
virsh domiflist <vm> # NICs/MAC/bridge
virsh domifaddr <vm> # requires guest agent or DHCP leases
# Edit / export XML
virsh edit <vm>
virsh dumpxml <vm> > /tmp/<vm>.xml
2) Cold Migration (recommended; safest across versions)
CentOS 7 ↔ Ubuntu 24 have large libvirt/QEMU version gaps. Avoid live migration. Do a cold move: power off → export → copy disks → fix XML → import.
1) On the source (a3520): shut down and export XML
virsh shutdown win10-cht-pro-basic
virsh dumpxml win10-cht-pro-basic > /tmp/win10.xml
2) Copy the virtual disk to the target (a1550)
Find the disk path:
virsh domblklist win10-cht-pro-basic
# e.g. /var/lib/libvirt/images/win10-cht-pro-basic.qcow2
Copy it:
rsync -avhP /var/lib/libvirt/images/win10-cht-pro-basic.qcow2 \
root@a1550:/var/lib/libvirt/images/
3) On a1550, adjust the XML (4 key items)
(A) QEMU binary path (Ubuntu 24)
<emulator>/usr/bin/qemu-system-x86_64</emulator>
If the source XML contains
/usr/libexec/qemu-kvm, it will fail on Ubuntu; change to the line above.
(B) CPU compatibility
Pick one of these for cross-host safety:
- host-model (better performance)
<cpu mode='host-model' check='none'/>
- qemu64 (most conservative; you may also disable svm/vmx if needed)
<cpu mode='custom' match='exact' check='none'>
<model fallback='allow'>qemu64</model>
<!-- If you hit "requires: svm", add these: -->
<!-- <feature policy='disable' name='svm'/> -->
<!-- <feature policy='disable' name='vmx'/> -->
</cpu>
(C) Memory size (KiB)
<memory unit='KiB'>4194304</memory>
<currentMemory unit='KiB'>4194304</currentMemory>
4GB = 4194304, 8GB = 8388608. For Windows 10, 4–8GB is recommended.
(D) Bridge name
Ensure the target’s bridge exists (e.g., br.eno1.5 or br0):
<interface type='bridge'>
<source bridge='br.eno1.5'/>
<model type='rtl8139'/> <!-- can switch to virtio later -->
</interface>
(E) Machine type (optional)
If you hit old machine-type compatibility issues, switch to q35:
<os>
<type arch='x86_64' machine='q35'>hvm</type>
</os>
4) Define and start
virsh define /tmp/win10.xml
virsh start win10-cht-pro-basic
virsh dominfo win10-cht-pro-basic
3) Getting the Guest IP
Method 1: Query ARP/neighbor by MAC (best for bridged networks)
# Get the MAC first
virsh domiflist win10-cht-pro-basic
# Suppose MAC=52:54:00:65:35:46, bridge=br.eno1.5
ip neigh show dev br.eno1.5 | grep -i 52:54:00:65:35:46 | awk '{print $1}'
If the table hasn’t learned it yet, do a quick ping/scan on the subnet, then retry.
Method 2: QEMU Guest Agent (best long-term)
Add a channel in the XML (if not present):
<channel type='unix'>
<source mode='bind'/>
<target type='virtio' name='org.qemu.guest_agent.0'/>
</channel>
Install qemu-guest-agent in Windows, then:
virsh domifaddr --source agent win10-cht-pro-basic
Method 3: NAT networks (libvirt default)
virsh net-dhcp-leases default
4) RDP CredSSP Error (“Encryption Oracle Remediation”)
Symptom: RDP shows the CredSSP remediation error.
Best fix (server-side)
- Log in via console (VNC/SPICE).
- Run Windows Update.
- Set mitigation (admin PowerShell):
New-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\CredSSP\Parameters' -Force | Out-Null Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\CredSSP\Parameters' -Name AllowEncryptionOracle -Type DWord -Value 1 - Ensure NLA is enabled:
SystemPropertiesRemote.exe→ tick “Allow connections only from computers running NLA…”.
Temporary client-side workaround (trusted network, short-term only):
# Run on your RDP client as Administrator
New-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\CredSSP\Parameters' -Force | Out-Null
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\CredSSP\Parameters' -Name AllowEncryptionOracle -Type DWord -Value 2
gpupdate /force
After connecting and fixing the server, revert the client.
5) No GUI on the Host? Open a Console (SPICE/VNC)
A. SSH tunnel to VNC (safest)
If virsh domdisplay shows vnc://localhost:1, the port is 5901:
# On your laptop/desktop
ssh -L 5901:127.0.0.1:5901 root@a1550
# Then connect your VNC client to 127.0.0.1:5901
B. Bind VNC to an internal IP (trusted LAN only)
- Allow libvirt to listen externally:
sed -i 's/^#\?vnc_listen.*/vnc_listen = "0.0.0.0"/' /etc/libvirt/qemu.conf
systemctl restart libvirtd
- In the VM XML:
<graphics type='vnc' autoport='yes' listen='192.168.100.15' passwd='StrongPass!'>
<listen type='address' address='192.168.100.15'/>
</graphics>
- Open 59xx on the firewall and connect.
If switching from SPICE to VNC, remove SPICE-specific devices (
<channel type='spicevmc'>,<redirdev type='spicevmc'>,video qxl,audio spice) and usevideo virtio/audio none. Otherwise you’ll see “chardev ‘spicevmc’ not supported without spice graphics”.
6) Performance & Compatibility Tips (Windows Guest)
- Switch disk/NIC to virtio for a big boost (install Windows virtio drivers first to avoid BSOD)
- Disk:
<target dev='vda' bus='virtio'/> - NIC:
<model type='virtio'/>
- Disk:
- Machine type: modern guests prefer
q35. If your old VM usedi440fx, keep it unless you hit issues. - CPU: prefer
host-model; fall back toqemu64for rescue. - vCPU/RAM: Windows 10 runs better with ≥2 vCPU and ≥4GB RAM (8GB is smoother for desktop use).
7) Common Errors & Fixes
- Cannot check QEMU binary /usr/libexec/qemu-kvm
→ On Ubuntu use/usr/bin/qemu-system-x86_64; change<emulator>. - Host CPU does not provide required features: svm
→ Source carried AMDsvmwhile the target is Intel (vmx). Usehost-modelorqemu64, and if needed disablesvmin the<cpu>block. - VNC only shows localhost
→ Use SSH tunneling, or setvnc_listeninqemu.confand bind<graphics>to your LAN IP. - RDP CredSSP error
→ See section 4; fix the server, use client downgrade only temporarily. - Missing disk/NIC
→ Verify<source file=…>paths/permissions (libvirt-qemu:kvm,chmod 640) and that the bridge exists.
8) (Optional) Live Migration Notes
Success depends on shared storage, similar CPUs, close libvirt/QEMU versions, and identical bridge names.
- Example (with shared storage):
virsh migrate --live --persistent --undefinesource \ <vm> qemu+ssh://a1550/system - Without shared storage you can use
--copy-storage-all, but it’s slow and risky across wide version gaps—avoid for production in this scenario.
9) Key Changes in This Case (summary)
<emulator>→/usr/bin/qemu-system-x86_64<cpu>→host-model(orqemu64withsvmdisabled if needed)<memory>→ raise to 4–8GB<interface>→ ensure target bridge exists (e.g.,br.eno1.5)- (optional)
<type machine='q35'> - When switching SPICE→VNC: remove SPICE devices, set
video virtio, configurevnc_listen