#!/bin/bash

set -eu

### --help Info: создаст образ ВМ из публичных образов провайдера
### --help Usage: vm_tmplt_create --type= --dist= --version= [--name=]
### --help Example: vm_tmplt_create --type=lxc --dist=ubuntu --version=jammy
### --help Example: vm_tmplt_create --type=lxc --dist=ubuntu --version=jammy \
### --help Example:                       --name=fox-ubuntu-24.04-v1.0

__SILENT=TRUE
. /opt/fox_utils/crab_sys.sh
[[ "$@" =~ --help ]] && sys::usage "$@"
sys::arg_parse "$@"
sys::arg_parse "$@"

declare FOLDER
declare MNT_PATH
declare NAME
declare NAME_IMG
declare NAME_ARCHIVE
declare TMPLT_PATH

FOLDER="/opt/fox_tmplt/$ARG_TYPE"


__lxc_run_prepare_script(){
	# TODO: запустить ВМ, загрузить в неё скрипт установки/подготовки, выполнить скрипт
	echo "TODO __lxc_run_install_script"
	return 0
	script="/opt/fox_utils/vm_tmplt_scripts/$ARG_TYPE/$ARG_SCRIPT"
	return 0
}
__lxc_patch_systemd_resolvconf(){
	local f
	for f in \
		"$MNT_PATH/etc/systemd/system/dbus-org.freedesktop.resolve1.service" \
		"$MNT_PATH/etc/systemd/system/multi-user.target.wants/systemd-resolved.service" \
		"$MNT_PATH/etc/resolv.conf"; do
		[[ -f "$f" ]] && rm -f "$f"
		[[ -L "$f" ]] && rm -f "$f"
	done
	ln -sf /dev/null "$MNT_PATH/etc/systemd/system/systemd-resolved.service"
	echo "nameserver 8.8.8.8" > "$MNT_PATH/etc/resolv.conf"
	return 0
}
__lxc_create_zero_template(){
	local lodev tmp_name

	echo "Создаём файл"
	fallocate -l 100M "$NAME_IMG"

	echo "Подключаем в системе"
	lodev="$(losetup --find --show $NAME_IMG)"

	echo "Превращаем в LVM"
	pvcreate "$lodev"
	vgcreate "$NAME" "$lodev"
	vgchange --activate y "$NAME"
	[[ "${ARG_DEBUG:-}" ]] && (pvdisplay -v -m)
	lvcreate -n root -l +100%FREE "$NAME"

	echo "Создаём ФС"
	mkfs.ext4 "/dev/$NAME/root"

	echo "Деактивируем LVM"
	lvchange --activate n "$NAME"
	vgchange --activate n "$NAME"
	losetup --detach "$lodev"

	echo "Архивируем"
	# Для zero обязательно, т.к. сжимает 100М до размера метаданных.
	xz -z -k "$NAME_IMG"
	return 0
}
__lxc_create_template(){
	local lodev
	MNT_PATH="/tmp/image_${NAME}_$(date +%s)"

	lxc-create \
		--name "$NAME" --template download \
		-- --dist "$ARG_DIST" --release "${ARG_VERSION}" --arch amd64
	[[ -n ${ARG_SCRIPT:-} ]] && __lxc_run_prepare_script

	echo "Создаём файл"
	fallocate -l 5G "$NAME_IMG"

	echo "Подключаем в системе"
	lodev=$(losetup --find --show --nooverlap "$NAME_IMG") && echo lodev="$lodev"

	echo "Превращаем в LVM"
	pvcreate "$lodev"
	vgcreate "$NAME" "$lodev"
	vgchange --activate y "$NAME"
	[[ "${ARG_DEBUG:-}" ]] && (pvdisplay -v -m)
	lvcreate -n root -l +100%FREE "$NAME"

	echo "Создаём ФС"
	mkfs.ext4 "/dev/$NAME/root"

	echo "Заполняем данными"
	mkdir -p "$MNT_PATH"
	mount "/dev/$NAME/root" "$MNT_PATH"
	rsync -ah --stats --numeric-ids --delete "/var/lib/lxc/$NAME/rootfs/" "$MNT_PATH/"

	echo "Патчим resolv.conf systemd"
	__lxc_patch_systemd_resolvconf

	echo "Отмонтируем"
	umount "$MNT_PATH"
	rm -rf --one-file-system "${MNT_PATH:-_NODIR}"

	echo "Деактивируем LVM"
	lvchange --activate n "$NAME"
	vgchange --activate n "$NAME"
	losetup --detach "$lodev"

	echo "Удаляем исходник образа"
	lxc-destroy --name "$NAME"

	echo "Архивируем"
	xz -z -k "$NAME_IMG"
	return 0
}
lxc_create_template(){
	local f
	NAME="${ARG_NAME:-}"
	[[ ! "${NAME:-}" ]] && NAME="$ARG_DIST-$ARG_VERSION-tmplt"
	# Название пустого шаблона должно быть zero, оно уже используется в скриптах.
	if [[ $NAME == zero ]]; then
		# Нельзя оставлять просто "zero"
		# 1) losetup ругается: /dev/zero: already exists in filesystem
		# 2) в supervisor/vm/vm_lxc/vm_lxc_driver zero меняется на fox-zero
		NAME="fox-zero"
		f=__lxc_create_zero_template
	else
		f=__lxc_create_template
	fi
	NAME_IMG="${NAME}.img"
	NAME_ARCHIVE="${NAME_IMG}.xz"
	TMPLT_PATH="$FOLDER/$NAME_ARCHIVE"
	if [[ ! -f $TMPLT_PATH ]]; then
		mkdir -p "$FOLDER"
		mkdir -p /tmp/vm_tmplt_create
		cd /tmp/vm_tmplt_create
		"$f" >&2
		mv "$NAME_IMG" "$FOLDER/"
		mv "$NAME_ARCHIVE" "$FOLDER/"
	fi
	echo "$TMPLT_PATH"
	return 0
}

if [[ -z "${ARG_TYPE:-}" ]]; then
	echo "Необходимо указать тип. Доступные типы: lxc"
	exit 1
elif [[ ! "${ARG_TYPE:-}" =~ ^(lxc|LXC)$ ]]; then
	echo "Создание образов для $ARG_TYPE не реализовано"
	exit 2
fi

"${ARG_TYPE}_create_template"

exit 0
