Cómo gestionar volúmenes con virsh
Breve: ejemplos de uso de la API de libvirt (virsh vol-*) para gestionar volúmenes dentro de pools y las diferencias según el backend.
Gestión de volúmenes de almacenamiento con virsh
En este apartado vamos a estudiar la gestión de volúmenes de almacenamiento usando la API de libvirt (herramienta virsh). Trabajaremos sobre pools de tipo dir (ficheros de imagen en disco), aunque muchas de las operaciones son compatibles con otros backends; donde existan diferencias, se indicará.
Pools y volúmenes: concepto rápido
Un “volumen” en libvirt es la unidad de almacenamiento creada dentro de un pool. En pools de tipo dir y fs los volúmenes son ficheros (por ejemplo qcow2, raw), en logical son volúmenes LVM, en disk pueden mapearse a particiones y en backends de red (Gluster, RBD, iSCSI) la creación y gestión puede requerir herramientas específicas.
Comprobar espacio disponible en los pools (requisito previo)
Antes de crear volúmenes conviene verificar que existe espacio disponible en el pool:
javiercruces@FJCD-PC:~$ virsh pool-list --details
Name State Autostart Persistent Capacity Allocation Available
------------------------------------------------------------------------------------
default running yes yes 914,78 GiB 100,98 GiB 813,80 GiB
isos running yes yes 914,78 GiB 100,98 GiB 813,80 GiB
libvirt running yes yes 914,78 GiB 100,98 GiB 813,80 GiB
Obtener información de los volúmenes de un pool
Para listar los volúmenes de un pool (ej. default):
javiercruces@FJCD-PC:~$ virsh vol-list default
Name Path
------------------------------------------------------------------------------------------------------
debian-13.1.0-amd64-netinst.iso /var/lib/libvirt/images/debian-13.1.0-amd64-netinst.iso
debian13-base.qcow2 /var/lib/libvirt/images/debian13-base.qcow2
debian13-clonacion-completa.qcow2 /var/lib/libvirt/images/debian13-clonacion-completa.qcow2
debian13-clonacion-enlazada.qcow2 /var/lib/libvirt/images/debian13-clonacion-enlazada.qcow2
debian13.qcow2 /var/lib/libvirt/images/debian13.qcow2
ubuntu-24.04-vm.qcow2 /var/lib/libvirt/images/ubuntu-24.04-vm.qcow2
ubuntu-24.04.3-live-server-amd64.iso /var/lib/libvirt/images/ubuntu-24.04.3-live-server-amd64.iso
ubuntu-25.04-live-server-amd64.iso /var/lib/libvirt/images/ubuntu-25.04-live-server-amd64.iso
ubuntu-25.04-vm.qcow2 /var/lib/libvirt/images/ubuntu-25.04-vm.qcow2
...
Si quieres más datos (capacidad, allocation), usa --details:
javiercruces@FJCD-PC:~$ virsh vol-list default --details
Name Path Type Capacity Allocation
---------------------------------------------------------------------------------------------------------------------------------------
debian-13.1.0-amd64-netinst.iso /var/lib/libvirt/images/debian-13.1.0-amd64-netinst.iso file 783,00 MiB 783,00 MiB
debian13-base.qcow2 /var/lib/libvirt/images/debian13-base.qcow2 file 20,00 GiB 585,61 MiB
debian13-clonacion-completa.qcow2 /var/lib/libvirt/images/debian13-clonacion-completa.qcow2 file 20,00 GiB 3,04 GiB
debian13-clonacion-enlazada.qcow2 /var/lib/libvirt/images/debian13-clonacion-enlazada.qcow2 file 20,00 GiB 105,88 MiB
debian13.qcow2 /var/lib/libvirt/images/debian13.qcow2 file 20,00 GiB 2,11 GiB
ubuntu-24.04-vm.qcow2 /var/lib/libvirt/images/ubuntu-24.04-vm.qcow2 file 20,00 GiB 3,32 MiB
ubuntu-24.04.3-live-server-amd64.iso /var/lib/libvirt/images/ubuntu-24.04.3-live-server-amd64.iso file 3,08 GiB 3,08 GiB
ubuntu-25.04-live-server-amd64.iso /var/lib/libvirt/images/ubuntu-25.04-live-server-amd64.iso file 1,88 GiB 1,88 GiB
ubuntu-25.04-vm.qcow2 /var/lib/libvirt/images/ubuntu-25.04-vm.qcow2 file 20,00 GiB 3,32 MiB
...
Para obtener información de un volumen concreto:
javiercruces@FJCD-PC:~$ virsh vol-info debian13.qcow2 default
Name: debian13.qcow2
Type: file
Capacity: 20,00 GiB
Allocation: 2,11 GiB
La definición XML del volumen puede verse con vol-dumpxml:
javiercruces@FJCD-PC:~$ virsh vol-dumpxml debian13.qcow2 default
<volume type='file'>
<name>debian13.qcow2</name>
<key>/var/lib/libvirt/images/debian13.qcow2</key>
<capacity unit='bytes'>21474836480</capacity>
<allocation unit='bytes'>2265751552</allocation>
<physical unit='bytes'>21478375424</physical>
<target>
<path>/var/lib/libvirt/images/debian13.qcow2</path>
<format type='qcow2'/>
<permissions>
<mode>0600</mode>
<owner>0</owner>
<group>0</group>
</permissions>
<timestamps>
<atime>1761395639.089998838</atime>
<mtime>1760392793.808858769</mtime>
<ctime>1760392794.101127920</ctime>
<btime>0</btime>
</timestamps>
<compat>1.1</compat>
<clusterSize unit='B'>65536</clusterSize>
<features>
<lazy_refcounts/>
</features>
</target>
</volume>
Crear volúmenes con vol-create-as
Ejemplo: crear un volumen raw de 10G en el pool default:
javiercruces@FJCD-PC:~$ virsh vol-create-as default vdisk-10G.img --format raw 10G
Comprobar fichero creado (en pools dir el volumen será un fichero en el directorio target del pool, típicamente /var/lib/libvirt/images para el pool default):
javiercruces@FJCD-PC:~$ sudo ls -l /var/lib/libvirt/images/
total 10485760
-rw------- 1 root root 10737418240 oct 26 00:05 vdisk-10G.img
Si creas un volumen en raw, no tendrás aprovisionamiento ligero (thin provisioning), el fichero ocupará el tamaño completo desde el inicio. Si creas en qcow2, la capacidad será lógica y la asignación física crecerá según uso.
Ejemplo de qcow2:
javiercruces@FJCD-PC:~$ virsh vol-create-as --pool default --format qcow2 vdisk-20G.qcow2 20G
Asi podemos comprobar que el disco en formato raw ocupa todo su tamaño mientras que el qcow2 solo lo que realmente tiene ocupado.
javiercruces@FJCD-PC:~$ virsh vol-list default --details
Name Path Type Capacity Allocation
---------------------------------------------------------------------------------------------
vdisk-10G.img /var/lib/libvirt/images/vdisk-10G.img file 10,00 GiB 10,00 GiB
vdisk-20G.qcow2 /var/lib/libvirt/images/vdisk-20G.qcow2 file 20,00 GiB 196,00 KiB
Borrar volúmenes
javiercruces@FJCD-PC:~$ virsh vol-delete vdisk-10G.img default
Esto elimina el volumen del pool. En pools de red o LVM el efecto depende del backend (p. ej. borrado de LUN, eliminación de RBD image, etc.).
Clonar volúmenes
Para clonar un volumen dentro del mismo pool:
javiercruces@FJCD-PC:~$ virsh vol-clone --pool default vdisk-20G.qcow2 vdisk-20G-clone.qcow2
Al clonar obtendrás una copia que, si es qcow2, tendrá aprovisionamiento ligero equivalente.
Redimensionar volúmenes
Para aumentar o reducir el tamaño de un volumen:
javiercruces@FJCD-PC:~$ virsh vol-resize --pool default vdisk-20G.qcow2 30G
Si el volumen forma parte de una máquina virtual activa, además de redimensionar el volumen desde el host debes redimensionar la partición y el sistema de ficheros dentro del invitado. A continuación se muestran ejemplos para un sistema con una única partición de datos en /dev/vda1 con un sistema de ficheros ext4.
- Aumentar el volumen (desde el host):
javiercruces@FJCD-PC:~$ virsh vol-resize --pool default vdisk-20G.qcow2 30G
- Redimensionar dentro del invitado (online, con la VM arrancada)
Si el invitado dispone de cloud-guest-utils (paquete growpart) puedes ampliar la partición y el sistema de ficheros en caliente:
# Conéctate al invitado (por ejemplo: ssh javiercruces@debian13)
javiercruces@debian13:~$ sudo apt update && sudo apt install -y cloud-guest-utils
javiercruces@debian13:~$ sudo growpart /dev/vda 1
javiercruces@debian13:~$ sudo resize2fs /dev/vda1
Explicación rápida:
growpart /dev/vda 1extiende la primera partición del disco/dev/vdapara ocupar el nuevo espacio disponible.resize2fs /dev/vda1ajusta el tamaño del sistema de ficheros ext4 a la nueva partición.
- Alternativa si no tienes
growpart(online, conparted)
javiercruces@debian13:~$ sudo apt install -y parted
javiercruces@debian13:~$ sudo parted /dev/vda --script resizepart 1 100%
javiercruces@debian13:~$ sudo resize2fs /dev/vda1
Sacar y meter datos de un disco
Descargar el contenido de un volumen a un fichero local:
javiercruces@FJCD-PC:~$ virsh vol-download --pool default vdisk-20G.qcow2 /tmp/vdisk-20G.qcow2
Subir el contenido desde un fichero local a un volumen (sobrescribe):
javiercruces@FJCD-PC:~$ virsh vol-upload --pool default vdisk-20G.qcow2 /tmp/vdisk-20G.qcow2
Estas operaciones pueden ser lentas para ficheros grandes; en muchos casos qemu-img convert o herramientas del propio backend (rbd, gluster) son más eficientes.
Asignar un volumen como disco a una VM
Puedes adjuntar un volumen a una VM directamente desde el host sin crear un fichero XML usando attach-disk. Ejemplos:
javiercruces@FJCD-PC:~$ # Adjuntar en caliente (live)
javiercruces@FJCD-PC:~$ virsh attach-disk testguest1 /var/lib/libvirt/images/vdisk-20G.qcow2 vdb --live
javiercruces@FJCD-PC:~$ # Adjuntar persistentemente en la configuración
javiercruces@FJCD-PC:~$ virsh attach-disk --config testguest1 /var/lib/libvirt/images/vdisk-20G.qcow2 vdb
javiercruces@FJCD-PC:~$ # Adjuntar en caliente y persistente a la vez
javiercruces@FJCD-PC:~$ virsh attach-disk --live --config testguest1 /var/lib/libvirt/images/vdisk-20G.qcow2 vdb
Explicación y notas:
attach-diskrecibe la ruta al fichero de imagen (o al dispositivo del pool) y el nombre del dispositivo objetivo dentro del invitado (p. ej.vdb).--liverealiza la operación en caliente en la VM en ejecución;--configescribe la entrada en la definición de la VM para que sea persistente al reinicio. Puedes combinar ambas.- Estos comandos son prácticos cuando conoces la ruta del volumen en el host y el nombre del dispositivo que quieres usar dentro del invitado.
Alternativa: adjuntar mediante un fragmento XML
Si prefieres la vía basada en XML (útil para casos complejos o cuando necesitas especificar atributos avanzados), puedes crear un fragmento XML y usar attach-device:
<disk type='volume' device='disk'>
<driver name='qemu' type='qcow2'/>
<source pool='default' volume='vdisk-20G.qcow2'/>
<target dev='vdb' bus='virtio'/>
</disk>
Y adjuntar persistentemente en la configuración:
javiercruces@FJCD-PC:~$ virsh attach-device --config testguest1 ~/vdisk-20G.xml
Dependiendo del tipo de pool, el XML cambia; para operaciones sencillas attach-disk suele ser la forma más directa.
Quitar (desasignar) un disco
Si necesitas quitar el disco por su nombre de dispositivo (sin XML), usa detach-disk:
javiercruces@FJCD-PC:~$ virsh detach-disk testguest1 vdb
javiercruces@FJCD-PC:~$ # Eliminar también la entrada persistente:
javiercruces@FJCD-PC:~$ virsh detach-disk --config testguest1 vdb
