Cool Linux Stuff: Live Resize of Libvirt Guest’s Disk Served as LVM Logical Volume on SAN Volume

Here is the situation: We have a FC SAN with one volume dedicated for virtual machines’ disks. That SAN volume is available on the server via 2 paths (two storage controllers, two FC switches and two HBAs) and failover is handled by multipath-tools. This SAN volume has no partition table but is a LVM’s physical volume (PV), which contributes to LVM volume group (VG) named lvm-guests-shared-VG. LVM logical volumes (LV) in this VG are virtual disks for libvirt/kvm virtual machines.

The problem: suppose we need to expand disk of one virtual machine a lot; expand so much, that SAN volume has to be expanded too; and we need to do that online – without restarting anything.

Step 1 – Expand SAN Volume

There is no explanation needed as this is a basic function of probably all storage arrays.

Step 2 – Make the SAN Volume’s New Size Visible on the Server

First we have to rescan volume’s geometry. We use multipath -l command to get block devices representing SAN volume available by each path. Example output:

The second, we let multipath know about the changes by running command multipath -r.

Step 3 – Utilizing New Space in LVM

To make PV consume whole SAN volume’s space, we execute command pvresize -v /dev/DEVICE. DEVICE can be found by looking at PV Name field in pvdisplay command’s output. Of course if we have many PVs on the server we take into account only the one contributing to our lvm-guests-shared-VG. Example pvresize output looks like this:

The last LVM thing is to expand LV. We do this using command lvresize -L 800G /dev/lvm-guests-shared-VG/resized-virtual-machine, where 800G is a new LV size, utilizing bigger VG and resized-virtual-machine is the name of LV with our virtual machine’s disk.

Step 4 – Refresh Disk Size on the Guest Machine

This is quite tricky, since VirtIO driver providing block device with guest’s disk has no refresh file under /sys/block/ tree. Refreshing virtual disk size has been implemented in libvirt 0.9.8 and can be triggered by block_resize command in qemu monitor. Command requires qemu disk name as an argument. To get this name issue: virsh qemu-monitor-command resized-virtual-machine --hmp "info block". The output should look like this:

Of course resized-virtual-machine is the name of our virtual machine (domain in libvirt terminology).

So disk’s name we where looking for is drive-virtio-disk0. Now we can refresh disk size on the guest side by executing virsh qemu-monitor-command resized-virtual-machine --hmp "block_resize drive-virtio-disk0 800G"