Friday, March 18, 2022

how to shrink disk on qcow2 image (with an xfs filesystem)

abstract

This explains how to shrink (or change the size of the disk) of a qcow2 image.
qcow2 images are used in VMware virtual machines.
I am converting everything to vdi to test with virtualbox, so I can test directly in my computer.

Basically, you can't directly shrink a qcow2 image (using xfs). The actual process is to make another image (with a different disk size), copying all the existing contents from the original one.
For simplicity, this image is a GNU/Linux system (centos), with a grub2 bootloader.
I'm doing all these commands on a Debian 11 system.

steps overall

1. convert qcow2 to vdi
2. create new disk for new disk size, and another to locally save the backup (temp)
3. attach the new and the old image disks (vdi) to the VM
4. create new filesystems, mount and backup/restore the old image files
5. copy mbr to new system
6. update `/boot/grub2` and `/etc/fstab` for the new disk's uuid, and remove grub2 admin password (in case your original image had the grub2 admin password set)
7. convert vdi to qcow2

pre-requirements

1. the qcow2 image (can download from openstack)
2. virtualbox with a working GNU/Linux OS (to run from a live CD ISO image is OK too)

steps with commands in detail


# 1. convert qcow2 to vdi
# (get the image to your local machine first)
qemu-img convert -O vdi some_image.qcow2 some_image_backup.vdi

# 2. create new disk for new disk size, and another to locally save the backup (temp)
# use virtualbox's GUI for this
# create new_disk.vdi. And temp_disk.vdi if you are running a live CD. Using your local disk is OK too.

# 3. attach the new and the old image image disks (vdi) to the VM
# use virtualbox's GUI for this. It's done in the "storage" tab

# 4. create new filesystems, mount and backup/restore the old image files
cd /mnt
mkdir old_random_image
mkdir new_random_image
mkdir temp_disk

fdisk -l /dev/sda
n
ENTER bunch of times
w

# same for /dev/sdb
mkfs.ext4 /dev/sda1
mkfs.xfs /dev/sdb1

mount /dev/sda1 temp_disk
mount /dev/sdb1 new_random_image
mount /dev/sdc1 old_random_image
cd temp_disk

apt-get update
apt-get install xfsdump parted
xfsdump -f random_image.dump /mnt/old_random_image
# use random names for job and disk labels like: foo, foo2, bar, etc

xfsrestore -f random_image.dump /mnt/new_random_image

# use df -h and ls to confirm the filesystems seem to match

# add boot permission
# check old image
parted /dev/sdc
p
Ctrl-D

# add boot flag to partition
parted /dev/sdb
p
toggle 1
boot
p
Ctrl-D

# 5. copy mbr to new system

# backup old mbr 
dd if=/dev/sdc of=orig_mbr bs=512 count=1

# copy MBR to new disk (booting part only, without the partition table definition)
dd if=orig_mbr of=/dev/sdb bs=446 count=1

# 6. update `/boot/grub2` and `/etc/fstab` for the new disk's uuid, and remove grub2 admin password
cp -r /boot/grub2  /boot/grub2_bk
cd /boot/grub2
rm user.cfg grub.cfg.*.rpmsave

# check the new disk's uuid
ls -lh /dev/disk/by-uuid/

# replace the old uuid with the new one, and remove password requiring config
vi grub.cfg

################################################################################
# (here is a diff for above)

78,87d80
< ### BEGIN /etc/grub.d/01_users ###
< if [ -f ${prefix}/user.cfg ]; then
<   source ${prefix}/user.cfg
<   if [ -n "${GRUB2_PASSWORD}" ]; then
<     set superusers="root"
<     export superusers
<     password_pbkdf2 root ${GRUB2_PASSWORD}
<   fi
< fi
< ### END /etc/grub.d/01_users ###
90c83
< menuentry 'CentOS Linux' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-XXXX-OLD-DISK-UID' {
---
> menuentry 'CentOS Linux' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-XXXX-NEW-DISK-UID' {
98c91
< 	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  OLD-DISK-UID
---
> 	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1' NEW-DISK-UID 
100c93
< 	  search --no-floppy --fs-uuid --set=root OLD-DISK-UID
---
> 	  search --no-floppy --fs-uuid --set=root NEW-DISK-UID
102c95
< 	linux16 /boot/vmlinuz-XXX.x86_64 root=UUID=OLD-DISK-UID ro console=tty0 crashkernel=auto console=ttyS0,115200 audit=1 LANG=en_US.UTF-8
---
> 	linux16 /boot/vmlinuz-XXX.x86_64 root=UUID=NEW-DISK-UID ro console=tty0 crashkernel=auto console=ttyS0,115200 audit=1 LANG=en_US.UTF-8
105c98
# ...
################################################################################

# do the same for fstab
vi /etc/fstab
# should look like this:
# UUID=XXXXXXXXXXXXXXXXXXX  /                       xfs     defaults        0 0
# (this has the new disk's UUID)

# restart VM unmounting all disks but the new image
# and check it boots OK (probably can't get a prompt due to network settings, but you should
# get no kernel error, or booting errors like "no disk/booter found" etc)

# 7. convert vdi to qcow2
qemu-img convert -f vdi -O qcow2 ~/virtualbox_vms/disks/random_image10G.vdi some_image_10G.qcow2

# 8. upload image to openstack
openstack image create --disk-format qcow2 --container-format bare  --file image/some_image_10G.qcow2 img-name-in-openstack

No comments:

Post a Comment