diff options
| author | torben | 2015-11-05 15:46:17 +0100 |
|---|---|---|
| committer | torben | 2015-11-05 15:46:17 +0100 |
| commit | 5dec51bd56b86f9f480cfff76a0779eb92d9b3c8 (patch) | |
| tree | af6e5f9008b73e221ca84336cfe8f41910d4582e /builder/dnbd3-rootfs/scripts | |
| parent | Document new simplified approaches. (diff) | |
| download | systemd-init-5dec51bd56b86f9f480cfff76a0779eb92d9b3c8.tar.gz systemd-init-5dec51bd56b86f9f480cfff76a0779eb92d9b3c8.tar.xz systemd-init-5dec51bd56b86f9f480cfff76a0779eb92d9b3c8.zip | |
Rename dracut modules folder.
Diffstat (limited to 'builder/dnbd3-rootfs/scripts')
| -rwxr-xr-x | builder/dnbd3-rootfs/scripts/prepare-disks | 211 | ||||
| -rwxr-xr-x | builder/dnbd3-rootfs/scripts/setup-qcow2 | 137 | ||||
| -rw-r--r-- | builder/dnbd3-rootfs/scripts/utils.sh | 99 |
3 files changed, 447 insertions, 0 deletions
diff --git a/builder/dnbd3-rootfs/scripts/prepare-disks b/builder/dnbd3-rootfs/scripts/prepare-disks new file mode 100755 index 00000000..2e68dd9e --- /dev/null +++ b/builder/dnbd3-rootfs/scripts/prepare-disks @@ -0,0 +1,211 @@ +#!/bin/bash +############################################################################### +# GLOBALS +# + +# flag file containing pids of running instances for concurrency checks +declare -rg OPENSLX_DISK_FLAG="/tmp/openslx.disk" +# file that will contain the name of the device used for the /tmp partition +# - label 'OPENSLX_TMP' in GPT / type '0x44' in MBR +declare -rg OPENSLX_TMP_MARKER="/tmp/openslx.disk.tmp" +# file that will contain the name of the device used for storing qcow2 +# - label 'OPENSLX_SYS' in GPT / type '0x46' in MBR +declare -rg OPENSLX_SYS_MARKER="/tmp/openslx.disk.sys" +# mount point for system partition +declare -rg OPENSLX_SYS_MOUNT="/opt/openslx/system" + +# +# END GLOBALS +############################################################################### + +############################################################################### +# FUNCTION DEFINITIONS +# +# helper to mount the OPENSLX_SYS partition to /opt/openslx/system +# Usage: mount_sys_part <path_to_sys_partition> +mount_sys_part() { + if [ ! -b "$1" ]; then + warn "($$) Refusing to mount '$1' as its not a block device!" + return 1 + fi + + local OPENSLX_SYS_DEVICE="$1" + mkdir -p ${OPENSLX_SYS_MOUNT} + if ! mount -t auto "${OPENSLX_SYS_DEVICE}" "${OPENSLX_SYS_MOUNT}"; then + warn "($$) Mounting '${OPENSLX_SYS_DEVICE}' to '${OPENSLX_SYS_MOUNT}' failed." + return 1 + fi + return 0 + +} +# +# generic helper to format the given partition with the given filesystem or +# from the prefdefined list of xfs, ext4, ... +# Usage: format_disk <dev> <fs> +# e.g. format_disk /dev/sda1 xfs +format_disk () { + local TARGET_DEVICE="$1" + local fslist="xfs ext4" + # if we have a second arguments, its the filesystem of choice + local fs + [ $# -ge 2 ] && fslist="$2" + for fs in $fslist ; do + unset found + local MKFS="$(busybox which mkfs.$fs)" + if [ -n $MKFS ]; then + found=yes + case "mkfs.$fs" in + mkfs.xfs) fopt="-fq" ;; + mkfs.ext4) fopt="-Fq" ;; + esac + info "($$) Formatting $TARGET_DEVICE as $fs" + return $(${MKFS} ${fopt} "${TARGET_DEVICE}") + fi + [ -n "$found" ] && break + done + # still here? then we didn't find a proper formatter... + warn "($$) Could not format $PART_DEV as $fs." + return 1 +} + +# +# END FUNCTION DEFINITIONS +############################################################################### + +############################################################################### +# MAIN CODE +# + +command -v warn >/dev/null || . /lib/dracut-lib.sh + +# let check the arguments +if [ "$#" -ne 2 ]; then + warn "($$) '$0' need 2 arguments: '$0 [OPENSLX_SYS|OPENSLX_TMP] <dev_path>'" + exit 1 +fi +# $1 sane? +if [ "x$1" != "xOPENSLX_SYS" ] && [ "x$1" != "xOPENSLX_TMP" ]; then + warn "($$) First arg needs to be either 'OPENSLX_SYS' or 'OPENSLX_TMP', given: $1" + exit 1 +fi +# $2 sane? +if [ ! -b "/dev/$2" ]; then + warn "($$) Second arg appears not to be a block device!" + exit 1 +fi + +# ok all seems well, set the arguments +PART_TYPE="$1" +PART_DEV="/dev/$2" + +unset OPENSLX_TMP_DEVICE +unset OPENSLX_SYS_DEVICE + +# lets check if we are already running +INSTANCES="$(grep "$PART_TYPE" "$OPENSLX_DISK_FLAG" | busybox wc -l)" +if [ "$INSTANCES" -ge 1 ]; then + # uhoh we are not alone! Need to check + # if the other instance actually did its job + warn "($$) '$0' already running for $PART_TYPE on $PART_DEV... checking state." + # here two/three cases depending on which PART_TYPE we are + # currently processing. + for timeout in 1 1 2; do + # always give the other instance time to finish + # but only check 3 times overall + sleep $timeout + case "$PART_TYPE" in + OPENSLX_TMP) + # was the tmp partition marker created with a device? + if [ ! -f "${OPENSLX_TMP_MARKER}" ]; then + info "($$) Invalid state: no marker for $PART_TYPE" + continue + fi + # it was, is it a valid block device? + OPENSLX_TMP_DEVICE="$(cat ${OPENSLX_TMP_MARKER})" + if [ -z $OPENSLX_TMP_DEVICE -o ! -b $OPENSLX_TMP_DEVICE ]; then + info "($$) Invalid state: no for device $OPENSLX_TMP_DEVICE" + continue + fi + # its detected, its a block device and as mounting is + # done later, we can not check for more at this point + info "($$) Valid state for $OPENSLX_TMP_DEVICE as $PART_TYPE" + exit 0 + ;; + OPENSLX_SYS) + # was the system partition marker created with a device? + if [ ! -f "${OPENSLX_SYS_MARKER}" ]; then + info "($$) Invalid state: no marker for $PART_TYPE" + continue + fi + # it was, is it a valid block device? + OPENSLX_SYS_DEVICE="$(cat ${OPENSLX_SYS_MARKER})" + if [ -z $OPENSLX_SYS_DEVICE -o ! -b $OPENSLX_SYS_DEVICE ]; then + info "($$) Invalid state: no for device $OPENSLX_SYS_DEVICE" + continue + fi + # its detected, its a block device, is it mounted? + if mount | grep -qE "^$OPENSLX_SYS_DEVICE\ on $OPENSLX_SYS_MOUNT"; then + info "($$) Valid state for $OPENSLX_SYS_DEVICE as $PART_TYPE" + exit 0 + fi + # if its not mounted, we want to keep on, so no exit! + ;; + *) + # weird case which should never happen + warn "($$) If you see this, then $0 was called with a bad PART_TYPE: $@" + continue + ;; + esac + done + warn "($$) Timeout reached!" + warn "($$) '$PART_TYPE' was found but not device was associated to it!" +fi + +# We write our pid to $OPENSLX_DISK_FLAG in order to make sure +# we are the only instance of this script running. +info "($$) Processing: $PART_TYPE -> $PART_DEV ($$)" +echo "$PART_TYPE.$$" >> "$OPENSLX_DISK_FLAG" + +# if we are still here, then we can go on and process the partition +if [ "$PART_TYPE" = "OPENSLX_TMP" ]; then + # always format /tmp partition + if ! format_disk "${PART_DEV}" xfs; then + # error while formatting, cleanup + warn "($$) Error formatting $PART_DEV ... removing $$" + sed -i "/^${PART_TYPE}\.$$/d" "${OPENSLX_DISK_FLAG}" + exit 1 + fi + info "($$) Using '$PART_DEV' as '$PART_TYPE'" + # mark it for later: in pre-pivot we will check this file + # and mount it as $NEWROOT/tmp + echo "$PART_DEV" > "$OPENSLX_TMP_MARKER" + # remove our pid from OPENSLX_DISK_FLAG + sed -i "/^${PART_TYPE}\.$$/d" "${OPENSLX_DISK_FLAG}" + exit 0 +fi +if [ "$PART_TYPE" = "OPENSLX_SYS" ]; then + # TODO make the formatting of the system partition configurable + if ! format_disk "${PART_DEV}" xfs; then + # error while formatting, cleanup + warn "($$) Error formatting $PART_DEV ... removing $$" + sed -i "/^${PART_TYPE}\.$$/d" "${OPENSLX_DISK_FLAG}" + exit 1 + fi + # mark it + # mount it now, since qemu-nbd needs it asap! + if mount_sys_part "$PART_DEV"; then + # mount worked, mark it as done + info "($$) Using '$PART_DEV' as '$PART_TYPE'" + echo "$PART_DEV" > "$OPENSLX_SYS_MARKER" + sed -i "/^${PART_TYPE}\.$$/d" "${OPENSLX_DISK_FLAG}" + exit 0 + else + warn "($$) 'mount_sys_part' failed in $0" + sed -i "/^${PART_TYPE}\.$$/d" "${OPENSLX_DISK_FLAG}" + exit 1 + fi +fi + +# +# END MAIN CODE +############################################################################### diff --git a/builder/dnbd3-rootfs/scripts/setup-qcow2 b/builder/dnbd3-rootfs/scripts/setup-qcow2 new file mode 100755 index 00000000..70babc17 --- /dev/null +++ b/builder/dnbd3-rootfs/scripts/setup-qcow2 @@ -0,0 +1,137 @@ +#!/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 /usr/bin/systemd-preserve-process-marker \ + nbd-client --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! diff --git a/builder/dnbd3-rootfs/scripts/utils.sh b/builder/dnbd3-rootfs/scripts/utils.sh new file mode 100644 index 00000000..3c72dbca --- /dev/null +++ b/builder/dnbd3-rootfs/scripts/utils.sh @@ -0,0 +1,99 @@ +UTILS_KERNEL_MODULE_DIRECTORY="builder/dnbd3-qcow2-rootfs/kernel_modules/" +UTILS_STANDARD_OUTPUT=/dev/null +UTILS_ERROR_OUTPUT=/dev/null + +function utils_log() { + # Handles logging messages. Returns non zero and exit on log level + # error to support chaining the message into toolchain. + # + # Examples: + # + # >>> build_initramfs_log + # info: test + # >>> build_initramfs_log debug message + # debug: message + # >>> build_initramfs_log info message '\n' + # + # info: message + local loggingType='info' && \ + local message="$1" && \ + if [ "$2" ]; then + loggingType="$1" + message="$2" + fi + if [ "$_VERBOSE" == 'yes' ] || [ "$loggingType" == 'error' ] || \ + [ "$loggingType" == 'critical' ]; then + if [ "$3" ]; then + echo -e -n "$3" + fi + echo -e "${loggingType}: $message" + fi + if [ "$loggingType" == 'error' ]; then + exit 1 + fi + return 0 +} +function compile_nbd() { + # Downloads and compiles nbd. + # + # Examples: + # + # >>> build_initramfs_compile_nbd + # ... + # Provides the following file: + # ${_KERNEL_MODULE_DIRECTORY}/nbd/nbd.ko + pushd "${_KERNEL_MODULE_DIRECTORY}/nbd" \ + 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" && \ + build_initramfs_log 'Compile the nbd kernel module.' && \ + make 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" && \ + popd 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" + return $? + # TODO make clean +} +function compile_dnbd3() { + # Downloads and compiles dnbd3. + # + # Examples: + # + # >>> build_initramfs_compile_dnbd3 + # ... + # Provides the following file: + # ${_KERNEL_MODULE_DIRECTORY}/dnbd3/build/dnbd3.ko + rm --recursive --force ${_KERNEL_MODULE_DIRECTORY}/dnbd3 \ + 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" && \ + pushd $_KERNEL_MODULE_DIRECTORY \ + 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" && \ + git clone git://git.openslx.org/dnbd3.git \ + 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" && \ + cd dnbd3 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" && \ + ./build.sh 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" && \ + popd 1>"$_STANDARD_OUTPUT" 2>"$_ERROR_OUTPUT" + return $? + # TODO rm -rf build +} +function compile_systemd_preserve_process_marker() { + # Compiles simple c program. + pushd && \ + make && \ + popd + return $? +} +function utils_dependency_check() { + # This function check if all given dependencies are present. + # + # Examples: + # + # >>> build_initramfs_perform_dependency_check "mkdir pacstrap mktemp" + # ... + local dependenciesToCheck="$1" && \ + local result=0 && \ + local dependency && \ + for dependency in ${dependenciesToCheck[*]}; do + if ! hash "$dependency" 1>"$_STANDARD_OUTPUT" 2>/dev/null; then + build_initramfs_log 'critical' \ + "Needed dependency \"$dependency\" isn't available." && \ + result=1 + fi + done + return $result +} |
