Increasing the Size of a qcow2 Image Under KVM

I like to keep my disk images as small as reasonably possible when running virtual machines as I find it just generally makes life easier. Combined with the fact that if you are running LVM it’s easy to expand the disk there’s really no excuse for over specifying on the disk at install time. This guide shows you step by step how to expand a qcow2 disk image and then how to give the guest the extra space. 

I’m going to assume that you have an install similar to the one I’ve detailed in the Installing and Running KVM on Ubuntu 14.04 series of articles on this site. In other words you virtual machines are Linux based and installed on qcow2 disk images. This basic resizing procedure should also work for Windows and other guests as well but the last step, where the guest grabs the additional space, will vary from one OS to another. On recent Windows OS’es I believe you can use Disk Management to change partition sizes.

Step 1 The Lay of the Land

On the guest machine you first want to run fdisk to determine the current partition sizes and the over all disk size:

$ sudo fdisk -l
Disk /dev/vda: 10.7 GB, 10737418240 bytes
16 heads, 63 sectors/track, 20805 cylinders, total 20971520 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00044219
Device Boot Start End Blocks Id System
/dev/vda1 * 2048 499711 248832 83 Linux
/dev/vda2 501758 20971519 10234881 5 Extended
/dev/vda5 501760 20969471 10233856 8e Linux LVM
Disk /dev/mapper/web--vg-root: 8300 MB, 8300527616 bytes
255 heads, 63 sectors/track, 1009 cylinders, total 16211968 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
Disk /dev/mapper/web--vg-root doesn't contain a valid partition table
Disk /dev/mapper/web--vg-swap_1: 2143 MB, 2143289344 bytes
255 heads, 63 sectors/track, 260 cylinders, total 4186112 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
Disk /dev/mapper/web--vg-swap_1 doesn't contain a valid partition table

From this output you can see that the virtual drive this machine (called web) is currently installed on is 10GB with about 8GB given to the OS and 2GB to a swap partition. You can safely ignore the warning about the disks not having valid partition tables this is because they are filled with LVM goodness (or badness depending on your point of view) and fdisk doesn’t understand them. You can also use the LVM tools to get additional information about the drives if you would like:

$ sudo pvs
 PV VG Fmt Attr PSize PFree 
 /dev/vda5 web-vg lvm2 a-- 9.76g 32.00m

The pvs command shows information about the physical volume layout that LVM has. Now shut down the guest machine either from within the guest or from the host using virsh or VMM. Note the machine must be shut down not hibernated or suspended.

Step 2 Expand the Disk

Check the size and configuration of the current disk:

$ sudo qemu-img info /var/lib/libvirt/images/web.qcow2
image: /var/lib/libvirt/images/web.qcow2
file format: qcow2
virtual size: 10G (10737418240 bytes)
disk size: 3.7G
cluster_size: 65536
Format specific information:
 compat: 1.1
 lazy refcounts: true

If everything looks good expand the disk. Here I’m expanding it by 2GB:

$ sudo qemu-img resize /var/lib/libvirt/images/web.qcow2 +2G
Image resized.

WARNING: The first time I ran the resize qemu-img reported that it repaired some clusters while it resized the drive which I’ve not seen it do in the past so for peace of mind I ran a check on the drive as well. It turned out that I had accidentally performed the drive resize with the guest still running! Fortunately this was on a throw away test machine I’d set up for the article so no harm done but always double check you’ve stopped your machines first!

$ sudo qemu-img check -r all /var/lib/libvirt/images/web.qcow2
No errors were found on the image.
131544/196608 = 66.91% allocated, 0.00% fragmented, 0.00% compressed clusters
Image end offset: 8622571520

Now getting the information for the drive should show a larger drive:

$ sudo qemu-img info /var/lib/libvirt/images/web.qcow2
image: /var/lib/libvirt/images/web.qcow2
file format: qcow2
virtual size: 12G (12884901888 bytes)
disk size: 3.7G
cluster_size: 65536
Format specific information:
 compat: 1.1
 lazy refcounts: true

