diff options
author | Jonathan Bauer | 2016-04-18 15:41:44 +0200 |
---|---|---|
committer | Jonathan Bauer | 2016-04-18 15:41:44 +0200 |
commit | a7abc3d120af436d3667f0cb819b24d4704fa831 (patch) | |
tree | c30263e0d2c4c91bfe35f40881d251a5675209bc /packager | |
parent | update rebash (diff) | |
download | systemd-init-a7abc3d120af436d3667f0cb819b24d4704fa831.tar.gz systemd-init-a7abc3d120af436d3667f0cb819b24d4704fa831.tar.xz systemd-init-a7abc3d120af436d3667f0cb819b24d4704fa831.zip |
reworked cleanup & stuff
Diffstat (limited to 'packager')
-rwxr-xr-x | packager/openslx | 3 | ||||
-rw-r--r-- | packager/openslx.config | 4 | ||||
-rw-r--r-- | packager/openslx.functions | 272 |
3 files changed, 133 insertions, 146 deletions
diff --git a/packager/openslx b/packager/openslx index 69102564..6845f9ba 100755 --- a/packager/openslx +++ b/packager/openslx @@ -32,7 +32,7 @@ else fi # setup trap -trap cleanexit SIGINT SIGTERM +trap do_cleanup SIGINT SIGTERM SIGUSR1 EXIT # read params read_params $@ @@ -40,3 +40,4 @@ read_params $@ # react to given action process_action +exit 0 diff --git a/packager/openslx.config b/packager/openslx.config index a02a608b..9c94226d 100644 --- a/packager/openslx.config +++ b/packager/openslx.config @@ -2,7 +2,7 @@ DEFAULT_RSYNC_OPTS="-e ssh -c arcfour -oStrictHostKeyChecking=no" # default size for the qcow2-container (the one containing diffs) -DEFAULT_QCOW_SIZE="25G" +DEFAULT_CONTAINER_SIZE="25G" # default filesystem type for the qcow2-container -DEFAULT_QCOW_FS="ext4" +DEFAULT_CONTAINER_FILESYSTEM="xfs" diff --git a/packager/openslx.functions b/packager/openslx.functions index e38f88c5..78208cd4 100644 --- a/packager/openslx.functions +++ b/packager/openslx.functions @@ -180,6 +180,7 @@ read_params() { declare -rg CONTAINER_MNT="$(mktemp -d)" [ -z "${CONTAINER_MNT}" ] && \ perror "Could not create temporary directory for mounting the container." + add_cleanup rmdir "${CONTAINER_MNT}" # RSYNC_TARGET depends on the action at this point if [ "x$ACTION" == "xPACKAGE" ]; then # use default path when packaging @@ -214,6 +215,32 @@ process_action() { fi return 0 } + +# wrapper to package a cloned stage4 as a qcow2 container +# - creates empty container at CONTAINER_PATH +# - mounts it to RSYNC_TARGET +# - copy RSYNC_TARGET +pack_clone() { + create_container + mount_container + copy_to_container +} +# wrapper to update an existing container +# - mounts it to RSYNC_TARGET +# - clone host there +update_container() { + mount_container + clone_host +} +# wrapper to export a host directly to a container +# - create en empty qcow2 container at CONTAINER_PATH +# - mount it to RSYNC_TARGET +# - clone host there +export_host() { + create_container + mount_container + clone_host +} # ------------------------------------------------------------------------------ # # Stage4 related functions @@ -228,10 +255,10 @@ process_action() { clone_host() { # 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." + # does it have the '.stage4' flag? skip this check when exporting directly + [ "x$ACTION" != "xEXPORT" ] && [ ! -e "${RSYNC_TARGET}/.stage4" ] && \ + perror "'${RSYNC_TARGET}' exists, but no '.stage4' flag found. Refusing to rsync there." + #touch $RSYNC_TARGET/.stage4 && exit 0 else # not a directory, create it and set the .stage4 flag mkdir -p "${RSYNC_TARGET}" || perror "Could not create '${RSYNC_TARGET}'." @@ -251,14 +278,12 @@ clone_host() { done # prepare rsync's options - if [ -z "$DEFAULT_RSYNC_OPTS" ]; then - local RSYNC_OPTS="-e ssh -c arcfour -oStrictHostKeyChecking=no" - else - local RSYNC_OPTS="$DEFAULT_RSYNC_OPTS" - fi + local RSYNC_OPTS="$DEFAULT_RSYNC_OPTS" + [ -z "$RSYNC_OPTS" ] && RSYNC_OPTS="-e ssh -c arcfour -oStrictHostKeyChecking=no" local RSYNC_SOURCE="root@$REMOTE_HOST:/" - _STATE='SYNCING' + # if something goes wrong during rsync, we need to recreate the .stage4 flag + add_cleanup touch ${RSYNC_TARGET}/.stage4 # run rsync with the exclude/include lists created earlier cat "$INCLUDE" "$EXCLUDE" | \ rsync --verbose \ @@ -272,53 +297,52 @@ clone_host() { --exclude-from=- \ "${RSYNC_OPTS}" \ "${RSYNC_SOURCE}" \ - "${RSYNC_TARGET}" \ - || perror "rsync from '${RSYNC_SOURCE}' to '${RSYNC_TARGET}' failed." - ## TODO real exit code handling - pinfo "Cloning '${REMOTE_HOST}' to '${RSYNC_TARGET}' succeeded." + "${RSYNC_TARGET}" + + local -i rsync_ret=$? + if [ "x$rsync_ret" != "x0" ]; then + perror "rsync from '${RSYNC_SOURCE}' to '${RSYNC_TARGET}' failed." + fi touch "${RSYNC_TARGET}/.stage4" - _STATE='SYNCED' - return 0 + # make sure everything gets flushed + sync + pinfo "Cloning '${REMOTE_HOST}' to '${RSYNC_TARGET}' succeeded." } # Helper to create the empty container at CONTAINER_PATH create_container() { # CONTAINER_PATH valid? - [ -d "$CONTAINER_PATH" ] && perror "Path to container can not be a directory!" - if [ -f "$CONTAINER_PATH" ]; then + [ -d "${CONTAINER_PATH}" ] && perror "Path to container can not be a directory!" + if [ -f "${CONTAINER_PATH}" ]; then if [ $FORCE -eq 0 ]; then perror "Container file already exists. Use '--force' to overwrite it." else # force removal - rm -f "$CONTAINER_PATH" || perror "Could not remove '$CONTAINER_PATH'" - pinfo "Removed old '$CONTAINER_PATH'." + rm -f "${CONTAINER_PATH}" || perror "Could not remove '${CONTAINER_PATH}'" + pinfo "Removed old '${CONTAINER_PATH}'." fi fi # which size for the qcow2 container? - if [ -z "$DEFAULT_QCOW_SIZE" ]; then - local QCOW_SIZE="25G" - else - local QCOW_SIZE="$DEFAULT_QCOW_SIZE" - fi + local CONTAINER_SIZE="${DEFAULT_CONTAINER_SIZE}" + [ -z "${CONTAINER_SIZE}" ] && CONTAINER_SIZE="25G" + # so far so good pinfo "Creating qcow2-container '${CONTAINER_PATH}'" - qemu-img create -f qcow2 "${CONTAINER_PATH}" "${QCOW_SIZE}" || \ + qemu-img create -f qcow2 "${CONTAINER_PATH}" "${CONTAINER_SIZE}" || \ perror "qemu-img create failed with: $?" # now expose it as a loop device - expose_container - _STATE='QCOW_EXPOSED' + expose_container # filesystem for the qcow2 container? - if [ -z "$DEFAULT_QCOW_FS" ]; then - local QCOW_FS="ext4" - else - # check if we have mkfs helper - which "mkfs.$DEFAULT_QCOW_FS" &>/dev/null || \ - perror "Could not find 'mkfs.$DEFAULT_QCOW_FS'. Install it and retry." - local QCOW_FS="$DEFAULT_QCOW_FS" - fi - pinfo "Creating '${QCOW_FS}' filesystem on '${CONTAINER_PATH}'..." - mkfs."${QCOW_FS}" "${LOOPED_NBD_DEV}" || perror "mkfs failed with: $?" + local CONTAINER_FILESYSTEM="${DEFAULT_CONTAINER_FILESYSTEM}" + [ -z "${CONTAINER_FILESYSTEM}" ] && CONTAINER_FILESYSTEM="xfs" + # check if we have that mkfs helper + which "mkfs.${CONTAINER_FILESYSTEM}" || \ + perror "Could not find 'mkfs.${CONTAINER_FILESYSTEM}'. Install it and retry." + + pinfo "Creating '${CONTAINER_FILESYSTEM}' filesystem on '${CONTAINER_PATH}'..." + mkfs."${CONTAINER_FILESYSTEM}" "${LOOPED_NBD_DEV}" || perror "mkfs failed with: $?" + return 0 } # Helper exposing the container as a loop device @@ -334,11 +358,13 @@ expose_container() { qemu-nbd -c "${NBD_DEV}" "${CONTAINER_PATH}" || \ perror "qemu-nbd failed with: $?" - _STATE='QCOW_EXPOSED_NBD' + add_cleanup disconnect_nbd # expose as a loop device declare -rg LOOPED_NBD_DEV="$(losetup --find)" losetup "${LOOPED_NBD_DEV}" "${NBD_DEV}" || \ perror "Loop device setup for '${NBD_DEV}' failed with: $?" + add_cleanup disconnect_loop + return 0 } # Helper to mount CONTAINER_PATH to CONTAINER_MNT through expose_container @@ -351,11 +377,13 @@ mount_container() { # lets be safe... [ -z "${LOOPED_NBD_DEV}" ] && \ perror "Internal error - LOOPED_NBD_DEV not set but should be! Check expose_container()" - + # now we got everything, mount it pinfo "Mounting '${LOOPED_NBD_DEV}' to '${CONTAINER_MNT}'..." - mount "${LOOPED_NBD_DEV}" "${CONTAINER_MNT}" || perror "Mount failed with: $?" - _STATE='QCOW_MOUNTED' + mount "${LOOPED_NBD_DEV}" "${CONTAINER_MNT}" \ + || perror "Mount failed with: $?" + add_cleanup umount_container + return 0 } # helper to copy the content of RSYNC_TARGET to CONTAINER_MNT @@ -374,110 +402,18 @@ copy_to_container() { fi # copy files from the stage4 directory to the mounted qcow2-container pinfo "Copying '${RSYNC_TARGET}' to '${CONTAINER_MNT}'..." - rsync -avAHX "${RSYNC_TARGET}"/ "${CONTAINER_MNT}"/ || perror "Rsync failed with: $?" -} - -# wrapper to package a cloned stage4 as a qcow2 container -# - creates empty container at CONTAINER_PATH -# - mounts it to RSYNC_TARGET -# - copy RSYNC_TARGET -pack_clone() { - create_container - mount_container - copy_to_container - umount_container -} -# wrapper to update an existing container -# - mounts it to RSYNC_TARGET -# - clone host there -update_container() { - mount_container - clone_host - umount_container -} -# wrapper to export a host directly to a container -# - create en empty qcow2 container at CONTAINER_PATH -# - mount it to RSYNC_TARGET -# - clone host there -export_host() { - create_container - mount_container - clone_host - umount_container -} - -# 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 ..." - - case "${_STATE}" in - 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 - break; - ;; - QCOW_MOUNTED) - # container mounted - [ -z "${CONTAINER_PATH}" ] && \ - perror "CONTAINER_PATH not set - should not be!" - [ -z "${CONTAINER_MNT}" ] && \ - perror "CONTAINER_MNT not set - should not be!" - umount_container || \ - perror "Could not umount '${CONTAINER_MNT}'." - ;; - QCOW_MOUNTED|QCOW_EXPOSED) - disconnect_container - break - ;; - # internal expose_container state - QCOW_EXPOSED_NBD) - disconnect_nbd - break - ;; - *) - [ -n "${_STATE}" ] && pwarning "Unknown state: ${_STATE}" - ;; - esac - # still here? then we ran into some error - exit 1 -} -# Helper to umount + disconnect the container from all the devices -umount_container() { - [ -z "${CONTAINER_MNT}" ] && \ - perror "CONTAINER_MNT not set - is it really mounted?" - umount "${CONTAINER_MNT}" || \ - perror "Failed to umount '${CONTAINER_MNT}'." - rmdir "${CONTAINER_MNT}" || \ - pwarning "Could not remove '${CONTAINER_MNT}'." + rsync -avAHX "${RSYNC_TARGET}"/ "${CONTAINER_MNT}"/ \ + || perror "Rsync failed with: $?" + #make sure everything is flushed + sync && return 0 } -# Wrapper to disconnect the container from all the devices -disconnect_container() { - disconnect_loop - disconnect_nbd -} -# Helper to disconnect from loop device -disconnect_loop() { - [ -z "${LOOPED_NBD_DEV}" ] && \ - perror "Container not connected to a loop device?" - losetup -d "${LOOPED_NBD_DEV}" ||\ - perror "Could not disconnect loop device '${LOOPED_NBD_DEV}'." -} -# Helper to disconnect from nbd device -disconnect_nbd() { - [ -z "${NBD_DEV}" ] && \ - perror "Container does not seem to be connected to a NBD device?" - qemu-nbd -d "${NBD_DEV}" || \ - perror "Could not disconnect '${CONTAINER_PATH}' from '${NBD_DEV}'." -} +############################################################################### +# +# +# +############################################################################### # helper to find an unused nbd device # Usage: # find_free_nbd @@ -550,4 +486,54 @@ user_confirm() { [ "x${_input}" == "x" -o "x${_input}" == "xy" ] && return 0 || return 1 } +############################################################################### +# +# CLEANUP FUNCTIONS +# +############################################################################### +# indexed array for cleanup commands +declare -ag cleanup_commands + +# function to add a cleanup command to be executed when the program exits +add_cleanup() { + # get current command count + local -i count="${#cleanup_commands[*]}" + cleanup_commands[$count]="$*" +} + +# function trapped to EXIT, SIGINT, SIGTERM +# do the cleanup in FILO style +do_cleanup() { + trap '' SIGINT SIGTERM EXIT # from now on, ignore INT and TERM + for i in $(seq $(( ${#cleanup_commands[*]} - 1 )) -1 0); do + pinfo "Running: ${cleanup_commands[$i]}" + eval ${cleanup_commands[$i]} + done +} + +# Helper to umount + disconnect the container from all the devices +umount_container() { + [ -z "${CONTAINER_MNT}" ] && \ + perror "CONTAINER_MNT not set - is it really mounted?" + # sync? + umount -l "${CONTAINER_MNT}" || \ + perror "Failed to umount '${CONTAINER_MNT}'." +# rmdir "${CONTAINER_MNT}" || \ +# pwarning "Could not remove '${CONTAINER_MNT}'." +} + +# Helper to disconnect from loop device +disconnect_loop() { + [ -z "${LOOPED_NBD_DEV}" ] && \ + perror "Container not connected to a loop device?" + losetup -d "${LOOPED_NBD_DEV}" ||\ + perror "Could not disconnect loop device '${LOOPED_NBD_DEV}'." +} +# Helper to disconnect from nbd device +disconnect_nbd() { + [ -z "${NBD_DEV}" ] && \ + perror "Container does not seem to be connected to a NBD device?" + qemu-nbd -d "${NBD_DEV}" || \ + perror "Could not disconnect '${CONTAINER_PATH}' from '${NBD_DEV}'." +} |