aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas K. Hüttel <dilfridge@gentoo.org>2024-10-13 16:42:49 +0200
committerAndreas K. Hüttel <dilfridge@gentoo.org>2024-10-13 22:30:49 +0200
commit48a56d53fa7b00ac319a25315bd309914f6d8da4 (patch)
tree70414036c91a7269bee81b7dd313e07a477dc94b
parentSupport scripts for diskimage configuration (diff)
downloadcatalyst-48a56d53fa7b00ac319a25315bd309914f6d8da4.tar.gz
catalyst-48a56d53fa7b00ac319a25315bd309914f6d8da4.tar.bz2
catalyst-48a56d53fa7b00ac319a25315bd309914f6d8da4.zip
Script to create a bootable qcow2 image
Signed-off-by: Andreas K. Hüttel <dilfridge@gentoo.org>
-rwxr-xr-xtargets/support/create-qcow2.sh188
1 files changed, 188 insertions, 0 deletions
diff --git a/targets/support/create-qcow2.sh b/targets/support/create-qcow2.sh
new file mode 100755
index 00000000..0073a25c
--- /dev/null
+++ b/targets/support/create-qcow2.sh
@@ -0,0 +1,188 @@
+#!/bin/bash
+
+source ${clst_shdir}/support/functions.sh
+
+## START RUNSCRIPT
+
+# Supported host architectures: all that do UEFI boot and support the tools
+# Script parameters:
+# - ${1} output qcow2 file
+
+#
+# Configuration parameters:
+# All sizes are in forms as understood by parted: use MiB, GiB, ... or M, G, ...
+# - clst_qcow2_size (internal) size of the qcow2 image (default 20GiB)
+# - clst_qcow2_efisize size of the EFI boot partition (default 512MiB)
+# - clst_qcow2_roottype type of the root partition (default xfs)
+#
+: "${clst_qcow2_size:=20GiB}"
+: "${clst_qcow2_efisize:=512MiB}"
+: "${clst_qcow2_roottype:=xfs}"
+
+#
+# We only support one set of tools, based on
+# - mkfs.vfat ( sys-fs/dosfstools , for the EFI partition )
+# - mkfs.xfs ( sys-fs/xfsprogs , this might actually be configurable )
+# - parted ( sys-block/parted , for partitioning )
+# - qemu-nbd ( app-emulation/qemu , for accessing a qcow2 image file as device )
+# - qemu-img ( app-emulation/qemu , for creating a qcow2 image file )
+#
+# Let's assume these are deps of catalyst and thus present.
+#
+
+mymountpoint="${1}.tmp.mnt"
+myqcow2="${1}"
+
+# TODO: find next free device
+modprobe -q nbd
+mydevice=/dev/nbd0
+
+# This script requires slightly more stringent cleanup in case of errors
+# from the moment on when the nbd was set up...
+qcow2die() {
+ echo "Something went wrong. Cleaning up..."
+
+ # here we just ignore errors
+ umount -R "${mymountpoint}/proc"
+ umount -R "${mymountpoint}/sys"
+ umount -R "${mymountpoint}/dev"
+ umount -R "${mymountpoint}/run"
+
+ umount "${mydevice}p1"
+ umount "${mydevice}p2"
+ qemu-nbd -d "${mydevice}"
+
+ die "$@"
+}
+
+# We need a means to execute a script inside the qcow with filesystems mounted
+# Which means reproducing half of catalyst here.
+exec_in_qcow2() {
+ local file_name=$(basename ${1})
+
+ # prepare qcow2 for chrooting
+ mount --types proc /proc "${mymountpoint}/proc"
+ mount --rbind /sys "${mymountpoint}/sys"
+ mount --make-rslave "${mymountpoint}/sys"
+ mount --rbind /dev "${mymountpoint}/dev"
+ mount --make-rslave "${mymountpoint}/dev"
+ mount --bind /run "${mymountpoint}/run"
+ mount --make-slave "${mymountpoint}/run"
+
+ # copy_to_chroot ${1}
+ cp -pPR "${1}" "${mymountpoint}/tmp" || qcow2die
+ # copy_to_chroot ${clst_shdir}/support/chroot-functions.sh
+ cp -pPR "${clst_shdir}/support/chroot-functions.sh" "${mymountpoint}/tmp" || qcow2die
+
+ # Ensure the file has the executable bit set
+ chmod +x "${mymountpoint}/tmp/${file_name}" || qcow2die
+
+ echo "Running ${file_name} in qcow2:"
+ echo " ${clst_CHROOT} ${mymountpoint} /tmp/${file_name}"
+ ${clst_CHROOT} "${mymountpoint}" "/tmp/${file_name}" || qcow2die
+
+ rm -f "${mymountpoint}/tmp/${file_name}" || qcow2die
+ rm -f "${mymountpoint}/tmp/chroot-functions.sh" || qcow2die
+
+ # cleanup qcow2 dir
+ umount -R "${mymountpoint}/proc" || qcow2die
+ umount -R "${mymountpoint}/sys" || qcow2die
+ umount -R "${mymountpoint}/dev" || qcow2die
+ umount -R "${mymountpoint}/run" || qcow2die
+}
+
+
+echo "Creating a new qcow2 disk image file ${myqcow2}.tmp.qcow2 with size ${clst_qcow2_size/%iB/}"
+qemu-img create -f qcow2 "${myqcow2}.tmp.qcow2" ${clst_qcow2_size/%iB/} || die "Cannot create qcow2 file"
+
+echo "Connecting the qcow2 file to network block device ${mydevice}"
+qemu-nbd -c ${mydevice} -f qcow2 "${myqcow2}.tmp.qcow2" || die "Cannot connect qcow2 file to nbd0"
+
+echo "Creating a GPT disklabel"
+parted -s ${mydevice} mklabel gpt || qcow2die "Cannot create disklabel"
+
+echo "Creating an EFI boot partition"
+parted -s ${mydevice} -- mkpart gentooefi fat32 1M ${clst_qcow2_efisize} || qcow2die "Cannot create EFI partition"
+# mark it as EFI boot partition
+parted -s ${mydevice} -- type 1 C12A7328-F81F-11D2-BA4B-00A0C93EC93B || qcow2die "Cannot set EFI partition UUID"
+# note down name
+mypartefi=${mydevice}p1
+
+echo "Creating the root partition"
+parted -s ${mydevice} -- mkpart gentooroot ${clst_qcow2_roottype} ${clst_qcow2_efisize}GiB -1M || qcow2die "Cannot create root partition"
+# mark it as generic linux filesystem partition
+parted -s ${mydevice} -- type 2 0FC63DAF-8483-4772-8E79-3D69D8477DE4 || qcow2die "Cannot set root partition UUID"
+# note down name
+mypartroot=${mydevice}p2
+
+echo "Re-reading the partition table"
+partprobe ${mydevice} || qcow2die "Probing partition table failed"
+
+echo "Printing the partition table"
+parted -s ${mydevice} -- print || qcow2die "Printing the partition table failed"
+
+echo "Making a vfat filesystem in p1"
+mkfs.fat -v -F 32 -n gentooefi ${mypartefi} || qcow2die "Formatting EFI partition failed"
+
+echo "Making an xfs filesystem in p2"
+mkfs.xfs -L gentooroot ${mypartroot} || qcow2die "Formatting root partition failed"
+
+echo "Printing blkid output"
+blkid ${mydevice}* || qcow2die "blkid failed"
+
+echo "Mounting things at ${mymountpoint}"
+mkdir -p "${mymountpoint}" || qcow2die "Could not create root mount point"
+mount ${mypartroot} "${mymountpoint}" || qcow2die "Could not mount root partition"
+mkdir -p "${mymountpoint}"/boot || qcow2die "Could not create boot mount point"
+mount ${mypartefi} "${mymountpoint}/boot" || qcow2die "Could not mount boot partition"
+
+# copy contents in; the source is the stage dir and not any "iso content"
+echo "Copying files into the mounted directories from ${clst_stage_path}"
+cp -a "${clst_stage_path}"/* "${mymountpoint}/" || qcow2die "Could not copy content into mounted image"
+
+echo "Setting machine-id to empty"
+# We are already running systemd-firstboot in a previous step, so we don't want to run it again.
+# The documented behaviour for an empty machine-id is that systemd generates a new one and commits
+# it on first boot, but otherwise treats the system as already initialized.
+rm -f "${mymountpoint}/etc/machine-id"
+touch "${mymountpoint}/etc/machine-id" || qcow2die "Could not set machine-id to empty"
+
+# now we can chroot in and install grub
+exec_in_qcow2 "${clst_shdir}/support/qcow2-grub-install.sh"
+
+echo "Generating /etc/fstab"
+cat > "${mymountpoint}/etc/fstab" <<END
+# /etc/fstab: static file system information.
+#
+# See the manpage fstab(5) for more information.
+#
+# <fs> <mountpoint> <type> <opts> <dump/pass>
+
+LABEL=gentooroot / xfs noatime,rw 0 1
+LABEL=gentooefi /boot vfat defaults 1 2
+
+END
+
+echo "Creating a CONTENTS file ${myqcow2}.CONTENTS"
+pushd "${mymountpoint}/" &> /dev/null || qcow2die "Could not cd into mountpoint"
+ls -laR > "${myqcow2}.CONTENTS" || qcow2die "Could not create CONTENTS file"
+popd &> /dev/null || qcow2die "Could not cd out of mountpoint"
+
+echo "Compressing the CONTENTS file"
+gzip "${myqcow2}.CONTENTS" || qcow2die "Could not compress the CONTENTS file"
+
+echo "Unmounting things"
+umount "${mymountpoint}/boot" || qcow2die "Could not unmount boot partition"
+umount "${mymountpoint}" || qcow2die "Could not unmount root partition"
+
+echo "Disconnecting ${mydevice}"
+qemu-nbd -d ${mydevice} || qcow2die "Could not disconnect ${mydevice}"
+
+echo "Rewriting the qcow2 file with stream compression to ${myqcow2}"
+qemu-img convert -c -O qcow2 "${myqcow2}.tmp.qcow2" "${myqcow2}" || qcow2die "Could not compress QCOW2 file"
+
+echo "Cleaning up"
+rm "${myqcow2}.tmp.qcow2" || qcow2die "Could not delete uncompressed QCOW2 file"
+rmdir "${mymountpoint}" || qcow2die "Could not remove mountpoint"
+
+# Finished...