#!/usr/bin/env bash # region imports type emergency_shell > /dev/null 2>&1 || source /lib/dracut-lib.sh source /etc/openslx source '/usr/lib/rebash/core.sh' core.import exceptions core.import logging # endregion # region globals/helper logging.set_log_file "${SLX_LOG_FILE_PATH:-/var/log/openslx}" # 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 logging.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 logging.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 logging.warn "Failed to attach '$in_device' to '$out_device'." return fi udevadm settle echo "$out_device" } container_unpack_losetup() { local in_device="$1" local out_device="$(losetup -f)" if ! losetup -r -t QCOW "$out_device" "$in_device" --partscan; then logging.warn "Failed to attach '$in_device' to '$out_device'." return fi udevadm settle echo "$out_device" } # endregion # region connect dnbd3 image # Determine stage4 image path and revision if [ -z "$SLX_DNBD3_IMAGE" ]; then # specified on the KCL? SLX_DNBD3_IMAGE="$(getarg slx.stage4.path=)" fi if [ -z "$SLX_DNBD3_IMAGE" ]; then # not specified, fall back to old bwlp default path convention SLX_DNBD3_IMAGE="stage4/bwlp/maxilinux-$(uname -r)" fi # save it for later echo "SLX_DNBD3_IMAGE='$SLX_DNBD3_IMAGE'" >> /etc/openslx if [ -z "$SLX_DNBD3_RID" ]; then # specified on the KCL? SLX_DNBD3_RID="$(getarg slx.stage4.rid=)" fi if [ -n "$SLX_DNBD3_RID" ]; then _dnbd3_client_additional_args=("--rid" "$SLX_DNBD3_RID") echo "SLX_DNBD3_RID='$SLX_DNBD3_RID'" >> /etc/openslx fi exceptions.try { ( IFS=", " for host in ${SLX_DNBD3_SERVERS} FAIL; do if [ "$host" = "FAIL" ]; then emergency_shell "Failed to connect '${SLX_DNBD3_IMAGE}' "\ "${SLX_DNBD3_RID:+(revision: $SLX_DNBD3_RID)} " "from one of '$SLX_DNBD3_SERVERS' to '$_dnbd3_dev'." fi logging.info "Trying host \"$host\"." if systemd-preserve-process-marker dnbd3-client \ --host "$host" \ --image "${SLX_DNBD3_IMAGE}" \ --device "$_dnbd3_dev" \ "${_dnbd3_client_additional_args[@]}"; then break fi done ) # endregion # region unpack dnbd3 image [ -z "$SLX_QCOW_HANDLER" ] && SLX_QCOW_HANDLER="kernel" if [ "$SLX_QCOW_HANDLER" = "xmount" ]; then read_only_device="$(container_unpack_xmount "$_dnbd3_dev")" elif [ "$SLX_QCOW_HANDLER" = "kernel" ]; then read_only_device="$(container_unpack_losetup "$_dnbd3_dev")" else logging.warn "Unsupported QCOW handler: $SLX_QCOW_HANDLER" 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 if [ -z "$SLX_SYSTEM_PARTITION_IDENTIFIER" ]; then SLX_SYSTEM_PARTITION_IDENTIFIER="SLX_SYS" echo "SLX_SYSTEM_PARTITION_IDENTIFIER='$SLX_SYSTEM_PARTITION_IDENTIFIER'" >> /etc/openslx fi read_only_partition="$(slx-tools dev_find_partitions \ "$read_only_device" "$SLX_SYSTEM_PARTITION_IDENTIFIER")" else eval "$SLX_SYSTEM_PARTITION_PREPARATION_SCRIPT" fi if [[ ! $? || -z "$read_only_partition" ]]; then logging.error "Failed to find unique device with identifier" \ "\"${SLX_SYSTEM_PARTITION_IDENTIFIER}\"; matched devices:" \ "\"${read_only_partition}\"" exit 1 fi logging.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 } exceptions.catch { logging.error "$exceptions_last_traceback" emergency_shell "error in ${BASH_SOURCE[0]}" } # region vim modline # vim: set tabstop=4 shiftwidth=4 expandtab: # vim: foldmethod=marker foldmarker=region,endregion: # endregion