#!/bin/sh

# Copyright (C) 2010-2023 Pädagogisches Landesinstitut Rheinland-Pfalz
# Copyright (C) 2022-2023 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.

# Prepare host for being a FAI server that can be used for installing
# Debian Edu Router systems.

set -e

LC_ALL=C
export LC_ALL

# Make sure the created directories and files are readable by tfptd
# run as user nobody.
umask 022

product="$(echo $(basename $0) | sed -Ee "s/(.+)-fai_install/\1/")"

###
### FAI Setup
###

[ "$archs" ]             || archs=$(command -V dpkg 1>/dev/null 2>/dev/null && dpkg --print-architecture || uname -m)
[ "$codenames" ]         || codenames=$(cat /etc/os-release | grep VERSION_CODENAME | cut -d "=" -f2)
[ "$http_proxy" ]        || unset http_proxy
[ "$ftp_proxy" ]         || unset ftp_proxy
[ "$mirrorurl" ]         || mirrorurl=http://deb.debian.org/debian
[ "$rootpw" ]            || rootpw=""
[ "$tftpdir" ]           || tftpdir="/srv/tftp"
[ "$fai_logserver" ]     || unset fai_logserver
[ "$deployment_server" ] || unset deployment_server
[ "$fai_loguser" ]       || unset fai_loguser
[ "$school_tag" ]        || school_tag="SKOLE"

# required for pre-selecting the default boot item in iPXE config
[ "$default_arch" ]      || default_arch="$(echo ${archs} | cut -d " " -f1)"
[ "$default_codename" ]  || default_codename=$(echo ${codenames} | cut -d " " -f1)

[ "$supported_locales" ] || supported_locales="C.UTF-8"
[ "$default_locale" ]    || default_locale="C.UTF-8"

# source debian-edu-fai's config file
# Allow site specific overrides to the variables
if [ -f /etc/debian-edu/${product}-fai.conf ] ; then
	. /etc/debian-edu/${product}-fai.conf
fi

