#! /bin/bash
# vim: shiftwidth=4 tabstop=4 expandtab

if in_array "${COMMAND_ARGS[0]}" --help -h help; then
    echo "$COMMAND [source VM name] [destination VM name]"
    if [ "${COMMAND_ARGS[1]}" == "details" ]; then
        echo "  Clone a VM specified by name"
    fi
    return
fi

SRC_VM=${COMMAND_ARGS[0]}
[[ -z "$SRC_VM" ]] && usage "Source VM name is missing"
DST_VM=${COMMAND_ARGS[1]}
[[ -z "$DST_VM" ]] && usage "Destination VM name is missing"

HYP=$( locate "$SRC_VM" )
check_hyp "$HYP" || usage "Unknown VM $SRC_VM"

TARGET_HYP=$( locate "$DST_VM" )
[[ -n "$TARGET_HYP" ]] && fatal_error "VM $DST_VM already exists on $TARGET_HYP!"

echo "Cloning $SRC_VM (on $HYP) as $DST_VM"

echo "List $SRC_VM volumes:"
VOLUMES=$(list_volumes "$SRC_VM" "$HYP")
[[ -z "$VOLUMES" ]] && fatal_error "Failed to list $SRC_VM volumes"
echo -e "$VOLUMES"|sed 's/^/ - /'


echo "Check RBD volumes layering feature..."
for image in $VOLUMES; do
    echo -n "  - $image: "
    features=$(rbd info "$image"|grep features)
    debug "$image features: $features"
    if [[ $(echo "$features"|grep -c layering) -eq 0 ]]; then
        echo "ERROR"
        echo "    Layering feature not available, this image must be dump and restore in new" \
            "format (VM off)."
        confirm "    Do you want to process now" || exit 1
        if is_running "$SRC_VM" "$HYP"; then
            confirm "    VM $SRC_VM is up. Please confirm its shutdown" || exit 1
            stop_and_wait_stopped "$SRC_VM" "$HYP"
        fi
        old_image="$image-old"
        echo -n "    Rename $image as $old_image... "
        run_external rbd mv "$image" "$old_image" || \
            fatal_error "Failed to rename $image as $old_image!"
        echo "done."

        echo "    Export/import $image..."
        if [[ -n "$GENERATE_SCRIPT" ]]; then
            {
                echo "rbd export '$old_image' - | rbd import --image-format 2 - '${image}'"
                echo "echo 'After confirming the VM is working, you could remove old image."
                echo "Press [enter] to continue...'"
                echo "read"
                echo "rbd rm $image-old"
            } >> "$GENERATE_SCRIPT"
        else
            run_external rbd export "$old_image" - | rbd import --image-format 2 - "${image}" || \
                fatal_error "Failed to reimport $old_image as $image!"
            echo "    done."

            echo "    => After confirming the VM is working, please remove old image:"
            echo "      rbd rm $image-old"
        fi
    else
        echo "OK"
    fi
done

echo "Create snapshot"
SNAP_PREFIX="$(date +%Y%m%d-%H%M)"
SNAP_SUFFIX="for-clonning-as-$DST_VM"
SNAP_NAME="${SNAP_PREFIX}-${SNAP_SUFFIX}"
create_snapshot "$SRC_VM" "$HYP" "$SNAP_NAME" || fatal_error "Failed to create snapshot $SNAP_NAME!"

echo "Clone $SRC_VM volumes..."
for VOLUME in $VOLUMES; do
    DST_VOLUME=${VOLUME/$SRC_VM/$DST_VM}
    echo -n "$VOLUME as $DST_VOLUME: "
    run_external rbd clone "$VOLUME"@"$SNAP_NAME" "$DST_VOLUME" || \
        fatal_error "Failed to clone the snapshot $VOLUME@$SNAP_NAME as $DST_VOLUME!"
    echo "done."
done

TMP=$(mktemp -t vm-clone-"${DST_VM}"-XXX --suffix .xml)
echo "Prepare $DST_VM configuration (in $TMP file)"
echo -n " - Dump $SRC_VM configuration..."
LC_ALL=C ssh "$HYP" "$REAL_VIRSH" dumpxml --inactive "$SRC_VM" > "$TMP" || \
    fatal_error "Failed to dump $SRC_VM configuration"
echo "done."

echo -n " - Rename VM $SRC_VM as $DST_VM..."
if sed -i "s/$SRC_VM/$DST_VM/g" "$TMP"; then
    echo "done."
else
    echo "FAILURE. Please change it manually!"
fi

UUID=$(uuidgen)
echo -n " - Change VM UUID ($UUID)... "
if xmlstarlet edit --inplace --update '/domain/uuid' --value "$NEW_UUID" "$TMP"; then
    echo "done."
else
    error "Failed to change VM UUID ($UUID). Please change it manually!"
fi


echo " - Generate new network interface MAC addresses..."
for old_mac in $(xmlstarlet select -t -v '/domain/devices/interface/mac/@address' "$TMP"); do
    new_mac=$(generate_mac)
    echo -n "   - Replace '$old_mac' by '$new_mac'..."
    if sed -i "s/$old_mac/$new_mac/g" "$TMP"; then
        echo "done."
    else
        error "Failed to replace old MAC address ($old_mac => $new_mac). Please change it manually!"
    fi
done
echo "done."

echo "done."

if [[ $AUTO -ne 1 ]]; then
    echo
    echo "Please control and adjust the generated configuration"
    echo "[Press enter to continue]"
    read -r
    vi "$TMP"
    confirm "Continue" || exit 1

    TARGET_HYP=""
    while [[ -z "$TARGET_HYP" ]]; do
        echo -n "On witch hypervisor you want to deploy the $DST_VM VM [$HYPS, default: $HYP]: "
        read -r TARGET_HYP
        [[ -z "$TARGET_HYP" ]] && TARGET_HYP=$HYP
        check_hyp "$TARGET_HYP" || { echo "Invalid hypervisor '$TARGET_HYP'."; TARGET_HYP=""; }
    done
else
    echo "Auto mode: deploy VM $DST_VM on same host as $SRC_VM ($HYP)."
    TARGET_HYP="$HYP"
fi

echo "Define $DST_VM VM on $TARGET_HYP..."
if [[ "$TARGET_HYP" != "$(hostname)" ]]; then
    run_external scp -q "$TMP" "$TARGET_HYP":/tmp/"$DST_VM".xml || \
        fatal_error "Failed to copy generated VM configuration file ($TMP) on $TARGET_HYP."
    run_external ssh "$TARGET_HYP" "$REAL_VIRSH" define "/tmp/$DST_VM.xml" || \
        fatal_error "Failed to define $DST_VM on $TARGET_HYP."
else
    run_external "$REAL_VIRSH" define "$TMP" || \
        fatal_error "Failed to define $DST_VM on $TARGET_HYP."
fi
echo "done."
clean_cache

if confirm "Do you want to start $DST_VM now on $TARGET_HYP"; then
    echo "Start $DST_VM in $TARGET_HYP..."
    if [[ "$TARGET_HYP" != "$(hostname)" ]]; then
        run_external ssh "$TARGET_HYP" "$REAL_VIRSH" start "$DST_VM" || \
            fatal_error "Failed to start $DST_VM on $TARGET_HYP."
    else
        run_external "$REAL_VIRSH" start "$DST_VM" || \
            fatal_error "Failed to start $DST_VM on $TARGET_HYP."
    fi
else
    echo "done."
fi