As you can see the drive is now 12GB as expected.

Step 3 – Give the New Space to LVM

Although the drive is larger the partitions on it are still the same size so from the guests point of view nothing has changed. There are several ways to change the partition sizes but I find the easiest is to use the Gparted Live bootable CD image. Simple download the live CD and mount it in your guest machine.

The easiest way to get the CD mounted in the guess is to use VMM. Simply open the guest, select the CD drive and insert the ISO image. Then under Boot Options change the boot device order so that the CD is first. Now when you start the guest you should boot the live CD.

Start the guest machine and switch to the console page in VMM. Select the first option from the Gparted boot menu and answer the configuration questions. After a short while you will be presented with a desktop and if you wait a few more seconds Gparted will start automatically and should look something like this:

gparted_2

You can graphically see in this image the drive layout that was reported by fdisk in the first step the main drive is about 10GB in size. At the right hand end you can see there is 2GB of unused space which I will now add to the LVM partition.

First select /dev/vda2 (not your device names may vary) and select Resize/Move from the toolbar. The Resize / Move window will open.

gparted_3

The simplest way to give the extra space to this partition is to just drag the end of the partition to the right. Alternatively you can type an exact value if you want. Once you have resized as you want click the Resize / Move button. Now repeat the process with /dev/vda5 to give the space to this partition as this is the one that LVM is actually installed on.

You should then have something that looks like this:

gparted_4

If you are happy with the changes click Apply, shut down the guest machine and remove the live CD from the drive.

Step 4 Resize the Drive

In the guest run fdisk again and note that it reports a larger drive. Note also that neither the data partition nor the swap partition are any larger – they don’t just grow to fill the space automatically:

$ sudo fdisk -l
Disk /dev/vda: 12.9 GB, 12884901888 bytes
16 heads, 63 sectors/track, 24966 cylinders, total 25165824 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00044219
Device Boot Start End Blocks Id System
/dev/vda1 * 2048 499711 248832 83 Linux
/dev/vda2 501758 25165823 12332033 5 Extended
/dev/vda5 501760 25163775 12331008 8e Linux LVM
Disk /dev/mapper/web--vg-root: 8300 MB, 8300527616 bytes
255 heads, 63 sectors/track, 1009 cylinders, total 16211968 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
Disk /dev/mapper/web--vg-root doesn't contain a valid partition table
Disk /dev/mapper/web--vg-swap_1: 2143 MB, 2143289344 bytes
255 heads, 63 sectors/track, 260 cylinders, total 4186112 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
Disk /dev/mapper/web--vg-swap_1 doesn't contain a valid partition table

If you run the LVM information commands you’ll notice that the physical drive and the volume group are larger but the logical volumes are still the same size as before.

$ sudo pvs
 PV VG Fmt Attr PSize PFree
 /dev/vda5 web-vg lvm2 a-- 11.76g 2.03g
$ sudo vgs
 VG #PV #LV #SN Attr VSize VFree
 web-vg 1 2 0 wz--n- 11.76g 2.03g
$ sudo lvs
 LV VG Attr LSize Pool Origin Data% Move Log Copy% Convert
 root web-vg -wi-ao--- 7.73g 
 swap_1 web-vg -wi-ao--- 2.00g

The configuration in step 3 took care of the physical volumes and the volume groups but the logical volumes need to be increased in size from within the guest. As I’ve not added any new memory to the system I’m going to give all the new space to the root drive like this:

$ sudo lvextend -L +2G /dev/web-vg/root
 Extending logical volume root to 9.73 GiB
 Logical volume root successfully resized

Now tell the file system it needs to resize itself:

$ sudo resize2fs /dev/web-vg/root

resize2fs 1.42.9 (4-Feb-2014)
Filesystem at /dev/web-vg/root is mounted on /; on-line resizing required
old_desc_blocks = 1, new_desc_blocks = 1
The filesystem on /dev/web-vg/root is now 2550784 blocks long.

And that’s everything done. If you want to confirm that the expansion has taken place there’s a variety of commands you could use such as “df -H” or fdisk or lvs