for codename in ${codenames}; do

	# skip codenames that don't sound like Debian suites...
	if ! echo "bullseye bookworm trixie forky sid unstable" | grep -q "${codename}"; then
		echo "WARNING: The name '${codename}' is not a known and recent Debian distribution codename. Skipping..."
		continue
	fi

	# iterate over configured FAI client architectures...
	for arch in ${archs}; do

		set +x

		echo
		echo "###"
		echo "### Creating/updating FAI server configuration"
		echo "### (codename: ${codename}, architecture: ${arch})"
		echo "###"

		set -x

		# create codename based fai base config
		faiconfig="/etc/debian-edu/fai/${product}-fai.${arch}+${codename}"
		if [ -d /etc/debian-edu/fai/${product}-fai.TEMPLATE ]; then
			if [ -d "${faiconfig}" ]; then
				rm -Rf "${faiconfig}"
			fi
			cp -a /etc/debian-edu/fai/${product}-fai.TEMPLATE "${faiconfig}"
			touch "${faiconfig}/DONT_MODIFY_FILES_IN_THIS_DIRECTORY"
		else
			echo "ERROR: Failed to create FAI configuration in ${faiconfig}, no ${product}-fai.TEMPLATE directory found"
			exit 1
		fi

		# fill in placeholders (@rootpw@, @codename@ and @arch@) in nfsroot.conf.in
		find "${faiconfig}" -name '*.in' | while read file_to_adapt; do

			cp "${file_to_adapt}" "${file_to_adapt%.in}"
			perms="$(stat --printf "%a" "${file_to_adapt}")"

			[ "$rootpw" ]            && export rootpw            && perl -p -e "s/\@rootpw\@/\$ENV{rootpw}/g" "${file_to_adapt%.in}" > "${file_to_adapt%.in}.new" && mv "${file_to_adapt%.in}.new" "${file_to_adapt%.in}"
			[ "$mirrorurl" ]         && export mirrorurl         && perl -p -e "s/\@mirrorurl\@/\$ENV{mirrorurl}/g" "${file_to_adapt%.in}" > "${file_to_adapt%.in}.new" && mv "${file_to_adapt%.in}.new" "${file_to_adapt%.in}"
			[ "$codename" ]          && export codename          && perl -p -e "s/\@codename\@/\$ENV{codename}/g" "${file_to_adapt%.in}" > "${file_to_adapt%.in}.new" && mv "${file_to_adapt%.in}.new" "${file_to_adapt%.in}"
			[ "$arch" ]              && export arch              && perl -p -e "s/\@arch\@/\$ENV{arch}/g" "${file_to_adapt%.in}" > "${file_to_adapt%.in}.new" && mv "${file_to_adapt%.in}.new" "${file_to_adapt%.in}"

			# FIXME: also comment out variables that are not set (anymore) in /etc/debian-edu/${product}-fai.cfg

			[ "$fai_logserver" ]     && export fai_logserver     && perl -p -e "s/^(#|)LOGSERVER=.{0,1}\@fai_logserver\@.{0,1}\s*\$/LOGSERVER=\'\$ENV{fai_logserver}\'\n/g" "${file_to_adapt%.in}" > "${file_to_adapt%.in}.new" && mv "${file_to_adapt%.in}.new" "${file_to_adapt%.in}"
			[ "$fai_loguser" ]       && export fai_loguser       && perl -p -e "s/^(#|)LOGUSER=.{0,1}\@fai_loguser\@.{0,1}\s*\$/LOGUSER=\'\$ENV{fai_loguser}\'\n/g" "${file_to_adapt%.in}" > "${file_to_adapt%.in}.new" && mv "${file_to_adapt%.in}.new" "${file_to_adapt%.in}"
			[ "$deployment_server" ] && export deployment_server && perl -p -e "s/^(#|)FAI_CONFIG_SRC=.{0,1}(http|https):\/\/\@deployment_server\@\/(.*)\$/FAI_CONFIG_SRC='\2:\/\/\$ENV{deployment_server}\/\3\n/g" "${file_to_adapt%.in}" > "${file_to_adapt%.in}.new" && mv "${file_to_adapt%.in}.new" "${file_to_adapt%.in}"

			# hack for non-free-firmware repo area added since Debian 12 (aka bookworm) [we only support Debian 11 (aka bullseye) and upwards]
			if [ "$codename" = "bullseye" ]; then
				perl -p -e "s/ non-free-firmware//g" "${file_to_adapt%.in}" > "${file_to_adapt%.in}.new" && mv "${file_to_adapt%.in}.new" "${file_to_adapt%.in}"
			fi

			chown root:root "${file_to_adapt%.in}"
			chmod "${perms}" "${file_to_adapt%.in}"
			rm "${file_to_adapt}"

		done

		# source the NFS conf file... this might override our FAI_CONFIGDIR
		# (but should not as recommended in our nfsroot.conf.in template)
		if [ -f "$faiconfig/nfsroot.conf" ]; then
			. $faiconfig/nfsroot.conf
		else
			echo "ERROR: No nfsroot.conf file found in $faiconfig/, can't continue..."
			exit 1
		fi

		# hard-code some sensible defaults in case they have been commented out in $faiconfig/nfsroot.conf
		[ "$FAI_DEBOOTSTRAP" ]      || FAI_DEBOOTSTRAP="${codename} http://deb.debian.org/debian"
		[ "$FAI_ROOTPW" ]           || FAI_ROOTPW="${rootpw}"
		[ "$NFSROOT" ]              || NFSROOT="/srv/fai/nfsroot.${product}-fai/${arch}+${codename}"
		[ "$TFTPROOT" ]             || TFTPROOT="${tftpdir}/${product}-fai.${arch}+${codename}"
		[ "$NFSROOT_HOOKS" ]        || NFSROOT_HOOKS="/etc/debian-edu/fai/${product}-fai.${arch}+${codename}/"
		[ "$FAI_DEBOOTSTRAP_OPTS" ] || FAI_DEBOOTSTRAP_OPTS="--arch=${arch}"
		[ "$FAI_CONFIGDIR" ]        || FAI_CONFIGDIR="/srv/fai/config"

		FAI_CONFIGDIR_REAL="${FAI_CONFIGDIR}"
		# if FAI_CONFIGDIR is a symlink, we need to find the real location...
		if [ -h ${FAI_CONFIGDIR} ]; then
			FAI_CONFIGDIR_REAL="$(readlink ${FAI_CONFIGDIR})"
		fi

		set +x

		echo
		echo "###"
		echo "### Installing/updating FAI config space (this takes some time)"
		echo "### (codename: ${codename}, architecture: ${arch})"
		echo "###"
		${product}-fai_updateconfigspace "${FAI_CONFIGDIR_REAL}"

		set -x

		# Update variables to be customized in FAI config space

		# This code block might be executed on the same FAI_CONFIGDIR several times
		# (once per arch and codename).
		# This is a known issue and works as designed. People might have chosen to
		# use difference FAI_CONFIGDIR values for different environments and with
		# such a choice executing the below per arch and per codename makes sense.

		set +x

		echo
		echo "###"
		echo "### Tweaking FAI config space"
		echo "### (codename: ${codename}, architecture: ${arch})"
		echo "###"

		set -x

		find ${FAI_CONFIGDIR_REAL} -name '*.in' | while read file_to_adapt; do

			cp "${file_to_adapt}" "${file_to_adapt%.in}"
			perms="$(stat --printf "%a" "${file_to_adapt}")"

			[ "$codename" ]          && export codename          && perl -p -e "s/\@codename\@/\$ENV{codename}/g" "${file_to_adapt%.in}" > "${file_to_adapt%.in}.new" && mv "${file_to_adapt%.in}.new" "${file_to_adapt%.in}"
			[ "$arch" ]              && export arch              && perl -p -e "s/\@arch\@/\$ENV{arch}/g" "${file_to_adapt%.in}" > "${file_to_adapt%.in}.new" && mv "${file_to_adapt%.in}.new" "${file_to_adapt%.in}"

			[ "$rootpw" ]            && export rootpw            && perl -p -e "s/^(#|)ROOTPW=.{0,1}\@rootpw\@.{0,1}\s*\$/ROOTPW=\'\$ENV{rootpw}\'\n/g" "${file_to_adapt%.in}" > "${file_to_adapt%.in}.new" && mv "${file_to_adapt%.in}.new" "${file_to_adapt%.in}"
			[ "$fai_logserver" ]     && export fai_logserver     && perl -p -e "s/^(#|)LOGSERVER=.{0,1}\@fai_logserver\@.{0,1}\s*\$/LOGSERVER=\'\$ENV{fai_logserver}\'\n/g" "${file_to_adapt%.in}" > "${file_to_adapt%.in}.new" && mv "${file_to_adapt%.in}.new" "${file_to_adapt%.in}"
			[ "$fai_loguser" ]       && export fai_loguser       && perl -p -e "s/^(#|)LOGUSER=.{0,1}\@fai_loguser\@.{0,1}\s*\$/LOGUSER=\'\$ENV{fai_loguser}\'\n/g" "${file_to_adapt%.in}" > "${file_to_adapt%.in}.new" && mv "${file_to_adapt%.in}.new" "${file_to_adapt%.in}"
			[ "$deployment_server" ] && export deployment_server && perl -p -e "s/^(#|)FAI_CONFIG_SRC=.{0,1}(http|https):\/\/\@deployment_server\@\/(.*)\$/FAI_CONFIG_SRC='\2:\/\/\$ENV{deployment_server}\/\3\n/g" "${file_to_adapt%.in}" > "${file_to_adapt%.in}.new" && mv "${file_to_adapt%.in}.new" "${file_to_adapt%.in}"
			[ "$school_tag" ]        && export school_tag        && perl -p -e "s/\@SKOLE\@/\$ENV{school_tag}/g" "${file_to_adapt%.in}" > "${file_to_adapt%.in}.new" && mv "${file_to_adapt%.in}.new" "${file_to_adapt%.in}"

			[ "$supported_locales" ] && export supported_locales && perl -p -e "s/\@supported_locales\@/\$ENV{supported_locales}/g" "${file_to_adapt%.in}" > "${file_to_adapt%.in}.new" && mv "${file_to_adapt%.in}.new" "${file_to_adapt%.in}"
			[ "$default_locale" ]    && export default_locale    && perl -p -e "s/\@default_locale\@/\$ENV{default_locale}/g" "${file_to_adapt%.in}" > "${file_to_adapt%.in}.new" && mv "${file_to_adapt%.in}.new" "${file_to_adapt%.in}"

			# hack for non-free-firmware repo area added since Debian 12 (aka bookworm) [we only support Debian 11 (aka bullseye) and upwards]
			if [ "$codename" = "bullseye" ]; then
				perl -p -e "s/ non-free-firmware//g" "${file_to_adapt%.in}" > "${file_to_adapt%.in}.new" && mv "${file_to_adapt%.in}.new" "${file_to_adapt%.in}"
			fi

			chown root:root "${file_to_adapt}"
			chmod "${perms}" "${file_to_adapt%.in}"

		done

		# set APTPROXY for use by fai-make-nfsroot...
		if [ -n "${http_proxy}" ]; then
			export APTPROXY="${http_proxy}"
			export http_proxy
		fi

		set +x

		echo
		echo "###"
		echo "### Creating FAI nfsroot installer environment"
		echo "### (codename: ${codename}, architecture: ${arch})"
		echo "###"

		# the NFSROOT variable we should have obtained from sourcing $faiconfig/nfsroot.conf
		# (aka /etc/fai/nfsroot.conf) above...
		if [ -n "${NFSROOT}" ] && [ -n "${codename}" ]; then

			# create nfs-root from scratch (if not present or not fully created in a previous run)

			# Create a ".DEBIAN_EDU_FAI_NFSROOT_INSTALLATION_COMPLETED" file at the end
			# of fai-make-nfsroot and check for the presence of that file for detecting
			# whether a fresh NFSROOT setup is required or just an NFSROOT update/upgrade.
			if [ ! -f "${NFSROOT}/.DEBIAN_EDU_FAI_NFSROOT_INSTALLATION_COMPLETED" ]; then

				# enforce NFSROOT re-creation (or initial creation)
				fai-make-nfsroot -v -f -N -C ${faiconfig}
				touch "${NFSROOT}/.DEBIAN_EDU_FAI_NFSROOT_INSTALLATION_COMPLETED"
			else
				# update packages (and clean old kernel images) in NFSROOT
				fai-make-nfsroot -v -k -N -C ${faiconfig}
				# adjust nfsroot configuration (SSH pubkeys, rootpw, etc.)
				fai-make-nfsroot -v -a -C ${faiconfig}

			fi
			# just in case, should be handled well by fai-make-nfsroot these days...
			[ -d "${NFSROOT}/proc/self" ] && umount "${NFSROOT}/proc"
			[ -d "${NFSROOT}/sys/class" ] && umount "${NFSROOT}/sys"

			# Remove /srv/tftp/${product}-fai.ARCH+CODENAME after NFSROOT creation.
			# We don't need that.
			if [ -d "${TFPTROOT}/" ]; then
				rm -Rf "${TFTPROOT}/"
			fi

			# symlink kernel and initrd files into 
			if [ -e "${NFSROOT}/vmlinuz" ] && [ -e "${NFSROOT}/initrd.img" ]; then

				# create kernel dir in tftp area
				mkdir -p "${tftpdir}/debian-edu-fai/${arch}+${codename}/"

				# symlink vmlinuz / initrd in the NFSROOT
				if [ -e "${tftpdir}/debian-edu-fai/${arch}+${codename}/vmlinuz" ]; then
					rm "${tftpdir}/debian-edu-fai/${arch}+${codename}/vmlinuz"
				fi
				cp -a "${NFSROOT}/$(readlink "${NFSROOT}/vmlinuz")" "${tftpdir}/debian-edu-fai/${arch}+${codename}/vmlinuz"
				if [ -e "${tftpdir}/debian-edu-fai/${arch}+${codename}/initrd.img" ]; then
					rm "${tftpdir}/debian-edu-fai/${arch}+${codename}/initrd.img"
				fi
				cp -a "${NFSROOT}/$(readlink "${NFSROOT}/initrd.img")" "${tftpdir}/debian-edu-fai/${arch}+${codename}/initrd.img"

			fi
		fi

		set -x

	done
done
