#!/bin/bash

set -eu
shopt -s nullglob
# __SILENT=TRUE
. /opt/fox_utils/crab_sys.sh
[ "${1:---help}" = "--help" ] && sys::usage "$@"
### --help Info: restore from local backup
### --help Usage: vz_cli|kvm_cli restore $VM_NAME
### --help Usage:   --backup-version=ts - востановить указанную версию, вместо последней
### --help Usage:   --backup-copy - копировать бэкап вместо перемещения, оригинал - в корзину
### --help Example:
sys::arg_parse "$@"
VM_NAME=$1
if vzctl status "$VM_NAME" &>/dev/null; then
	echo "LOG_ERROR $VM_NAME already exists"
	exit 255
fi
if [ -d "/vz/backup/$VM_NAME" ]; then
	BACKUP_DIR="/vz/backup/$VM_NAME"
elif [ -d "/vz/backup/kvm-${VM_NAME}" ]; then
	BACKUP_DIR="/vz/backup/kvm-${VM_NAME}"
else
	echo "LOG_ERROR not found backup ${VM_NAME}"
	exit 255
fi

[ ! -d "$BACKUP_DIR/conf" ] && { echo "backup не обнаружен $BACKUP_DIR"; exit 255; }
mkdir -p "/opt/fox_conf/vm/"

[ "${ARG_ONLY_DISK:-}" != TRUE ] && \
	rsync -a --delete "$BACKUP_DIR/conf/" "/opt/fox_conf/vm/$VM_NAME/"

. /opt/fox_utils/fox_conf vm get "$VM_NAME"

PRIVATE="/vz/private/$VM_UUID"

crab_sync_utils_opts=
if [[ ${__DEBUG:-} == TRUE ]]; then
	crab_sync_utils_opts+=--debug
fi

if [[ -n ${ARG_BACKUP_COPY:-} ]]; then
	/opt/fox_utils/crab_sync_utils ${crab_sync_utils_opts} restore \
		--dir "${BACKUP_DIR}/disk" --dst "$PRIVATE" \
		${ARG_BACKUP_VERSION:+--version "$ARG_BACKUP_VERSION"}
	# старый бекап сохраним в корзине
	mkdir -p "/vz/.trash"
	mv -f "$BACKUP_DIR" "/vz/.trash/backup.${BACKUP_DIR##*/}.$(date +%s)"
else
	mv -f "${BACKUP_DIR}/disk" "$PRIVATE"
	if [[ -n ${ARG_BACKUP_VERSION:-} ]]; then
		# Откатим бэкап к требуемой версии
		/opt/fox_utils/crab_sync_utils ${crab_sync_utils_opts} restore \
			--dir "$PRIVATE" --version "$ARG_BACKUP_VERSION"
	fi
	rm -rf --one-file-system "$BACKUP_DIR/conf/"
	rmdir "${BACKUP_DIR}"
fi
# Удаляем BLOG в $PRIVATE,
#  т.к. при запуске ВМ, история ломается, вследствви модификации ploop
#  а попытка восстановиться из поломанной истории поломает ploop
rm -rf --one-file-system "$PRIVATE/.INFO" "$PRIVATE/.BACKUP"
find "$PRIVATE" -type d \( -name .BLOG -o -name .BMAP \) -exec rm -r --one-file-system '{}' +

rm -f "/etc/vz/conf/${VM_UUID}.conf" "/etc/vz/names/${VM_NAME}.conf"
ln -nsf '5' "$PRIVATE/.ve.layout" # признак новой версии контейнера
mkdir -p "$PRIVATE/fs" "$PRIVATE/scripts"
ln -nfs "root.hdd/templates" "$PRIVATE/templates"
vzctl register "/vz/private/${VM_UUID}/" "${VM_UUID}"
# это сделает vzctl register ln -nfs "$PRIVATE/ve.conf" "/etc/vz/conf/${VM_UUID}.conf"
# это сделает vzctl register ln -nfs "$PRIVATE/ve.conf" "/etc/vz/names/${VM_NAME}.conf"
rm -rf --one-file-system "$PRIVATE/dump/Dump"


extract_dumps() {
	local f tar_name snap_id
	for f in $PRIVATE/dump/*.tar.lzo; do
		# Dump.tar.lzo, <ts>.{<snap_id>}.tar.lzo
		tar_name="${f##*/}"
		tar_name="${tar_name%.tar.lzo}"
		snap_id="${tar_name#*.}"
		if [[ $tar_name = Dump ]] \
			|| (  [[ -f "$PRIVATE/Snapshots.xml" ]] \
			&& grep -qe "$snap_id" "$PRIVATE/Snapshots.xml" ); then
			(
				cd "$PRIVATE/dump/"
				tar -I lzop -xf "$f"
				rm -f "$f"
			)
		fi
	done
	return 0
}


if [ "${ARG_ONLY_DISK:-}" != TRUE ]; then
	extract_dumps
fi

if [ -d "$PRIVATE/dump/Dump" ]; then
	# Наличие папки не очень надёжный признак suspend-а
	vzctl restore "$VM_UUID"
else
	# В нормальной ситуации у нас может быть 2 снапшота: backup_cur_state и backup_snap
	#  откатываемся к backup_cur_state, если он есть
	#  при оффлайн миграции контейнер останавливается, и backup_cur_state не создаётся
	#
	# PARENT_UUID C UUID                                   DATE                NAME
	#             * {08ed71b2-759f-4092-923a-1131ae5d1d76} 2020-06-18 03:47:27 backup_snap
	set -o pipefail
	BACKUP_CUR_STATE=$( vzctl snapshot-list "$VM_UUID" \
		| sed 's/.*\* {\([0-9a-f-]\+\)}.* backup_cur_state$/\1/;t;d' )
	set +o pipefail
	if [ -n "$BACKUP_CUR_STATE" ]; then
		# snapshot-switch - делает resume, если у снапшота есть дамп
		vzctl snapshot-switch "$VM_UUID" --id "$BACKUP_CUR_STATE"
	fi
	# Это нормально Failed to delete snapshot: Error in do_delete_snapshot (snapshot.c:127)
fi

# Мы восстановились, удалим в корзину лишние дампы и снапшоты чтобы они не попадали в бекап
dump_id_list="$(vzctl snapshot-list "$VM_UUID" -H -o UUID)"
snap_id_list="$(ploop snapshot-list -H -o FNAME $PRIVATE/root.hdd/DiskDescriptor.xml)"
vz_trash_dir="/vz/.trash/snapshots.${BACKUP_DIR##*/}.$(date +%s)"
for dump_file in $PRIVATE/dump/*{ve.conf,tar.lzo}; do
	if [ -n "$dump_id_list" ] && grep -qF "$dump_id_list" <<< "$dump_file"; then
		continue
	fi
	mkdir -p "$vz_trash_dir/dump/"
	mv "$dump_file" "$vz_trash_dir/dump/"
done
for snap_file in $PRIVATE/root.hdd/root.hds.*; do
	snap_name=${snap_file##*/}
	if [ -n "$snap_id_list" ] && ! grep -q "$snap_name" <<< "$snap_id_list"; then
		mkdir -p "$vz_trash_dir/root.hdd/"
		mv "$snap_file" "$vz_trash_dir/root.hdd/"
	fi
done

[ "${ARG_ONLINE:-}" != TRUE ] && vzctl stop "$VM_UUID"

exit 0
