Skip to content

Commit

Permalink
fix bugs in disk-expand (#879)
Browse files Browse the repository at this point in the history
  • Loading branch information
hopkiw authored Mar 25, 2020
1 parent eff97a7 commit dad8239
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 35 deletions.
1 change: 1 addition & 0 deletions packages/gce-disk-expand/packaging/debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -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.
4 changes: 3 additions & 1 deletion packages/gce-disk-expand/packaging/gce-disk-expand.spec
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
42 changes: 22 additions & 20 deletions packages/gce-disk-expand/src/expandfs-lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
Expand Down Expand Up @@ -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
parted -m ---pretend-input-tty "$disk" print Fix >/dev/null 2>&1 </dev/null
if parted -sm "$disk" print 2>&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."
Expand All @@ -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}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -29,39 +29,39 @@ 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

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

0 comments on commit dad8239

Please sign in to comment.