summaryrefslogtreecommitdiffstats
path: root/modules.d/95nbd
diff options
context:
space:
mode:
Diffstat (limited to 'modules.d/95nbd')
-rwxr-xr-xmodules.d/95nbd/module-setup.sh39
-rwxr-xr-xmodules.d/95nbd/nbd-generator.sh64
-rwxr-xr-xmodules.d/95nbd/nbdroot.sh137
-rwxr-xr-xmodules.d/95nbd/parse-nbdroot.sh64
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