Shrink, optimise and expand an existing QCOW2 image
edafe.de/qcow A virtual disk image is a block device in a file. There are a number of different disk image formats to choose from when setting up a virtual machine. QEMU Copy On Write version 2 (QCOW2) is the default virtual disk image format for the Quick Emulator (QEMU). Features such as thin provisioning, snapshots and compression make QCOW2 one of the most versatile virtual disk formats available. These instructions specifically target Debian 12 with a GNOME desktop as the host, but they should also be applicable to other Linux distributions such as Ubuntu or Linux Mint. The guest in this particular example is a Windows 11 virtual machine that has run out of space. The overall objective is to shrink and optimise the 64 GiB disk image for random read and write operations before expanding it to a desired size of 128 GiB. With thanks to Fam Zheng. Before you begin Shut down the virtual machine and delete all existing snapshots from the image file. Never modify images currently in use by a running virtual machine. Step 1 On the host, install the necessary tools for working with virtual disk images. $ sudo apt-get install --yes libguestfs-tools gnome-disk-utility Step 2 Only root can access the host directory /var/lib/libvirt/images. Use the following command to obtain the necessary privileges. $ sudo su Step 3 Continue by creating a directory in which to keep your virtual machine backups. # mkdir /var/lib/libvirt/backups Step 4 Now create a backup of the virtual machine with the name windows by copying its QCOW2 image file to the backups directory. # cp /var/lib/libvirt/images/windows.qcow2 /var/lib/libvirt/backups/windows-backup.qcow2 Step 5 Sparsify the image file to convert any free space within the disk image to free space on the host. # virt-sparsify --in-place /var/lib/libvirt/images/windows.qcow2 Step 6 Rename the sparsified image file. # mv /var/lib/libvirt/images/windows.qcow2 /var/lib/libvirt/images/windows-sparsified.qcow2 Step 7 Check the disk size of the sparsified image file. # qemu-img info /var/lib/libvirt/images/windows-sparsified.qcow2 The disk size should be smaller than the virtual size. In this particular case, the disk size is 33.7 GiB and the virtual size 64 GiB. image: /var/lib/libvirt/images/windows-sparsified.qcow2file format: qcow2virtual size: 64 GiB (68719476736 bytes)disk size: 33.7 GiBcluster_size: 65536Format specific information: compat: 1.1 compression type: zlib lazy refcounts: true refcount bits: 16 corrupt: false extended l2: false Step 8 Determine which partition to resize by obtaining more detailed information about the contents of the sparsified disk image. # virt-filesystems --long -h --all -a /var/lib/libvirt/images/windows-sparsified.qcow2 On the virtual device /dev/sda, the partition /dev/sda3 is equivalent to the Local Disk (C:) of the Windows 11 virtual machine. Name Type VFS Label MBR Size Parent/dev/sda1 filesystem vfat - - 96M -/dev/sda3 filesystem ntfs - - 63G -/dev/sda4 filesystem ntfs - - 768M -/dev/sda1 partition - - - 100M /dev/sda/dev/sda2 partition - - - 16M /dev/sda/dev/sda3 partition - - - 63G /dev/sda/dev/sda4 partition - - - 768M /dev/sda/dev/sda device - - - 64G - Step 9 Load the network block device (NBD) kernel module. # modprobe nbd max_part=8 Step 10 Connect the sparsified image. # qemu-nbd --connect=/dev/nbd9 /var/lib/libvirt/images/windows-sparsified.qcow2 Step 11 The partition /dev/sda3 listed in Step 8 is equivalent to /dev/nbd9p3 connected as a network block device. Use GNOME Disks to shrink /dev/nbd9p3 to its Minimal Size. Use a graphical utility to minimise the risk of introducing errors. Select the correct partition and from the pop-up menu, choose the option Resize… Select Minimal Size and resize the partition. Step 12 Disconnect the resized image. # qemu-nbd -d /dev/nbd9 Step 13 Unload the NBD kernel module. # modprobe -r nbd Step 14 Create a target image larger than the resized source image. In this example, the size of the target image is 128G and its format QCOW2 with full preallocation and a cluster size of 2M. # qemu-img create -f qcow2 -o preallocation=full -o cluster_size=2M /var/lib/libvirt/images/windows-target.qcow2 128G Step 15 Copy the source image to the target image. Specify the correct partition which to expand in the process. # virt-resize --expand /dev/sda3 /var/lib/libvirt/images/windows-sparsified.qcow2 /var/lib/libvirt/images/windows-target.qcow2 Step 16 Confirm the size of the target image. # qemu-img info /var/lib/libvirt/images/windows-target.qcow2 The overall disk size is now 128 GiB in total. image: /var/lib/libvirt/images/windows-target.qcow2file format: qcow2virtual size: 128 GiB (137438953472 bytes)disk size: 128 GiBcluster_size: 2097152Format specific information: compat: 1.1 compression type: zlib lazy refcounts: false refcount bits: 16 corrupt: false extended l2: false Step 17 Obtain more detailed information about the contents of the target disk image. # virt-filesystems --long -h --all -a /var/lib/libvirt/images/windows-target.qcow2 The partition /dev/sda3 of the virtual device /dev/sda is now 127G in size. Name Type VFS Label MBR Size Parent/dev/sda1 filesystem vfat - - 96M -/dev/sda3 filesystem ntfs - - 127G -/dev/sda4 filesystem ntfs - - 768M -/dev/sda1 partition - - - 100M /dev/sda/dev/sda2 partition - - - 16M /dev/sda/dev/sda3 partition - - - 127G /dev/sda/dev/sda4 partition - - - 768M /dev/sda/dev/sda device - - - 128G - Step 18 Rename the target image file. # mv /var/lib/libvirt/images/windows-target.qcow2 /var/lib/libvirt/images/windows.qcow2 All done! You can also modify format specific options for an existing image without having to create a target disk image. Or alternatively expand into a target image that uses a format compatible with other hypervisors, such as RAW, VMDK, VDI, VHD, VHDX or QED.
Discussion in the ATmosphere