diff options
Diffstat (limited to 'modules.d/dnbd3-rootfs/hooks/s3-dnbd3root.sh')
-rwxr-xr-x | modules.d/dnbd3-rootfs/hooks/s3-dnbd3root.sh | 153 |
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 |