I’m quite sure I’d resized qcow2 images before. However, when I needed to resize an image today for my VM at home, I totally forgot about it. Well, this means it’s a good excuse for me to just write down a few commands to help me in the future.

If you try to follow a long, two things you wanna keep in in mind: do it at your own risk, and always backup your data before you make change to it. Having said, that’s get started.

I have a qcow2 image originally allocated for 10GiB of space. It’s full, and I wanted to increase it to 20GiB.

/vm/rh415
➜ ls -lh workstation.qcow2
-rw-------. 1 root root 8.7G Dec 25 07:58 workstation.qcow2

To increase or expand the image size, we can run qemu-img resize IMAGE.qcow2 +SIZE command as the following:

➜ sudo qemu-img resize workstation.qcow2 +10G
[sudo] password for kenno:
Image resized.

➜ ls -lh workstation.qcow2
-rw-------. 1 root root 8.7G Dec 25 08:15 workstation.qcow2

In the above example, I intended to increase the workstation.qcow2 image file by 10GiB. Note that when we listed the file after resizing, it still displayed as 8.7GB. This is expected as qcow2 is a sparse file, it doesn’t pre-allocate the disk space until it’s used. You can read more about it here [1].

The next step is to resize this qcow2 image from the operating system. From here, the situations would be different depending on how the disk (qcow2 image) is configured and formatted with your system. I’m going to show you how to expand a disk configured as LVM on CentOS 7.

After booting the CentOS 7 VM, I can verify that the disk has been expanded to 21.5GB (I know, it isn’t exactly 20GiB I expected, but it doesn’t really matter.)

[root@workstation ~]# parted -s -a opt /dev/sda "print free"
Model: ATA QEMU HARDDISK (scsi)
Disk /dev/sda: 21.5GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags: 

Number  Start   End     Size    Type     File system  Flags
        32.3kB  1049kB  1016kB           Free Space
 1      1049kB  1075MB  1074MB  primary  xfs          boot
 2      1075MB  10.7GB  9663MB  primary               lvm
        10.7GB  21.5GB  10.7GB           Free Space

What does each option passed to parted do?

  • -s - execute this command as non-interactive script
  • -a opt - use optimum alignment as given by the disk topology information
  • print free - display the partition table including the free space

Before the LVM physical volume residing on partition 2 (/dev/sda2) can be expanded, I need to enlarge that partition to take up more space (10.7GB) first.

With the help from this link [2], I run the following command:

[root@workstation ~]# parted -s -a opt /dev/sda "resizepart 2 100%"
[root@workstation ~]# echo $?
0

[root@workstation ~]# parted -s -a opt /dev/sda "print free"
Model: ATA QEMU HARDDISK (scsi)
Disk /dev/sda: 21.5GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags: 

Number  Start   End     Size    Type     File system  Flags
        32.3kB  1049kB  1016kB           Free Space
 1      1049kB  1075MB  1074MB  primary  xfs          boot
 2      1075MB  21.5GB  20.4GB  primary               lvm

A brief explanation of the above command, basically I wanted to resize partition 2 to use all the available free space. The echo $? is optional, it’s just to show that the previous command was executed successfully. The last command in the above output was just to confirm that the size of partition 2 has been increased.

[root@workstation ~]# pvdisplay 
  --- Physical volume ---
  PV Name               /dev/sda2
  VG Name               cl
  PV Size               <9.00 GiB / not usable 3.00 MiB
  Allocatable           yes (but full)
  PE Size               4.00 MiB
  Total PE              2303
  Free PE               0
  Allocated PE          2303
  PV UUID               N6ROGe-H1y3-f62b-yraO-yDxL-I5lH-66WDUd
   

Next, I need to expand the physical disk of the LVM. In my case, the partition that I wanted to resize is /dev/sda2.

[root@workstation ~]# pvresize /dev/sda2
  Physical volume "/dev/sda2" changed
  1 physical volume(s) resized or updated / 0 physical volume(s) not resized

[root@workstation ~]# pvdisplay 
  --- Physical volume ---
  PV Name               /dev/sda2
  VG Name               cl
  PV Size               <19.00 GiB / not usable 2.00 MiB
  Allocatable           yes 
  PE Size               4.00 MiB
  Total PE              4863
  Free PE               2560
  Allocated PE          2303
  PV UUID               N6ROGe-H1y3-f62b-yraO-yDxL-I5lH-66WDUd

So far so good. There are some free PE (physical extend) of 2560. I can use it to expand other LVM. For example, I’m going to allocate an additional 5GiB to the root logical volume.

[root@workstation ~]# lvs
  LV   VG Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  root cl -wi-ao---- <8.00g                                                    
  swap cl -wi-ao----  1.00g                                                    

[root@workstation ~]# lvresize -L +5GiB /dev/cl/root 
  Size of logical volume cl/root changed from <8.00 GiB (2047 extents) to <13.00 GiB (3327 extents).
  Logical volume cl/root successfully resized.

[root@workstation ~]# lvs
  LV   VG Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  root cl -wi-ao---- <13.00g                                                    
  swap cl -wi-ao----   1.00g 
References:

The last step is to resize the actual filesystem used by the root logical volume.

[root@workstation ~]# lsblk -fs | grep root
cl-root xfs               cccaadf6-4748-4b8b-98dc-eb205c785bb5   /
[root@workstation ~]# xfs_growfs /dev/mapper/cl-root 
meta-data=/dev/mapper/cl-root    isize=512    agcount=4, agsize=524032 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=0 spinodes=0
data     =                       bsize=4096   blocks=2096128, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal               bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 2096128 to 3406848

[root@workstation ~]# df -lh | grep root
/dev/mapper/cl-root   13G  7.9G  5.2G  61% /

Well, that’s it folks.