#!/usr/bin/bash # dracut-lib to use debugging functions command -v warn >/dev/null || . /lib/dracut-lib.sh command -v emergency_shell >/dev/null || . /lib/dracut-lib.sh ############################################################################### # GLOBALS # # TODO make this configurable [ -f /opt/openslx/config ] && . /opt/openslx/config [ -z $SLX_DNBD3_SERVER ] && SLX_DNBD3_SERVER="132.230.4.1" [ -z $SLX_STAGE4 ] && SLX_STAGE4="stage4/joe/centos7" [ -z $SLX_STAGE4_RID ] && SLX_STAGE4_RID="4" declare -rg DNBD3_SERVER="$SLX_DNBD3_SERVER" declare -rg DNBD3_IMAGE="$SLX_STAGE4" declare -rg DNBD3_RID="$SLX_STAGE4_RID" declare -rg DNBD3_DEVICE="/dev/dnbd0" declare -rg QCOW_CONTAINER="/opt/openslx/system/system.qcow2" # # END GLOBALS ############################################################################### ############################################################################### # FUNCTION DEFINITIONS # # helper to do some sanity checks check_dnbd3() { if [ ! command -v "dnbd3-client" >/dev/null ]; then warn "No 'dnbd3-client' found. Was the initramfs built correctly?" emergency_shell -n "Error in $0" return 1 fi return 0 } # helper to connect to the dnbd3-server connect_dnbd3() { # check if it already connected local current_image_name="$(cat /sys/block/${DNBD3_DEVICE#/dev/}/net/image_name)" [ "x${current_image_name}" != "x(null)" ] && return 0 # not connected yet, do it if ! dnbd3-client -h "${DNBD3_SERVER}" \ -i "${DNBD3_IMAGE}" \ -r "${DNBD3_RID}" \ -d "${DNBD3_DEVICE}" ; then warn "Failed to mount $DNBD3_IMAGE from $DNBD3_SERVER to $DNBD3_DEVICE" emergency_shell -n "Error in $0" return 1 fi return 0 } # helper to create the qcow2 container file using # DNBD3_DEVICE as the base of the filesystem # QCOW_CONTAINER as the writable file # (our future rootfs) create_qcow() { # check if we already created the qcow2-container [ -e "$QCOW_CONTAINER" ] && return 0 # check if we have our target directory, if not create it [ ! -d "$(busybox dirname $QCOW_CONTAINER)" ] && \ mkdir -p "$(busybox dirname $QCOW_CONTAINER)" # we did not, let's create it if ! qemu-img create -f qcow2 -o \ backing_file="$DNBD3_DEVICE",backing_fmt=qcow2 "$QCOW_CONTAINER"; then warn "Failed to create qcow2-Container from $DNBD3_DEVICE" emergency_shell -n "Error in $0" rm -f -- "$QCOW_CONTAINER" return 1 fi return 0 } # helper to start qemu-nbd on localhost:2000 # use our wrapper to set argv[0][0] to '@' # this keeps qemu-nbd running after switching root export_qcow() { # check if we already have a qemu-nbd if [ -e /tmp/qemu-nbd.pid ]; then kill -0 $(cat /tmp/qemu-nbd.pid) && return 0 fi # since we use the wrapper, we need a little more logic to see if it runs /usr/bin/systemd-preserve-process-marker \ /usr/bin/qemu-nbd -t -p 2000 "$QCOW_CONTAINER" & # the wrapper returns 255 if the qemu-nbd binary is missing local qemu_nbd_pid="$!" for i in 0.5 1 2; do sleep $i if ! kill -0 $qemu_nbd_pid; then # not running wait $qemu_nbd_pid local ret_wrapper="$?" if [ "${ret_wrapper}" -eq 127 ]; then # wrapper was not found by bash warn "No such file or directory: /usr/bin/systemd-preserve-process-marker" elif [ "${ret_wrapper}" -eq 255 ]; then # qemu-nbd was not found warn "No such file or directory: /usr/bin/qemu-nbd" fi emergency_shell -n "Error in $0" return 1 else # all good, qemu-nbd is running, remember its pid echo $qemu_nbd_pid > /tmp/qemu-nbd.pid return 0 fi done # fallback return 1 } # helper to mount the qcow2-container per nbd connect_qcow() { # try to mount the locally exported qcow2-container using nbd-client if nbd-client --systemd-mark --persist 127.0.0.1 2000 /dev/nbd0; then # it worked, lets set the symlink to /dev/root as dracut needs it # later on to mount that device to the future root (/sysroot) ln -sf /dev/nbd0 /dev/root return 0 else # this is pretty bad, dracut would spawn an emergency later on # since there is no /dev/root to mount. # For debugging purposes, we drop an emergency shell ourselves # if the mount fails. warn "Could not mount /dev/nbd0 from 127.0.0.1:2000." emergency_shell -n "Error in $0" return 1 fi } # # END FUNCTION DEFINITIONS ############################################################################### # No main, use functions!