Skip to content

Commit eed4c31

Browse files
author
Prakash Surya
authored
DLPX-72158 create script to more easily update grub configuration (#478)
PR URL: https://www.github.com/delphix/delphix-platform/pull/478
1 parent a242c56 commit eed4c31

File tree

1 file changed

+184
-0
lines changed

1 file changed

+184
-0
lines changed
+184
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
#!/bin/bash
2+
#
3+
# Copyright 2024 Delphix
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
18+
function die() {
19+
echo "$(basename "$0"): $*" >&2
20+
exit 1
21+
}
22+
23+
function warn() {
24+
echo "$(basename "$0"): $*" >&2
25+
}
26+
27+
function usage() {
28+
echo "$(basename "$0"): $*" >&2
29+
30+
PREFIX_STRING="Usage: $(basename "$0")"
31+
PREFIX_NCHARS=$(echo -n "$PREFIX_STRING" | wc -c)
32+
PREFIX_SPACES=$(printf "%.s " $(seq "$PREFIX_NCHARS"))
33+
34+
echo "$PREFIX_STRING update"
35+
echo "$PREFIX_SPACES recover <rpool> <rootfs>"
36+
37+
exit 2
38+
}
39+
40+
function get_bootloader_devices() {
41+
#
42+
# When installing/updating the bootloader during upgrade, we
43+
# need to determine which devices are being used as bootloader
44+
# devices. We determine this by listing the devices used by the
45+
# rpool. Additionally, we have to filter out devices that could
46+
# be attached to the rpool, but would never be used for the
47+
# bootloader. Finally, we need to strip off any parition
48+
# information, since we want to install the bootloader directly
49+
# to the device, rather than to a partition of the device.
50+
#
51+
zpool list -vH "$1" | tail -n -1 |
52+
awk '! /mirror|replacing|spare/ {print $1}' |
53+
while read -r part; do
54+
#
55+
# If the rpool is not installed a parition, we throw
56+
# an error. We expect this to never happen, and the
57+
# calling code is likely untested in that case, so we
58+
# throw an error rather than try to handle it.
59+
#
60+
[[ "$(lsblk --nodeps -no type "/dev/$part")" == "part" ]] ||
61+
die "rpool installed on full disk \"$part\""
62+
lsblk -no pkname "/dev/$part"
63+
done
64+
}
65+
66+
function update_bootloader_cleanup() {
67+
[[ -n "$MKTEMP" ]] || return
68+
umount "$MKTEMP" || warn "'umount' of '$MKTEMP' failed"
69+
rm -d "$MKTEMP" || warn "'rm -d $MKTEMP' failed"
70+
}
71+
72+
function update_bootloader() {
73+
MKTEMP=$(mktemp -d -p "/var/tmp" -t bootloader.XXXXXXX)
74+
75+
trap update_bootloader_cleanup EXIT
76+
77+
mount -t zfs "${1}/grub" "$MKTEMP" ||
78+
die "'mount -t zfs ${1}/grub' failed"
79+
80+
for dev in $(get_bootloader_devices "$1"); do
81+
[[ -e "/dev/$dev" ]] ||
82+
die "bootloader device '/dev/$dev' not found"
83+
84+
[[ -b "/dev/$dev" ]] ||
85+
die "bootloader device '/dev/$dev' not block device"
86+
87+
grub-install -v --debug-image=all \
88+
--root-directory="$MKTEMP" "/dev/$dev" ||
89+
die "'grub-install' for '$dev' failed"
90+
done
91+
92+
grub-mkconfig -o "$MKTEMP/boot/grub/grub.cfg" ||
93+
die "'grub-mkconfig' failed"
94+
95+
update_bootloader_cleanup
96+
trap - EXIT
97+
}
98+
99+
function recover_bootloader_cleanup() {
100+
umount "/$RPOOL/mnt" ||
101+
warn "'umount' of '/$RPOOL/mnt' failed"
102+
103+
for dir in /proc /sys /dev; do
104+
umount -R "/${RPOOL}${dir}" ||
105+
warn "'umount -R' of '$dir' failed"
106+
done
107+
108+
zfs umount "$RPOOL/ROOT/$CONTAINER/root" ||
109+
warn "'zfs umount $RPOOL/ROOT/$CONTAINER/root' failed"
110+
}
111+
112+
function recover_bootloader() {
113+
RPOOL="$1"
114+
CONTAINER="$2"
115+
116+
trap recover_bootloader_cleanup EXIT
117+
118+
zfs mount "$RPOOL/ROOT/$CONTAINER/root" ||
119+
die "'zfs mount $RPOOL/ROOT/$CONTAINER/root' failed"
120+
121+
mount --make-slave "/$RPOOL" ||
122+
die "'mount --make-slave /$RPOOL' failed"
123+
124+
for dir in /proc /sys /dev; do
125+
mount --rbind "$dir" "/${RPOOL}${dir}" ||
126+
die "'mount --rbind' of '$dir' failed"
127+
mount --make-rslave "/${RPOOL}${dir}" ||
128+
die "'mount --make-rslave' of '$dir' failed"
129+
done
130+
131+
mount -t zfs "$RPOOL/grub" "/$RPOOL/mnt" ||
132+
die "'mount -t zfs $RPOOL/grub' failed for '$CONTAINER'"
133+
134+
for dev in $(get_bootloader_devices "$RPOOL"); do
135+
[[ -e "/dev/$dev" ]] ||
136+
die "bootloader device '/dev/$dev' not found"
137+
138+
[[ -b "/dev/$dev" ]] ||
139+
die "bootloader device '/dev/$dev' not block device"
140+
141+
chroot "/$RPOOL" \
142+
grub-install -v --debug-image=all \
143+
--root-directory=/mnt "/dev/$dev" ||
144+
die "'grub-install' for '$dev' failed in '$CONTAINER'"
145+
done
146+
147+
chroot "/$RPOOL" \
148+
grub-mkconfig -o /mnt/boot/grub/grub.cfg ||
149+
die "'grub-mkconfig' failed in '$CONTAINER'"
150+
151+
recover_bootloader_cleanup
152+
trap - EXIT
153+
}
154+
155+
[[ "$EUID" -ne 0 ]] && die "must be run as root"
156+
157+
#
158+
# We only have a single bootloader on any given appliance, so we
159+
# need to ensure that only a single process is attempting to
160+
# update the bootloader at any given time. The locking done here
161+
# is to help prevent accidential corruption of the bootloader,
162+
# by ensuring only a single invocation of this script can set
163+
# the boot filesystem at any given time.
164+
#
165+
# Note, we use the same lock file path here as the upgrade scripts.
166+
#
167+
if [[ "$SET_BOOTFS_LOCKED" != "true" ]]; then
168+
exec env SET_BOOTFS_LOCKED="true" \
169+
flock -e "/var/run/delphix-set-bootfs-lock" "$0" "$@"
170+
fi
171+
172+
case "$1" in
173+
update)
174+
update_bootloader "rpool"
175+
;;
176+
recover)
177+
[[ -n "$2" ]] || usage "rpool name not specified"
178+
[[ -n "$3" ]] || usage "rootfs container name not specified"
179+
recover_bootloader "$2" "$3"
180+
;;
181+
*)
182+
usage "invalid option -- '$1'"
183+
;;
184+
esac

0 commit comments

Comments
 (0)