# ------------------------------------------------------------------------------ # # Functions for OpenSLX-NG # # ------------------------------------------------------------------------------ # # check if we have our environement variables to check # if we actually got sourced by the main script if [ -z "${SELF_PID}" -o -z "${ROOT_DIR}" ]; then # not using perror, since we probably don't have it. echo "Neither SELF_PID nor ROOT_DIR is set. Was this included by OpenSLX-NG?" exit 1 fi # Helper to generate a stage4 export for a remote machine per rsync. clone_stage4() { [ $# -ne 2 ] && perror "$0 " local REMOTE_HOST="$1" local TARGET_DIR="$2" local BUILD_DIR="${ROOT_DIR}/builds/$REMOTE_HOST" mkdir -p "$TARGET_DIR" mkdir -p "$BUILD_DIR" local EXCLUDE="$BUILD_DIR/exclude-stage4" local INCLUDE="$BUILD_DIR/include-stage4" pinfo "Building rsync exclude-file for building stage 4...." echo "## Exclude file for stage4 of $REMOTE_HOST" > "$EXCLUDE" echo "## Include file for stage4 of $REMOTE_HOST" > "$INCLUDE" for FILE in $(find "$ROOT_DIR"/blacklists/*/ -type f); do echo "## From $FILE" >> "$EXCLUDE" echo "## From $FILE" >> "$INCLUDE" grep '^-' "$FILE" >> "$EXCLUDE" grep '^+' "$FILE" >> "$INCLUDE" done pinfo "Done." # prepare rsync's options local RSYNC_SOURCE="root@$REMOTE_HOST:/" local RSYNC_OPTS="-e ssh -c arcfour -oStrictHostKeyChecking=no" # run rsync with the exclude/include lists created earlier pinfo "Cloning via rsync..." cat "$INCLUDE" "$EXCLUDE" | \ rsync --verbose \ --archive \ --delete \ --delete-excluded \ --numeric-ids \ --exclude-from=- \ "${RSYNC_OPTS}" \ "${RSYNC_SOURCE}" \ "${TARGET_DIR}" \ || perror "rsync from '${RSYNC_SOURCE}' to '${TARGET_DIR}' failed." pinfo "Cloning '${REMOTE_HOST}' to '${TARGET_DIR}' succeeded." return 0 } # helper to build a qcow2 container from a stage4 sync directory. # required tools: qemu-img, qemu-nbd, nbd, mkfs.ext4 export_qcow2() { # enough args? [ $# -ne 2 ] && perror "Usage: $0 " # $1 valid? [ ! -d $1 ] && perror "First argument not a directory!" # $2 should not be a dir or strange things will happen... [ -d $2 ] && perror "Target file can not be a directory!" # $1 is dir, strip trailing slash if there is one local STAGE4_DIR="${1%/}" local TARGET_FILE="$2" if [ -e $TARGET_FILE ]; then pinfo "Removing old target: $TARGET_FILE" rm $target || perror "Could not remove '$TARGET_FILE'" fi # so far so good pinfo "Creating empty qcow2-container ..." qemu-img create -f qcow2 $TARGET_FILE 10G \ || perror "qemu-img create failed with: $?" pinfo "Done." # find usable nbd device pinfo "Looking for usable nbd device..." local NBD_ID="$(find_free_nbd)" local NBD_DEV="/dev/nbd${NBD_ID}" [ -b "$NBD_DEV" ] || perror "'$NBD_DEV' is not a block device!" pinfo "Exporting '${TARGET_FILE}' using '${NBD_DEV}'..." qemu-nbd -c ${NBD_DEV} ${TARGET_FILE} || perror "qemu-nbd failed with: $?" pinfo "Done." pinfo "Creating ext4 filesystem on '${TARGET_FILE}'..." mkfs.ext4 "${NBD_DEV}" || perror "mkfs failed with: $?" pinfo "Done." # mount NBD_DEV mkdir ${BUILD_DIR}/mnt pinfo "Mounting '${NBD_DEV}' to '${BUILD_DIR}/mnt'..." mount ${NBD_DEV} ${BUILD_DIR}/mnt || perror "Mount failed with: $?" pinfo "Done." # copy files from the stage4 directory to the mounted qcow2-container pinfo "Copying '${STAGE4_DIR}' to '${BUILD_DIR}/mnt'..." cp -ra "${STAGE4_DIR}"/* "${BUILD_DIR}"/mnt || perror "Copying failed with: $?" pinfo "Done." pinfo "Cleaning up..." umount "${BUILD_DIR}/mnt" || perror "Could not unmount '${BUILD_DIR}/mnt'." qemu-nbd -d /dev/nbd${nbd_id} || perror "Could not disconnect '${NBD_DEV}'." pinfo "Exporting '${STAGE4_DIR}' to '${TARGET_FILE}' completed." } # helper to find an unused nbd device find_free_nbd() { local nbd_size=0 for nbd_id in {0..15}; do [ -b "/dev/nbd${nbd_id}" ] || continue [ ! -e "/sys/block/nbd${nbd_id}/size" ] || continue nbd_size=$(cat /sys/block/nbd${nbd_id}/size) [ $nbd_size -eq 0 ] && break done return ${nbd_id} } # helper to validate an ip valid_ip() { local ip=$1 local stat=1 if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then OIFS=$IFS IFS='.' ip=($ip) IFS=$OIFS [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \ && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]] stat=$? fi return $stat }