From b760f7e9d8f601cf13d197fdd75e0a6546f49734 Mon Sep 17 00:00:00 2001 From: Jonathan Bauer Date: Wed, 3 Jun 2015 12:42:18 +0200 Subject: trapped SIGINT/SIGTERM and implemented cleanup function only rsync if we have a '.stage4' flag in the target sync dir --- packager/openslx | 17 ++++-- packager/openslx.functions | 142 ++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 139 insertions(+), 20 deletions(-) (limited to 'packager') diff --git a/packager/openslx b/packager/openslx index a71a1db6..9613196b 100755 --- a/packager/openslx +++ b/packager/openslx @@ -10,21 +10,22 @@ # # ------------------------------------------------------------------------------ # -# OpenSLX-NG Main Code +# Main Code # # ------------------------------------------------------------------------------ declare -rg ARG0="$0" -declare -rg SELF="$(readlink -f "$ARG0")" +declare -rg SELF="$(readlink -f "${ARG0}")" declare -rg ROOT_DIR="$(dirname "${SELF}")" declare -rg SELF_PID="$$" # let's keep it simple for now, just source our config/functions file -. "${ROOT_DIR}/$ARG0".functions || perror "Could not source functions." -. "${ROOT_DIR}/$ARG0".config || perror "Could not source config." +. "${ROOT_DIR}/${ARG0}".functions || perror "Could not source functions." +. "${ROOT_DIR}/${ARG0}".config || perror "Could not source config." # root check if [ "$(id -u)" -ne 0 ]; then + banner perror "ERROR: You need to be root to use this toolkit." else banner @@ -32,11 +33,17 @@ fi # do we even have tools? for TOOL in qemu-img qemu-nbd mkfs.ext4; do - which $TOOL &>/dev/null || perror "Could not find '$TOOL'." + which "${TOOL}" &>/dev/null || \ + perror "Could not find '${TOOL}'. Please install it." done +# setup trap +trap cleanexit SIGINT SIGTERM +# read params read_params $@ + +# react to given action if [ "x$ACTION" == "xCLONE" ]; then clone_stage4 || perror "Cloning stage4 failed with: $?" elif [ "x$ACTION" == "xPACKAGE" ]; then diff --git a/packager/openslx.functions b/packager/openslx.functions index 867e252d..8ecc1fdc 100644 --- a/packager/openslx.functions +++ b/packager/openslx.functions @@ -143,6 +143,88 @@ read_params() { done } +# helper function trapped on SIGTERM/SIGINT +# Usage: do not use as is +cleanexit() { + trap '' SIGINT SIGTERM # from now on, ignore INT and TERM + pwarning "SIGINT/SIGTERM triggered - cleaning up ..." + [ -z "${_STATE}" ] && perror "'_STATE' not set, this is bad." + + case "${_STATE}" in + SYNC_DONE|QCOW_DONE) + # we are happy + pwarning "SIGINT/SIGTERM received, but everything seems fine. Check it!" + exit 0 + ;; + BLACKLISTING) + # creation of blacklists failed + # TODO do what? + ;; + SYNCING) + # error during rsync, create the .stage4 file again + [ -z "${RSYNC_TARGET}" ] && \ + perror "RSYNC_TARGET not set, this should not happen." + if [ ! -e "${RSYNC_TARGET}/.stage4" ]; then + pwarning "'.stage4' flag was lost during rsync, restoring it." + touch "${RSYNC_TARGET}/.stage4" + fi + ;; + QCOW_CREATING) + # qemu-img failed. Just remove the container if its there + if [ -n "${CONTAINER_PATH}" -a -e "${CONTAINER_PATH}" ]; then + rm -f "${CONTAINER_PATH}" || \ + pwarning "Could not remove '${CONTAINER_PATH}'." + fi + ;; + QCOW_NBD_CONNECTING) + # qemu-nbd failed + if [ -n "${NBD_DEV}" ]; then + qemu-nbd -d "${NBD_DEV}" && \ + pwarning "Could not disconnect '${NBD_DEV}'." + fi + ;; + QCOW_FSING) + # mkfs failed, disconnect and remove container + if [ -n "${NBD_DEV}" ]; then + qemu-nbd -d "${NBD_DEV}" && \ + pwarning "Could not disconnect '${NBD_DEV}'." + fi + if [ -n "${CONTAINER_PATH}" -a -e "${CONTAINER_PATH}" ]; then + rm -f "${CONTAINER_PATH}" || \ + pwarning "Could not remove '${CONTAINER_PATH}'." + fi + ;; + QCOW_MOUNTING) + # mounting failed: + # umount, disconnect and remove container and mount point + if [ -n "${NBD_MNT}" ]; then + umount "${NBD_MNT}" || pwarning "Could not umount '${NBD_MNT}'." + rmdir "${NBD_MNT}" || pwarning "Could not rmdir '${NBD_MNT}'." + fi + if [ -n "${NBD_DEV}" ]; then + qemu-nbd -d "${NBD_DEV}" && \ + perror "Could not disconnect '${NBD_DEV}'." + fi + if [ -n "${CONTAINER_PATH}" -a -e "${CONTAINER_PATH}" ]; then + rm -f "${CONTAINER_PATH}" || \ + perror "Could not remove '${CONTAINER_PATH}'." + fi + ;; + QCOW_COPYING) + # rare case, should not happen + ;; + QCOW_CLEANING) + # should also not happen + ;; + *) + pwarning "Unknown state: ${_STATE}" + esac + # still here? then we ran into some error + exit 1 +} + + + # helper to validate an ip # Usage: # valid_ip @@ -163,6 +245,20 @@ valid_ip() { return $stat } +# helper to check whether a given host is valid +# Usage: +# check_host +# Returns 0 if valid, 1 otherwise +check_host() { + local HOST="$1" + [ -z "$HOST" ] && return 1 + # check if its a valid IP or a valid hostname + valid_ip "$HOST" && return 0 + host -W 2 "$HOST" && return 0 + # still here? then fail + return 1 +} + # helper to check if a dir is empty or not # Usage: # dir_empty @@ -186,19 +282,6 @@ user_confirm() { [ "x${_input}" == "x" -o "x${_input}" == "xy" ] && return 0 || return 1 } -# helper to check whether a given host is valid -# Usage: -# check_host -# Returns 0 if valid, 1 otherwise -check_host() { - local HOST="$1" - [ -z "$HOST" ] && return 1 - # check if its a valid IP or a valid hostname - valid_ip "$HOST" && return 0 - host -W 2 "$HOST" && return 0 - # still here? then fail - return 1 -} # ------------------------------------------------------------------------------ # # Stage4 related functions @@ -225,12 +308,25 @@ clone_stage4() { # RSYNC_TARGET set? if [ -z "$RSYNC_TARGET" ]; then - pwarning "RSYNC_TARGET not set. Assuming local mode" + pwarning "RSYNC_TARGET not set. Assuming local mode." pinfo "Using '${BUILD_DIR}/stage4'" declare -rg RSYNC_TARGET="${BUILD_DIR}/stage4" fi - mkdir -p "${RSYNC_TARGET}" + # check if RSYNC_TARGET is valid + if [ -d "${RSYNC_TARGET}" ]; then + # does it have the '.stage4' flag? + [ ! -e "${RSYNC_TARGET}/.stage4" ] && \ + perror "'${RSYNC_TARGET}' exists, but no '.stage4' flag found." \ + "Refusing to rsync there." + else + # not a directory, create it and set the .stage4 flag + mkdir -p "${RSYNC_TARGET}" + touch "${RSYNC_TARGET}/.stage4" + fi + + # mark state + _STATE='BLACKLISTING' local EXCLUDE="$BUILD_DIR/exclude-stage4" local INCLUDE="$BUILD_DIR/include-stage4" @@ -253,6 +349,7 @@ clone_stage4() { fi local RSYNC_SOURCE="root@$REMOTE_HOST:/" + _STATE='SYNCING' # run rsync with the exclude/include lists created earlier cat "$INCLUDE" "$EXCLUDE" | \ rsync --verbose \ @@ -267,6 +364,8 @@ clone_stage4() { || perror "rsync from '${RSYNC_SOURCE}' to '${RSYNC_TARGET}' failed." ## TODO real exit code handling pinfo "Cloning '${REMOTE_HOST}' to '${RSYNC_TARGET}' succeeded." + _STATE='SYNC_DONE' + touch "${RSYNC_TARGET}/.stage4" return 0 } # helper to build a qcow2 container from a stage4 sync directory @@ -317,6 +416,11 @@ pack_qcow2() { [ ! -d "$RSYNC_TARGET" ] && perror "'$RSYNC_TARGET' not a directory!" is_dir_empty "$RSYNC_TARGET" && \ perror "'$RSYNC_TARGET' appears to be empty. Did you clone?" + # the ultimative check + if [ ! -e "${RSYNC_TARGET}/.stage4" ]; then + perror "No '.stage4' flag found in '${RSYNC_TARGET}'." \ + "Was this cloned properly?" + fi # which size for the qcow2 container? if [ -z "$DEFAULT_QCOW_SIZE" ]; then @@ -326,6 +430,7 @@ pack_qcow2() { fi # so far so good pinfo "Creating empty qcow2-container ..." + _STATE='QCOW_CREATING' qemu-img create -f qcow2 "${CONTAINER_PATH}" "${QCOW_SIZE}" \ || perror "qemu-img create failed with: $?" pinfo "Done." @@ -336,6 +441,7 @@ pack_qcow2() { [ -z "${NBD_DEV}" ] && perror "Could not find usable NBD device." [ -b "${NBD_DEV}" ] || perror "'${NBD_DEV}' is not a block device!" pinfo "Exporting '${CONTAINER_PATH}' using '${NBD_DEV}'..." + _STATE='QCOW_NBD_CONNECTING' qemu-nbd -c "${NBD_DEV}" "${CONTAINER_PATH}" || \ perror "qemu-nbd failed with: $?" pinfo "Done." @@ -350,9 +456,11 @@ pack_qcow2() { local QCOW_FS="$DEFAULT_QCOW_FS" fi pinfo "Creating '${QCOW_FS}' filesystem on '${CONTAINER_PATH}'..." + _STATE='QCOW_FSING' mkfs."${QCOW_FS}" "${NBD_DEV}" || perror "mkfs failed with: $?" pinfo "Done." + # prepare NBD mount directory and check state to be safe local NBD_MNT="$(mktemp -d)" [ ! -d "${NBD_MNT}" ] && \ @@ -361,18 +469,22 @@ pack_qcow2() { perror "'${NBD_MNT}' not empty. Refusing to mount ${NBD_DEV} to it." pinfo "Mounting '${NBD_DEV}' to '${NBD_MNT}'..." + _STATE='QCOW_MOUNTING' mount "${NBD_DEV}" "${NBD_MNT}" || perror "Mount failed with: $?" pinfo "Done." # copy files from the stage4 directory to the mounted qcow2-container pinfo "Copying '${RSYNC_TARGET}' to '${NBD_MNT}'..." + _STATE='QCOW_COPYING' cp -ra "${RSYNC_TARGET}"/* "${NBD_MNT}" || perror "Copying failed with: $?" pinfo "Done." pinfo "Cleaning up..." + _STATE='QCOW_CLEANING' umount "${NBD_MNT}" || pwarning "Could not unmount '${NBD_MNT}'." rmdir "${NBD_MNT}" || pwarning "Could not remove '${NBD_MNT}'." qemu-nbd -d "${NBD_DEV}" || pwarning "Could not disconnect '${NBD_DEV}'." + _STATE='QCOW_DONE' pinfo "Exporting '${RSYNC_TARGET}' to '${CONTAINER_PATH}' completed." } -- cgit v1.2.3-55-g7522