#!/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)" 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 IFS=", " 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" # endregion