En corto

Con la VM apagada:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
modprobe nbd max_part=16
qemu-nbd --connect=/dev/nbd0 /var/lib/vz/images/100/vm-100-disk-0.qcow2   # añade -r para solo lectura
partprobe /dev/nbd0
lsblk /dev/nbd0                                  # nbd0p1, nbd0p2…
mount /dev/nbd0p2 /mnt/vm

# ... leer, copiar o reparar ...

umount /mnt/vm
qemu-nbd --disconnect /dev/nbd0

Sin el --disconnect la VM no vuelve a arrancar: QEMU se encuentra la imagen bloqueada.

Por qué nbd

Un .qcow2 no es un volcado del disco: tiene cabecera, tabla de clusters, snapshots internos y a veces un archivo base detrás. losetup no lo entiende. qemu-nbd sí, y lo publica como un dispositivo de bloques a través del cliente NBD del kernel; a partir de ahí es un disco más para lsblk, mount, fsck o dd.

max_part importa: sin él el kernel no crea los nodos nbd0p1, nbd0p2… partprobe los fuerza si tras el --connect no aparecen.

Si el disco de la VM lleva LVM

Lo normal en Ubuntu Server, RHEL y Fedora: dentro de la partición hay un VG. Actívalo, monta el LV y, al terminar, desactívalo antes de desconectar:

1
2
3
4
5
6
7
8
vgscan
vgchange -ay                                   # activa lo que encuentre en nbd0
lvs                                            # ubuntu-vg/ubuntu-lv, rhel/root…
mount /dev/ubuntu-vg/ubuntu-lv /mnt/vm

umount /mnt/vm
vgchange -an ubuntu-vg
qemu-nbd --disconnect /dev/nbd0

Trampa clásica: el host tiene un VG con el mismo nombre que el de la VM (ubuntu-vg contra ubuntu-vg, pve contra pve). LVM se niega a activar dos iguales. La herramienta para eso es vgimportclone, que renombra el VG del disco importado sin tocar el del host:

1
2
vgimportclone -n vm100-vg /dev/nbd0p3
vgchange -ay vm100-vg

Si prefieres no cambiar nada dentro de la VM, guestmount (abajo) resuelve el LVM por su cuenta y no toca el LVM del host.

Windows, NTFS y snapshots internos

  • NTFS: mount -t ntfs3 /dev/nbd0p3 /mnt/vm (kernel 5.15+) o ntfs-3g. Si Windows quedó hibernado o con Fast Startup, NTFS solo se deja montar en lectura; apágalo bien desde dentro antes de escribir.
  • Snapshot interno de qcow2 (qemu-img snapshot -l vm.qcow2): qemu-nbd -r -l antes-del-cambio --connect=/dev/nbd0 vm.qcow2 monta el estado de ese snapshot, solo lectura, sin tocar el disco actual.
  • Otros formatos: qemu-nbd habla también vmdk, vhdx y vdi (-f vhdx si no lo detecta); qemu-img convert -O raw es la alternativa si vas a trabajar mucho tiempo con la imagen.

guestmount: lo mismo sin nbd ni root

libguestfs monta la imagen por FUSE, detecta particiones y LVM solo, y no interfiere con el host:

1
2
3
4
apt install libguestfs-tools          # dnf install guestfs-tools en Fedora/RHEL
virt-filesystems --long -h --all -a vm.qcow2      # qué hay dentro
guestmount -a vm.qcow2 -i --ro /mnt/vm            # -i: monta el sistema operativo que encuentre
guestunmount /mnt/vm

Más lento que nbd para copiar gigas, pero imposible de dejar mal cerrado.

Trampas

  • Nunca con la VM encendida. En escritura corrompes el sistema de archivos con seguridad; en -r ves un estado inconsistente (lo que el guest tiene en caché no está en disco). Si necesitas mirar una VM viva, haz un snapshot y monta el snapshot.
  • La imagen queda bloqueada mientras qemu-nbd esté conectado: qm start 100 falla con Failed to get "write" lock. qemu-nbd -d /dev/nbd0 lo suelta; ls /sys/block/nbd*/pid dice cuáles siguen en uso.
  • --disconnect con “device busy”: queda algo montado o un VG activo (vgchange -an). lsof /dev/nbd0* lo encuentra.
  • Proxmox con LVM-thin o ZFS no necesita nbd: el disco de la VM ya es un dispositivo de bloques (/dev/pve/vm-100-disk-0, /dev/zvol/rpool/data/vm-100-disk-0); kpartx -av sobre él saca las particiones. qemu-nbd es para qcow2 en storages de directorio y NFS.
  • Archivos base: una imagen con backing file se monta igual; lo que escribas va a la capa superior. No muevas la base mientras esté conectada.

Ver también: convertir una máquina física a VHDX y el import de discos en Proxmox. Referencia: qemu-nbd en la documentación de QEMU.