Problema
Muchas organizaciones están dejando atrás Hyper‑V para adoptar una solución basada en KVM como Proxmox. El reto no es mover una o dos máquinas, sino cientos de VMs con diferentes sistemas operativos, tamaños de disco y configuraciones de red. En un entorno de producción, la migración debe minimizar el tiempo de inactividad, preservar backups existentes y evitar la reconfiguración manual de cada VM. La falta de una herramienta “one‑click” que convierta VHDX a los formatos nativos de Proxmox obliga a combinar varias utilidades y a orquestar procesos en lote.
Causa
- Formato de disco incompatible – Hyper‑V utiliza VHD/VHDX, mientras que Proxmox (KVM/QEMU) prefiere RAW o QCOW2. La conversión no es trivial porque los metadatos de la VM (CPU, NIC, controladores) también difieren.
- Ausencia de exportación nativa – Hyper‑V no ofrece una exportación directa a OVF que Proxmox pueda importar sin ajustes. Cada VM queda como un conjunto de VHDX + archivo de configuración XML.
- Dependencia de backups – Muchas empresas confían en Veeam para la protección de datos. Veeam guarda los discos en su propio formato y, aunque permite restaurar a Hyper‑V o VMware, no incluye un destino Proxmox.
- Drivers y agentes – Los Integration Services de Hyper‑V no funcionan bajo KVM; es necesario instalar qemu‑guest‑agent y, a veces, cambiar el tipo de controlador de disco o NIC.
- Escalado – Lo que funciona para una VM rara vez escala a cientos sin automatización. La falta de scripts reutilizables genera errores de nomenclatura, IDs duplicados y configuraciones inconsistentes.
Solución
Una estrategia robusta combina tres bloques: extracción de los discos, conversión al formato KVM y creación automática de las VMs en Proxmox. Se pueden usar dos caminos principales; la elección depende de si ya se dispone de backups Veeam.
1. Migración usando Veeam como punto de partida
- Crear backup Veeam de cada VM – Si ya se está respaldando con Veeam, no hay que generar exportaciones adicionales.
- Restaurar el backup a un host Windows temporal – Utiliza la opción “Instant VM Recovery” o “Restore to a new location” para obtener el VHDX original.
- Exportar el VHDX – Copia el archivo VHDX a un storage accesible desde el nodo Proxmox (NFS, SMB o iSCSI).
- Convertir a QCOW2 –
qemu-img convert -f vhdx -O qcow2 source.vhdx dest.qcow2. - Importar en Proxmox –
qm importdisk <VMID> dest.qcow2 local-lvm --format qcow2. - Crear la VM – Usa
qm createcon los parámetros de CPU, RAM y NIC que correspondan. - Instalar qemu‑guest‑agent – Después del primer arranque, instala el agente para mejorar la gestión de la VM.
Este flujo mantiene la cadena de backup intacta: si algo falla, el backup Veeam sigue disponible y la conversión puede reintentarse sin tocar la VM original.
2. Conversión directa con virt‑v2v
virt-v2v es una herramienta de libguestfs diseñada para migrar VMs entre hipervisores. Soporta VHDX como entrada y genera discos QCOW2 o RAW listos para Proxmox.
virt-v2v -i disk /path/to/source.vhdx -o local -os /var/lib/vz/template/qemu \
-of qcow2 -osid 100 --machine q35
-i diskindica que el origen es un disco bruto.-o localy-osespecifican el directorio de destino en el nodo Proxmox.-of qcow2elige el formato de salida.--machine q35fuerza la emulación de chipset compatible con Windows 10/Server 2019.
virt-v2v también adapta la configuración de NIC, elimina los drivers de Hyper‑V y agrega un controlador virtio por defecto. Para cientos de VMs basta con envolver el comando en un bucle Bash.
3. Orquestación en lote
A continuación se muestra un script que cubre la mayor parte del proceso: exporta VHDX desde un share, los convierte, crea la VM y la registra en Proxmox. El script asume que los IDs de VM se generan secuencialmente a partir de 9000; ajústelo a su rango.
#!/usr/bin/env bash
SRC="/mnt/hyperv_exports" # Share con los VHDX exportados
DST="/var/lib/vz/template/qemu" # Directorio de plantillas QCOW2 en Proxmox
START_ID=9000
NEXT_ID=$START_ID
for vhdx in "$SRC"/*.vhdx; do
name=$(basename "$vhdx" .vhdx)
qcow="${DST}/${name}.qcow2"
echo "Convirtiendo $vhdx → $qcow"
qemu-img convert -f vhdx -O qcow2 "$vhdx" "$qcow"
vmid=$NEXT_ID
((NEXT_ID++))
echo "Creando VM $vmid ($name)"
qm create "$vmid" --name "$name" --memory 4096 --net0 virtio,bridge=vmbr0
qm importdisk "$vmid" "$qcow" local-lvm --format qcow2
qm set "$vmid" --scsihw virtio-scsi-pci --ide2 local:cloudinit
qm set "$vmid" --boot c --bootdisk scsi0
done
El script cubre los pasos críticos y permite añadir opciones de CPU, RAM o discos adicionales mediante variables de entorno. Al ejecutarse en el nodo Proxmox, la VM queda lista para arrancar; solo falta instalar el qemu-guest-agent y, en caso de Windows, cambiar el controlador de disco a virtio (se hace automáticamente en la mayoría de versiones modernas).
Cuándo aplicar esta solución
- Migraciones masivas – Cuando el número de VMs supera decenas y la intervención manual es inviable.
- Entornos con backups Veeam – Si ya se cuenta con Veeam, el primer camino evita duplicar trabajo de exportación.
- Versiones recientes de Windows/Linux –
virt-v2vgestiona bien los controladores modernos; para sistemas muy antiguos (Windows Server 2003) puede requerir ajustes manuales. - Redes estáticas o DHCP – La solución asume que la configuración de red se puede volver a aplicar en Proxmox; si la VM depende de VLANs específicas, añada la opción
--bridgeadecuada enqm create.
No es recomendable cuando:
- Se necesita migración en tiempo real – Ningún método aquí ofrece “live migration” entre Hyper‑V y KVM.
- Licencias de Windows están atadas al hardware Hyper‑V – La reactivación será necesaria y podría romper la automatización.
- Los discos están cifrados con BitLocker sin clave de recuperación – La conversión fallará sin la clave.
Código
#!/usr/bin/env bash
SRC="/mnt/hyperv_exports"
DST="/var/lib/vz/template/qemu"
START_ID=9000
NEXT_ID=$START_ID
for vhdx in "$SRC"/*.vhdx; do
name=$(basename "$vhdx" .vhdx)
qcow="${DST}/${name}.qcow2"
qemu-img convert -f vhdx -O qcow2 "$vhdx" "$qcow"
vmid=$NEXT_ID
((NEXT_ID++))
qm create "$vmid" --name "$name" --memory 4096 --net0 virtio,bridge=vmbr0
qm importdisk "$vmid" "$qcow" local-lvm --format qcow2
qm set "$vmid" --scsihw virtio-scsi-pci --ide2 local:cloudinit
qm set "$vmid" --boot c --bootdisk sc