From dad8239611d85fc697ff0905d60f00cc66ad747d Mon Sep 17 00:00:00 2001 From: Liam Hopkins Date: Wed, 25 Mar 2020 10:17:50 -0700 Subject: fix bugs in disk-expand (#879) --- packages/gce-disk-expand/packaging/debian/control | 1 + .../gce-disk-expand/packaging/gce-disk-expand.spec | 4 ++- packages/gce-disk-expand/src/expandfs-lib.sh | 42 +++++++++++----------- .../modules.d/50expand_rootfs/expand_rootfs.sh | 19 ++++++---- .../share/dracut/modules.d/50expand_rootfs/install | 1 + .../usr/share/initramfs-tools/hooks/expand-rootfs | 2 ++ .../scripts/local-premount/expand_rootfs | 16 ++++----- 7 files changed, 50 insertions(+), 35 deletions(-) (limited to 'packages') diff --git a/packages/gce-disk-expand/packaging/debian/control b/packages/gce-disk-expand/packaging/debian/control index ac38b5d..92f2e1b 100644 --- a/packages/gce-disk-expand/packaging/debian/control +++ b/packages/gce-disk-expand/packaging/debian/control @@ -9,6 +9,7 @@ Homepage: https://github.com/GoogleCloudPlatform/compute-image-packages Package: gce-disk-expand Architecture: all Depends: parted, + gdisk, ${misc:Depends} Description: Automatically resize the root partition on first boot. This package resizes the root partition on first boot using parted. diff --git a/packages/gce-disk-expand/packaging/gce-disk-expand.spec b/packages/gce-disk-expand/packaging/gce-disk-expand.spec index 409d898..3f6c0dc 100644 --- a/packages/gce-disk-expand/packaging/gce-disk-expand.spec +++ b/packages/gce-disk-expand/packaging/gce-disk-expand.spec @@ -20,9 +20,11 @@ License: Apache Software License Group: System Environment/Base URL: https://github.com/GoogleCloudPlatform/compute-image-packages Source0: %{name}_%{version}.orig.tar.gz -Requires: e2fsprogs, dracut, grep, util-linux, parted +Requires: e2fsprogs, dracut, grep, util-linux, parted, gdisk Conflicts: dracut-modules-growroot +BuildRequires: rsync + # Allow other files in the source that don't end up in the package. %define _unpackaged_files_terminate_build 0 diff --git a/packages/gce-disk-expand/src/expandfs-lib.sh b/packages/gce-disk-expand/src/expandfs-lib.sh index 69f67ed..4a02b9f 100755 --- a/packages/gce-disk-expand/src/expandfs-lib.sh +++ b/packages/gce-disk-expand/src/expandfs-lib.sh @@ -29,8 +29,8 @@ resize_filesystem() { ;; ext*) if ! out=$(e2fsck -pf "$disk"); then - echo "Calling e2fsck \"${disk}\" failed: ${out}" - return 1 + local ret=$? + echo "Calling e2fsck \"${disk}\" failed: ${out} exit code ${ret}" fi if ! out=$(resize2fs "$disk"); then echo "Calling resize2fs \"${disk}\" failed: ${out}" @@ -60,32 +60,31 @@ blkid_get_fstype() ( echo $ID_FS_TYPE ) +sgdisk_get_label() { + local root="$1" + [ -z "$root" ] && return 0 + + if sgdisk -p "$root" | grep -q "Found invalid GPT and valid MBR"; then + echo "mbr" + else + echo "gpt" + fi +} -# Checks for and corrects the end-of-disk GPT backup block in case of expanded -# disk. -parted_fix_gpt() { +sgdisk_fix_gpt() { local disk="$1" [ -z "$disk" ] && return - if parted -sm "$disk" print 2>&1 | grep -q "fix the GPT"; then - # Running parted prompts the user to fix this condition, but only does so in - # the interactive exception handler. In order to pass input we must use the - # hidden triple-dash flag and pass both print and Fix arguments. `print` - # alone will not perform the fix, but `Fix` alone will fail the argument - # parser. - parted -m ---pretend-input-tty "$disk" print Fix >/dev/null 2>&1 /dev/null 2>&1 &1 | grep -q "fix the GPT"; then - echo "Failed to fix the GPT." - return 1 - fi - fi + local label=$(sgdisk_get_label "$disk") + [ "$label" != "gpt" ] && return + + sgdisk --move-second-header "$disk" } # Returns "disk:partition", supporting multiple block types. split_partition() { local root="$1" disk="" partnum="" - [ -z "$root" ] && return + [ -z "$root" ] && return 0 if [ -e /sys/block/${root##*/} ]; then echo "Root is not a partition, skipping partition resize." @@ -104,7 +103,10 @@ split_partition() { # Checks if partition needs resizing. parted_needresize() { local disk="$1" partnum="$2" disksize="" partend="" - [ -z "$root" ] && return + if [ -z "$disk" ] || [ -z "$partnum" ]; then + echo "invalid args to parted_needresize" + return 1 + fi if ! out=$(parted -sm "$disk" unit b print 2>&1); then echo "Failed to get disk details: ${out}" diff --git a/packages/gce-disk-expand/src/usr/share/dracut/modules.d/50expand_rootfs/expand_rootfs.sh b/packages/gce-disk-expand/src/usr/share/dracut/modules.d/50expand_rootfs/expand_rootfs.sh index 3d12b35..62d7171 100755 --- a/packages/gce-disk-expand/src/usr/share/dracut/modules.d/50expand_rootfs/expand_rootfs.sh +++ b/packages/gce-disk-expand/src/usr/share/dracut/modules.d/50expand_rootfs/expand_rootfs.sh @@ -16,6 +16,12 @@ # Contains dracut-specific logic for detecting disk, then calls appropriate # library functions. +# Notes for developing dracut modules: this module must never exit with anything +# other than a 0 exit code. That means no use of set -e or traps on err, and +# every command must be defensively written so that errors are caught and +# logged, rather than causing end of execution. Note that error handling in the +# main() function always calls return 0 + kmsg() { echo "expand_rootfs: $@" > /dev/kmsg } @@ -49,13 +55,14 @@ main() { kmsg "Resizing disk ${rootdev}" + # First, move the secondary GPT to the end. + if ! out=$(sgdisk_fix_gpt "$disk"); then + kmsg "Failed to fix GPT: ${out}" + fi + if ! out=$(parted_resizepart "$disk" "$partnum"); then - # Try fixing the GPT and try resizing again. - parted_fix_gpt "$disk" - if ! out=$(parted_resizepart "$disk" "$partnum"); then - kmsg "Failed to resize partition: ${out}" - return - fi + kmsg "Failed to resize partition: ${out}" + return fi if ! out=$(resize_filesystem "$rootdev"); then diff --git a/packages/gce-disk-expand/src/usr/share/dracut/modules.d/50expand_rootfs/install b/packages/gce-disk-expand/src/usr/share/dracut/modules.d/50expand_rootfs/install index cdd021d..4fa6a5b 100755 --- a/packages/gce-disk-expand/src/usr/share/dracut/modules.d/50expand_rootfs/install +++ b/packages/gce-disk-expand/src/usr/share/dracut/modules.d/50expand_rootfs/install @@ -21,6 +21,7 @@ inst_hook pre-mount 50 "$moddir/expand_rootfs.sh" inst_hook pre-pivot 99 "$moddir/xfs_growfs.sh" dracut_install parted +dracut_install sgdisk dracut_install cut dracut_install sed dracut_install grep diff --git a/packages/gce-disk-expand/src/usr/share/initramfs-tools/hooks/expand-rootfs b/packages/gce-disk-expand/src/usr/share/initramfs-tools/hooks/expand-rootfs index dae461a..a463ea5 100755 --- a/packages/gce-disk-expand/src/usr/share/initramfs-tools/hooks/expand-rootfs +++ b/packages/gce-disk-expand/src/usr/share/initramfs-tools/hooks/expand-rootfs @@ -36,3 +36,5 @@ copy_exec /sbin/e2fsck /bin copy_exec /sbin/blkid /bin copy_exec /sbin/resize2fs /bin copy_exec /bin/udevadm /bin +copy_exec /usr/sbin/dmidecode /bin +copy_exec /sbin/sgdisk /bin diff --git a/packages/gce-disk-expand/src/usr/share/initramfs-tools/scripts/local-premount/expand_rootfs b/packages/gce-disk-expand/src/usr/share/initramfs-tools/scripts/local-premount/expand_rootfs index a380bc2..9b59b20 100755 --- a/packages/gce-disk-expand/src/usr/share/initramfs-tools/scripts/local-premount/expand_rootfs +++ b/packages/gce-disk-expand/src/usr/share/initramfs-tools/scripts/local-premount/expand_rootfs @@ -29,15 +29,15 @@ esac . /scripts/expandfs-lib.sh if ! rootdev=$(resolve_device "${ROOT}"); then - log_failure_message "Failed to resolve root device for \"${ROOT}\"" + log_failure_msg "Failed to resolve root device for \"${ROOT}\"" fi if ! fs_type=$(get_fstype "${rootdev}"); then - log_failure_message "Failed to determine fstype for \"${rootdev}\"" + log_failure_msg "Failed to determine fstype for \"${rootdev}\"" fi if ! out=$(split_partition "$rootdev"); then - log_failure_message "Failed to detect disk and partition info: ${out}" + log_failure_msg "Failed to detect disk and partition info: ${out}" exit 0 fi @@ -45,23 +45,23 @@ disk=${out%:*} partnum=${out#*:} if ! parted_needresize "${disk}" "${partnum}"; then - log_success_message "Disk ${rootdev} doesn't need resizing." + log_success_msg "Disk ${rootdev} doesn't need resizing." exit 0 fi -if ! out=$(parted_fix_gpt "$disk"); then - log_failure_message "Failed to fix GPT: ${out}" +if ! out=$(sgdisk_fix_gpt "$disk"); then + log_failure_msg "Failed to fix GPT: ${out}" exit 0 fi echo "Resizing partition on ${rootdev}" if ! out=$(parted_resizepart "${disk}" "${partnum}"); then - log_failure_message "Failed to resize partition: ${out}" + log_failure_msg "Failed to resize partition: ${out}" exit 0 fi echo "Resizing filesystem on ${rootdev}" if ! out=$(resize_filesystem "${rootdev}"); then - log_failure_message "Failed to resize filesystem: ${out}" + log_failure_msg "Failed to resize filesystem: ${out}" exit 0 fi -- cgit v1.2.1