summaryrefslogtreecommitdiffstats
path: root/modules.d/dnbd3-rootfs/hooks/s3-dnbd3root.sh
diff options
context:
space:
mode:
Diffstat (limited to 'modules.d/dnbd3-rootfs/hooks/s3-dnbd3root.sh')
-rwxr-xr-xmodules.d/dnbd3-rootfs/hooks/s3-dnbd3root.sh153
1 files changed, 153 insertions, 0 deletions
diff --git a/modules.d/dnbd3-rootfs/hooks/s3-dnbd3root.sh b/modules.d/dnbd3-rootfs/hooks/s3-dnbd3root.sh
new file mode 100755
index 00000000..01a8c32c
--- /dev/null
+++ b/modules.d/dnbd3-rootfs/hooks/s3-dnbd3root.sh
@@ -0,0 +1,153 @@
+#!/usr/bin/env bash
+type emergency_shell > /dev/null 2>&1 || source /lib/dracut-lib.sh
+source /etc/openslx
+
+export PATH="/usr/local/bin:$PATH"
+export LD_LIBRARY_PATH="/usr/local/lib"
+
+
+# hardcode dnbd device path
+declare -rg _dnbd3_dev="/dev/dnbd0"
+
+# all outputs are redirected to stderr, since this functions should
+# only echo the path to the unpacked container to stdout.
+container_unpack_xmount() {
+ local in_device="$1"
+ local out_path="/mnt/xmount"
+ mkdir -p "$out_path"
+ # check tools first
+ if ! hash xmount systemd-preserve-process-marker; then
+ warn "Missing xmount deps, will try raw..." 1>&2
+ elif ! systemd-preserve-process-marker xmount \
+ --in qemu "$in_device" \
+ --out raw "$out_path" &>/dev/null; then
+ warn "xmount call failed, assuming raw image." 1>&2
+ else
+ in_device="${out_path}/${_dnbd3_dev##*/}.dd"
+ fi
+ local out_device="$(losetup -f)"
+ if ! losetup "$out_device" "$in_device" --partscan; then
+ warn "Failed to attach '$in_device' to '$out_device'."
+ return 1
+ fi
+ udevadm settle
+ echo "$out_device"
+}
+
+container_unpack_xloop() {
+ local in_device="$1"
+ local out_device="$(xlosetup -f)"
+ for kmod in xloop xloop_file_fmt_qcow xloop_file_fmt_raw; do
+ if ! modprobe "${kmod}"; then
+ warn "Failed to load kernel module: $kmod"
+ fi
+ done
+ if ! xlosetup -r -t QCOW "$out_device" "$in_device" --partscan; then
+ warn "Failed to attach '$in_device' to '$out_device'."
+ return
+ fi
+ udevadm settle
+ echo "$out_device"
+}
+# endregion
+
+# region connect dnbd3 image
+# Determine path to dnbd3 image: either on the kcl or via config file
+declare -r KCL_DNBD3_IMAGE="$(getarg slx.stage4.path=)"
+if [ -n "$KCL_DNBD3_IMAGE" ]; then
+ SLX_DNBD3_IMAGE="$KCL_DNBD3_IMAGE"
+ echo "SLX_DNBD3_IMAGE='$SLX_DNBD3_IMAGE'" >> /etc/openslx
+fi
+if [ -z "$SLX_DNBD3_IMAGE" ]; then
+ emergency_shell "Failed to determine which DNBD3 image to use." \
+ "It was neither specified on kernel command line nor in the" \
+ "configuration file."
+fi
+declare -r KCL_DNBD3_RID="$(getarg slx.stage4.rid=)"
+if [ -n "$KCL_DNBD3_RID" ]; then
+ # specified on the KCL?
+ SLX_DNBD3_RID="$KCL_DNBD3_RID"
+ echo "SLX_DNBD3_RID='$SLX_DNBD3_RID'" >> /etc/openslx
+fi
+if [ -n "$SLX_DNBD3_RID" ]; then
+ _dnbd3_client_additional_args=("--rid" "$SLX_DNBD3_RID")
+fi
+
+if ! modprobe dnbd3; then
+ warn "Failed to load kernel module: dnbd3"
+fi
+
+for try in {1..5} ""; do
+ if [ -z "$try" ]; then
+ emergency_shell "Failed to connect '${SLX_DNBD3_IMAGE}'" \
+ "(revision: ${SLX_DNBD3_RID:-0})" \
+ "from one of '$SLX_DNBD3_SERVERS' to '$_dnbd3_dev'." \
+ "Check if the image exists on one of the servers" \
+ "and if any is reachable from this client."
+ fi
+ info "Trying hosts '$SLX_DNBD3_SERVERS'."
+ if dnbd3-client \
+ --host "$SLX_DNBD3_SERVERS" \
+ --image "$SLX_DNBD3_IMAGE" \
+ --device "$_dnbd3_dev" \
+ "${_dnbd3_client_additional_args[@]}"; then
+ break
+ fi
+ sleep 1
+done
+
+# endregion
+# region unpack dnbd3 image
+if ! [[ $SLX_QCOW_HANDLER =~ ^(kernel|xloop|xmount)?$ ]]; then
+ emergency_shell "Unsupported QCOW handler: $SLX_QCOW_HANDLER" \
+ "Use either 'xmount' or 'xloop'."
+fi
+if [ -z "$SLX_QCOW_HANDLER" ]; then
+ SLX_QCOW_HANDLER="xloop"
+ echo "SLX_QCOW_HANDLER='$SLX_QCOW_HANDLER'" >> /etc/openslx
+fi
+if [[ $SLX_QCOW_HANDLER =~ ^kernel|xloop$ ]]; then
+ read_only_device="$(container_unpack_xloop "$_dnbd3_dev")"
+fi
+if [ -z "$read_only_device" ]; then
+ read_only_device="$(container_unpack_xmount "$_dnbd3_dev")"
+fi
+
+# Fail fast if unpacking dnbd3 image failed.
+if [ -z "$read_only_device" ]; then
+ emergency_shell "Failed to unpack the qcow2 image!"
+fi
+
+# endregion
+# region find system partition within dnbd3 image
+if [ -z "$SLX_SYSTEM_PARTITION_PREPARATION_SCRIPT" ]; then
+ # Find requested root partition - default to SLX_SYS label
+ read_only_partition="$( slx-tools dev_find_partitions \
+ "$read_only_device" "${SLX_SYSTEM_PARTITION_IDENTIFIER:-SLX_SYS}" )"
+ if [ -z "$SLX_SYSTEM_PARTITION_IDENTIFIER" ]; then
+ if [ -n "$read_only_partition" ]; then
+ # Defaulting to SLX_SYS worked
+ echo "SLX_SYSTEM_PARTITION_IDENTIFIER='SLX_SYS'" >> /etc/openslx
+ else
+ # Aussume there is no partition table
+ read_only_partition="$read_only_device"
+ fi
+ fi
+
+else
+ eval "$SLX_SYSTEM_PARTITION_PREPARATION_SCRIPT"
+fi
+if [[ -z "$read_only_partition" ]]; then
+ warn "Failed to find unique device with identifier" \
+ "\"${SLX_SYSTEM_PARTITION_IDENTIFIER}\"; matched devices:" \
+ "\"${read_only_partition}\""
+ exit 1
+fi
+info "Using read-only partition: $read_only_partition"
+# endregion
+
+# region add rw layer to dnbd3 image
+# don't be fooled to think we are done, the next part is crucial
+dmsetup-slx-device "$read_only_partition"
+udevadm settle
+# endregion