diff options
Diffstat (limited to 'modules.d/95nbd')
-rwxr-xr-x | modules.d/95nbd/module-setup.sh | 39 | ||||
-rwxr-xr-x | modules.d/95nbd/nbd-generator.sh | 64 | ||||
-rwxr-xr-x | modules.d/95nbd/nbdroot.sh | 137 | ||||
-rwxr-xr-x | modules.d/95nbd/parse-nbdroot.sh | 64 |
4 files changed, 304 insertions, 0 deletions
diff --git a/modules.d/95nbd/module-setup.sh b/modules.d/95nbd/module-setup.sh new file mode 100755 index 0000000..aa3570a --- /dev/null +++ b/modules.d/95nbd/module-setup.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +# called by dracut +check() { + local _rootdev + + # if an nbd device is not somewhere in the chain of devices root is + # mounted on, fail the hostonly check. + [[ $hostonly ]] || [[ $mount_needs ]] && { + _rootdev=$(find_root_block_device) + [[ -b /dev/block/$_rootdev ]] || return 1 + check_block_and_slaves block_is_nbd "$_rootdev" || return 255 + } + require_binaries nbd-client || return 1 + + return 0 +} + +# called by dracut +depends() { + # We depend on network modules being loaded + echo network rootfs-block +} + +# called by dracut +installkernel() { + instmods nbd +} + +# called by dracut +install() { + inst nbd-client + inst_hook cmdline 90 "$moddir/parse-nbdroot.sh" + inst_script "$moddir/nbdroot.sh" "/sbin/nbdroot" + if dracut_module_included "systemd-initrd"; then + inst_script "$moddir/nbd-generator.sh" "$systemdutildir"/system-generators/dracut-nbd-generator + fi + dracut_need_initqueue +} diff --git a/modules.d/95nbd/nbd-generator.sh b/modules.d/95nbd/nbd-generator.sh new file mode 100755 index 0000000..38603bf --- /dev/null +++ b/modules.d/95nbd/nbd-generator.sh @@ -0,0 +1,64 @@ +#!/bin/sh + +type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh + +[ -z "$root" ] && root=$(getarg root=) + +[ "${root%%:*}" = "nbd" ] || exit 0 + +GENERATOR_DIR="$2" +[ -z "$GENERATOR_DIR" ] && exit 1 + +[ -d "$GENERATOR_DIR" ] || mkdir -p "$GENERATOR_DIR" + +ROOTFLAGS="$(getarg rootflags)" + +nroot=${root#nbd:} +nbdserver=${nroot%%:*} +if [ "${nbdserver%"${nbdserver#?}"}" = "[" ]; then + nbdserver=${nroot#[} + nbdserver=${nbdserver%%]:*}\] + nroot=${nroot#*]:} +else + nroot=${nroot#*:} +fi +nbdport=${nroot%%:*} +nroot=${nroot#*:} +nbdfstype=${nroot%%:*} +nroot=${nroot#*:} +nbdflags=${nroot%%:*} + +if [ "$nbdflags" = "$nbdfstype" ]; then + unset nbdflags +fi +if [ "$nbdfstype" = "$nbdport" ]; then + unset nbdfstype +fi + +[ -n "$nbdflags" ] && ROOTFLAGS="$nbdflags" + +if getarg "ro"; then + if [ -n "$ROOTFLAGS" ]; then + ROOTFLAGS="$ROOTFLAGS,ro" + else + ROOTFLAGS="ro" + fi +fi + +if [ -n "$nbdfstype" ]; then + ROOTFSTYPE="$nbdfstype" +else + ROOTFSTYPE=$(getarg rootfstype=) || unset ROOTFSTYPE +fi + +{ + echo "[Unit]" + echo "Before=initrd-root-fs.target" + echo "[Mount]" + echo "Where=/sysroot" + echo "What=/dev/root" + [ -n "$ROOTFSTYPE" ] && echo "Type=${ROOTFSTYPE}" + [ -n "$ROOTFLAGS" ] && echo "Options=${ROOTFLAGS}" +} > "$GENERATOR_DIR"/sysroot.mount + +exit 0 diff --git a/modules.d/95nbd/nbdroot.sh b/modules.d/95nbd/nbdroot.sh new file mode 100755 index 0000000..b1a8030 --- /dev/null +++ b/modules.d/95nbd/nbdroot.sh @@ -0,0 +1,137 @@ +#!/bin/sh + +type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh + +PATH=/usr/sbin:/usr/bin:/sbin:/bin + +# Huh? Empty $1? +[ -z "$1" ] && exit 1 + +# Huh? Empty $2? +[ -z "$2" ] && exit 1 + +# Huh? Empty $3? +[ -z "$3" ] && exit 1 + +# root is in the form root=nbd:srv:port[:fstype[:rootflags[:nbdopts]]] +# shellcheck disable=SC2034 +netif="$1" +nroot="$2" +NEWROOT="$3" + +# If it's not nbd we don't continue +[ "${nroot%%:*}" = "nbd" ] || return + +nroot=${nroot#nbd:} +nbdserver=${nroot%%:*} +if [ "${nbdserver%"${nbdserver#?}"}" = "[" ]; then + nbdserver=${nroot#[} + nbdserver=${nbdserver%%]:*} + nroot=${nroot#*]:} +else + nroot=${nroot#*:} +fi +nbdport=${nroot%%:*} +nroot=${nroot#*:} +nbdfstype=${nroot%%:*} +nroot=${nroot#*:} +nbdflags=${nroot%%:*} +nbdopts=${nroot#*:} + +if [ "$nbdopts" = "$nbdflags" ]; then + unset nbdopts +fi +if [ "$nbdflags" = "$nbdfstype" ]; then + unset nbdflags +fi +if [ "$nbdfstype" = "$nbdport" ]; then + unset nbdfstype +fi +if [ -z "$nbdfstype" ]; then + nbdfstype=auto +fi + +# look through the NBD options and pull out the ones that need to +# go before the host etc. Append a ',' so we know we terminate the loop +nbdopts=${nbdopts}, +while [ -n "$nbdopts" ]; do + f=${nbdopts%%,*} + nbdopts=${nbdopts#*,} + if [ -z "$f" ]; then + break + fi + if [ -z "${f%bs=*}" -o -z "${f%timeout=*}" ]; then + preopts="$preopts $f" + continue + fi + opts="$opts $f" +done + +# look through the flags and see if any are overridden by the command line +nbdflags=${nbdflags}, +while [ -n "$nbdflags" ]; do + f=${nbdflags%%,*} + nbdflags=${nbdflags#*,} + if [ -z "$f" ]; then + break + fi + if [ "$f" = "ro" -o "$f" = "rw" ]; then + nbdrw=$f + continue + fi + fsopts=${fsopts:+$fsopts,}$f +done + +getarg ro && nbdrw=ro +getarg rw && nbdrw=rw +fsopts=${fsopts:+$fsopts,}${nbdrw} + +# XXX better way to wait for the device to be made? +i=0 +while [ ! -b /dev/nbd0 ]; do + [ $i -ge 20 ] && exit 1 + udevadm settle --exit-if-exists=/dev/nbd0 + i=$((i + 1)) +done + +# If we didn't get a root= on the command line, then we need to +# add the udev rules for mounting the nbd0 device +if [ "$root" = "block:/dev/root" -o "$root" = "dhcp" ]; then + printf 'KERNEL=="nbd0", ENV{DEVTYPE}!="partition", ENV{ID_FS_TYPE}=="?*", SYMLINK+="root"\n' > /etc/udev/rules.d/99-nbd-root.rules + udevadm control --reload + wait_for_dev -n /dev/root + + if [ -z "$DRACUT_SYSTEMD" ]; then + type write_fs_tab > /dev/null 2>&1 || . /lib/fs-lib.sh + + write_fs_tab /dev/root "$nbdfstype" "$fsopts" + + printf '/bin/mount %s\n' \ + "$NEWROOT" \ + > "$hookdir"/mount/01-$$-nbd.sh + else + mkdir -p /run/systemd/system/sysroot.mount.d + cat << EOF > /run/systemd/system/sysroot.mount.d/dhcp.conf +[Mount] +Where=/sysroot +What=/dev/root +Type=$nbdfstype +Options=$fsopts +EOF + systemctl --no-block daemon-reload + fi + # if we're on systemd, use the nbd-generator script + # to create the /sysroot mount. +fi + +if ! [ "$nbdport" -gt 0 ] 2> /dev/null; then + nbdport="-name $nbdport" +fi + +if ! nbd-client -check /dev/nbd0 > /dev/null; then + # shellcheck disable=SC2086 + nbd-client -p -systemd-mark "$nbdserver" $nbdport /dev/nbd0 $opts || exit 1 +fi + +need_shutdown +exit 0 diff --git a/modules.d/95nbd/parse-nbdroot.sh b/modules.d/95nbd/parse-nbdroot.sh new file mode 100755 index 0000000..1c3f0a0 --- /dev/null +++ b/modules.d/95nbd/parse-nbdroot.sh @@ -0,0 +1,64 @@ +#!/bin/sh +# +# Preferred format: +# root=nbd:srv:port/exportname[:fstype[:rootflags[:nbdopts]]] +# [root=*] netroot=nbd:srv:port/exportname[:fstype[:rootflags[:nbdopts]]] +# +# nbdopts is a comma separated list of options to give to nbd-client +# +# root= takes precedence over netroot= if root=nbd[...] +# + +# This script is sourced, so root should be set. But let's be paranoid +[ -z "$root" ] && root=$(getarg root=) + +if [ -z "$netroot" ]; then + for netroot in $(getargs netroot=); do + [ "${netroot%%:*}" = "nbd" ] && break + done + [ "${netroot%%:*}" = "nbd" ] || unset netroot +fi + +# Root takes precedence over netroot +if [ "${root%%:*}" = "nbd" ]; then + if [ -n "$netroot" ]; then + warn "root takes precedence over netroot. Ignoring netroot" + + fi + netroot=$root + unset root +fi + +# If it's not nbd we don't continue +[ "${netroot%%:*}" = "nbd" ] || return + +# Check required arguments +nroot=${netroot#nbd:} +server=${nroot%%:*} +if [ "${server%"${server#?}"}" = "[" ]; then + server=${nroot#[} + server=${server%%]:*}\] + nroot=${nroot#*]:} +else + nroot=${nroot#*:} +fi +port=${nroot%%:*} +unset nroot + +[ -z "$server" ] && die "Argument server for nbdroot is missing" +[ -z "$port" ] && die "Argument port for nbdroot is missing" + +# NBD actually supported? +incol2 /proc/devices nbd || modprobe nbd || die "nbdroot requested but kernel/initrd does not support nbd" + +# Done, all good! +# shellcheck disable=SC2034 +rootok=1 + +# Shut up init error check +if [ -z "$root" ]; then + root=block:/dev/root + # the device is created and waited for in ./nbdroot.sh +fi + +echo 'nbd-client -check /dev/nbd0 > /dev/null 2>&1' > "$hookdir"/initqueue/finished/nbdroot.sh |