#!/bin/sh
#
# Prepare for PXE installation of Debian Edu.
#
# A better idea might be to use di-netboot-assistant,
# <URL:http://www.klabs.be/~fpiat/linux/debian/di-netboot-assistant/>.

set -e

LC_ALL=C
export LC_ALL

## FIXME: Why is resolv.conf empty or missing? Because network 
## was started in the chroot (target)? 
## Try to find the DNS from the leases file, if that fails use
## default DNS:
if [ ! -s /etc/resolv.conf ] ; then
	DNS="10.0.2.2"
	LEASEDIR=/var/lib/dhcp/
	if [ -d $LEASEDIR ] ; then
		LEASEFILE=$LEASEDIR`ls -tr -1 $LEASEDIR | tail -n 1`
		if [ -r $LEASEFILE ] ; then
			if DNSLEASE=`cat $LEASEFILE | grep domain-name-servers | \
				tail -n 1 | \
				grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+"` ; then
				DNS=$DNSLEASE
				echo "info: Found leases file and domain-name-server: $DNS."
			else
				echo "info: Could not extract DNS from leases file."
			fi
		fi
	fi
	echo "info: Create temporary /etc/resolv.conf with DNS: $DNS."
	cat >> /etc/resolv.conf <<EOF
## This is a temporary resolv.conf created by $0.
## If you find it after installation, something went wrong. Try to replace it 
## by a symlink: /etc/resolv.conf -> /etc/resolvconf/run/resolv.conf, i.e.: 
## rm /etc/resolv.conf; ln -s /etc/resolvconf/run/resolv.conf /etc/resolv.conf
nameserver $DNS
search intern
EOF
	fi

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

# Fetch ftp_proxy and http_proxy if set globally
if [ -f /etc/environment ] ; then
	. /etc/environment
fi

# Grab dist value for both testing and stable release cases.
if grep -q / /etc/debian_version ; then
	# Likely a Debian testing/unstable system this script is executed on.
	dist_codename=$(cat /etc/debian_version | cut -d/ -f1)
	dist_version=${dist_codename}
else
	# A stable release of Debian.
	dist_codename=$(lsb_release -sc)
	dist_version=$(lsb_release -sr)
fi

default_mydesktop="xfce"

[ "$archs" ]      || archs="amd64"
[ "$mirrorurl" ]  || mirrorurl=http://deb.debian.org/debian
[ "$hostname" ]   || hostname=pxeinstall
[ "$domain" ]     || domain=intern
[ "$mydesktop" ]  || mydesktop="${default_mydesktop}"
[ "$graphicdi" ]  || graphicdi=false
[ "$dailydi" ]    || dailydi=false
[ "$theme" ]      || theme="$(ls -L /etc/alternatives/desktop-theme/plymouth 2>/dev/null | grep script | cut -d'.' -f 1)"
# Not hardcoded to allow PXE installation of a main-server without a
# proxy set
#[ "$http_proxy" ] || http_proxy=http://webcache:3128
#[ "$ftp_proxy" ] || ftp_proxy=http://webcache:3128

if [ -f /etc/debian-edu/config ] ; then
	. /etc/debian-edu/config
fi

# Allow site specific overrides to the variables
if [ -f /etc/debian-edu/pxeinstall.conf ] ; then
	. /etc/debian-edu/pxeinstall.conf
fi

# This part does not work from within debian-installer, as it is
# executed from cfengine before the cdebconf files are copied into
# /var/log/installer/cdebconf/ ("debconf-get-selections --installer"
# does not work).  A workaround for this issue was added to
# debian-edu-install, copying the files a bit earlier.
installconfig=""
for template in debian-installer/locale \
                keyboard-configuration/xkb-keymap \
                tasksel/desktop; do
	value="$(debconf-get-selections --installer | grep $template | awk '{print $4}')"
	if [ -z "$value" ] ; then
		# If there is no value in the installer debconf database, set the default one.
		# Useful if modular main server installation has been used (no desktop).
		value="${default_mydesktop}"
	fi

	if [ "tasksel/desktop" = $template ] && [ "${mydesktop}" != "${default_mydesktop}" ]; then
		# Let setting from /etc/debian-edu/pxeinstall.conf override tasksel/desktop.
		value="${mydesktop}"
	fi

	# Map the long debconf names to the keywords supported in the kernel cmdline.
	if [ "tasksel/desktop" = $template ] ; then template=desktop; fi
	if [ "debian-installer/locale" = $template ] ; then template=locale; fi
	if [ "keyboard-configuration/xkb-keymap" = $template ] ; then template=keymap; fi

	if [ "$value" ] ; then
	installconfig="$installconfig $template=$value"
	fi
done

tftpdir=/srv/tftp

# Where to find the preseed file on the web
preseedurl=http://www/debian-edu-install.dat

# Where the preseed file is on the disk.
preseedfile=/etc/debian-edu/www/debian-edu-install.dat

# Start from a clean state after any configuration changes have been made.
if [ -d $tftpdir/ltsp ] ; then
	rm -rf $tftpdir/debian-edu
	rm -rf $tftpdir/debian-installer
	rm -f $tftpdir/ltsp/ltsp.ipxe
	# re-generate clean ipxe menu file in case of LTSP client support.
	if [ -d /srv/ltsp/images ] ; then
		ltsp ipxe
		# adjust ipxe menue for Debian Edu use.
		sed -i 's#ltsp/ltsp.img#ltsp/${img}/ltsp.img#' /srv/tftp/ltsp/ltsp.ipxe
	fi
fi

[ -d $tftpdir ] || mkdir $tftpdir
[ -d $tftpdir/debian-edu ] || mkdir $tftpdir/debian-edu

[ -d $tftpdir/debian-installer ] || \
mkdir $tftpdir/debian-installer
cd $tftpdir/debian-installer

# We require to have at least debian-installer-<dist_version>-netboot-* installed,
# if not, we fallback to http download from Debian archive servers
if [ -d "/usr/lib/debian-installer/images/${dist_version}" ]; then
	di_versions_supported="$(cd /usr/lib/debian-installer/images/; ls -1 | grep -E '^[0-9]+$' | sort -r -h)"
else
	di_versions_supported="${dist_version}"
fi

for arch in $archs ; do
	for di_ver in ${di_versions_supported}; do
		(
		cd $tftpdir/debian-installer

		tarball=""
		if [ -d /usr/lib/debian-installer/images/ ] && [ -n "$(find /usr/lib/debian-installer/images/ -mindepth 1 -maxdepth 1 -type d  2>/dev/null)" ]; then

			di_img_dir="/usr/lib/debian-installer/images/${di_ver}/${arch}"
			if [ -d ${di_img_dir} ]; then
				# Use the debian/installer netboot debs
				mkdir -p ${di_ver}/
				if [ true = "$graphicdi" ]; then
					cp -r -u ${di_img_dir}/gtk/debian-installer/${arch}  ${di_ver}/
				else
					cp -r -u ${di_img_dir}/text/debian-installer/${arch} ${di_ver}/
				fi
			else
				continue
			fi

		elif [ ! -f ${dist_version}/netboot-$arch.tar.gz ] ; then

			# Daily DI vs. released netboot images
			if [ true = "$dailydi" ] ; then
				diurl=https://d-i.debian.org/daily-images/$arch/daily/netboot
			else
				diurl=${mirrorurl}/dists/${dist_codename}/main/installer-${arch}/current/images/netboot
			fi

			# Only support D-I version of the server's distro version
			di_ver=${dist_version}

			# This only supports Debian Installer netboot setup for the same version as this server.
			if [ true = "$graphicdi" ]; then
				# Use this URL for graphical installer, and fix
				# gtkvideo setting below
				url=$diurl/gtk/netboot.tar.gz
			else
				url=$diurl/netboot.tar.gz
			fi
			echo "Fetching $url"
			set +e
			if wget -q -O netboot-$arch.tar.gz.new $url; then
				mkdir -p ${di_ver}/
				cd ${di_ver}
				mv ../netboot-$arch.tar.gz.new netboot-$arch.tar.gz
				tarball=netboot-$arch.tar.gz
			else
				echo "warning: Unable to download $url"
				# remove cruft
				rm -f netboot-$arch.tar.gz.new
				continue
			fi
			set -e
		fi
		if [ "$tarball" ] ; then
			tar --strip-components=2 -zxvf $tarball
			# remove downloaded netboot installer tarball
			rm $tarball
		fi
		if [ true = "$graphicdi" ]; then
			# Replace Debian installer logo with Debian Edu one.
			TMP=$(mktemp -d)
			mkdir $TMP/$arch
			cd $TMP/$arch
			mkdir new
			cd new
			unmkinitramfs ${tftpdir}/debian-installer/${di_ver}/${arch}/initrd.gz .
			if [ ! -z "$theme" ] ; then
				cp /usr/share/pixmaps/debian-edu-${di_ver}-installer-logo.png usr/share/graphics/logo_debian.png
			fi
			find . | cpio -H newc -o > ../initrd
			cd ..
			gzip initrd
			cp initrd.gz ${tftpdir}/debian-installer/${di_ver}/${arch}/
			rm -rf $TMP
		fi
		)
	done
done

# We know that this script has been able to provide at least one netinstaller if its initrd.gz has been created successfully.
if [ -z "$(find ${tftpdir}/debian-installer/*/*/initrd.gz)" ]; then
	echo "ERROR: no D-I netboot image could be obtained, aborting further PXE setup for PXE-based Debian Installer."
	exit 1
fi

echo "Generating $preseedfile"
(
	cat <<EOF
# Enable the Debian Edu installer overrides
d-i     anna/choose_modules     multiselect     debian-edu-install-udeb: Execute Debian-Edu debian-installer profile

# Just accept the proposed hostname and domain, as it is dynamically
# fetched from DNS.
d-i     netcfg/get_hostname     seen    true
d-i     netcfg/get_domain       seen    true

# location of the proxies, in case it is required, both http and ftp
# in case someone ask d-i to use ftp mirrors.
d-i     mirror/http/proxy       string  $http_proxy
d-i     mirror/ftp/proxy        string  $ftp_proxy

# list extra packages to install here
#d-i     pkgsel/include string <pkg_name>

# if you want popcon enabled by default
#d-i     debian-edu-install/participate-popcon boolean true

# If you want a specific set of profiles installed
#d-i	debian-edu-install/profile multiselect Workstation, LTSP-Server

# If you want automatic partitioning
#d-i	debian-edu-install/confirm boolean true

# If you want to avoid the password question
#d-i passwd/root-password-crypted password passwordhash

# Tell PXE clients to fetch the correct time from the central NTP server
# d-i is unable to discover the ntp-server DHCP option.  Hardcode
# setting here instead.  FIXME: Remove when #714288 in netcfg is fixed.
d-i netcfg/dhcp_ntp_servers string ntp

# Pass on the time zone used on the main-server
EOF
	debconf-get-selections --installer | grep -w 'time/zone'

	# No use copying the installation mirror setting if a DVD or USB
	# stick was used.
	if grep -qi 'dvd|bd' /etc/apt/sources.list ; then
		cat <<EOF

# Avoid questions about mirrors, using manual setup
choose-mirror-bin     mirror/country          string  manual
choose-mirror-bin     mirror/protocol select  http
choose-mirror-bin     mirror/http/mirror      select
choose-mirror-bin     mirror/http/hostname    string  deb.debian.org
choose-mirror-bin     mirror/http/directory   string  /debian
EOF
	else
	debconf-get-selections --installer | grep -Ew 'mirror/http/mirror|mirror/country|mirror/protocol|mirror/http/hostname|mirror/http/directory|mirror/ftp/hostname|mirror/ftp/directory' | sort
	fi

	# Make it easier to have local overrides and still be able to
	# rerun debian-edu-pxeinstall.
	if [ -f $preseedfile.local ] ; then
		cat $preseedfile.local
	fi
) > $preseedfile

menufile=$tftpdir/debian-edu/install.cfg
echo "Generating $menufile"
(
	if [ true = "$graphicdi" ]; then
		gtkvideo="vga=788"
	fi
	for arch in $archs ; do
		for di_ver in ${di_versions_supported}; do
			if [ -d "${tftpdir}/debian-installer/${di_ver}/${arch}" ]; then
				cat <<EOF

# Based upon locale, keymap and desktop values used during main-server installation; auto URL added.
:${arch}_${di_ver}
set params auto url=http://www/debian-edu-install.dat hostname=$hostname domain=$domain $installconfig $gtkvideo --- quiet
kernel /debian-installer/${di_ver}/${arch}/linux initrd=initrd.gz \${params}
initrd /debian-installer/${di_ver}/${arch}/initrd.gz
boot || goto failed
EOF
			fi
		done
	done
) > $menufile

if [ ! -z "$theme" ] ; then
	cp /usr/share/pixmaps/$theme-syslinux.png $tftpdir/debian-edu/debian-edu-pxe.png
fi

# Generate/modify the iPXE menu file
if [ -f $tftpdir/ltsp/ltsp.ipxe ] ; then
	# ltsp is installed already, modify existing ipxe menu
	if ! grep -q main-server $tftpdir/ltsp/ltsp.ipxe ; then
		echo "Modifying $tftpdir/ltsp/ltsp.ipxe"

		# FIXME: also support other installer versions here, currently only latest version gets
		# integrated into LTSP servers ltsp.ipxe file.

		sed -i "/^menu.*/ a item\
item --gap                        Installation:\
item --key a amd64_${dist_version} Install Debian Edu ${dist_version} / amd64 (64-Bit)\
# BEGIN: Debian-Installer other versions
# END: Debian-Installer other versions
item\
" ${tftpdir}/ltsp/ltsp.ipxe
		cat $menufile >> $tftpdir/ltsp/ltsp.ipxe
	fi
else
	# generate ipxe menu on a plain main server for PXE installations
	mkdir -p $tftpdir/ltsp/
	cp /usr/lib/ipxe/undionly.kpxe $tftpdir/ltsp/
	cp /usr/lib/ipxe/snponly.efi $tftpdir/ltsp/
	cp /boot/memtest86+ia32.bin $tftpdir/ltsp/memtest.0
	cp /boot/memtest86+x64.efi $tftpdir/ltsp/memtest.efi
	echo "Generating $tftpdir/ltsp/ltsp.ipxe"
	cat <<EOF > ${tftpdir}/ltsp/ltsp.ipxe
#!ipxe
#
# Configure iPXE for network installations

console --picture /debian-edu/debian-edu-pxe.png ||

# Set the default image (img) based on arch, or to root-path if it's not empty
cpuid --ext 29 && set img amd64_${dist_version} || set img i386_${dist_version}

goto start

:start
# To completely hide the menu, set menu-timeout to -1
isset \${menu-timeout} || set menu-timeout 5000
iseq "\${menu-timeout}" "-1" && goto \${img} ||
menu Debian Edu iPXE boot menu || goto \${img}
item
item --gap                        Debian Edu installation:
item --key a amd64_${dist_version} Install Debian Edu ${dist_version} / amd64
item
# BEGIN: Debian-Installer other versions
# END: Debian-Installer other versions
item
item --gap                        Other options:
item --key m memtest              Memory test
item --key c config               Enter iPXE configuration
item --key s shell                Drop to iPXE shell
item --key d disk                 Boot from the first local disk
item
item --key x exit                 Exit iPXE and continue BIOS boot
choose --timeout \${menu-timeout} --default \${img} img || goto cancel
goto \${img}

:memtest
iseq \${platform} pcbios && kernel memtest.0 || kernel memtest.efi
# Boot "fails" on normal memtest exit with Esc, so show the menu again
boot ||
goto start

:config
config
goto start

:shell
echo Type 'exit' to get back to the menu
shell
goto start

:disk
# Boot the first local HDD
sanboot --no-describe --drive 0x80 || goto failed

:exit
exit 1

:cancel
echo You cancelled the menu, dropping to a shell
goto shell

:failed
echo Booting failed, dropping to a shell
goto shell
EOF
	if ! grep -q main-server $tftpdir/ltsp/ltsp.ipxe ; then
		cat $menufile >> $tftpdir/ltsp/ltsp.ipxe
	fi
fi

# Insert other Debian-Installer versions, if any.
if [ "${dist_version}" != "${di_versions_supported}" ]; then
	# We have more D-I netboot versions installed, so inject them into the iPXE boot menu
	for di_ver in ${di_versions_supported}; do
		for arch in ${archs}; do
			if [ "${di_ver}" = "${dist_version}" ]; then
				# we already have this, see above
				:
			else
				if [ -d $tftpdir/debian-installer/${di_ver}/${arch} ]; then
					sed -i "/^# END: Debian-Installer other versions/i \
item ${arch}_${di_ver}         Install Debian Edu ${di_ver} / ${arch}\
" ${tftpdir}/ltsp/ltsp.ipxe
				fi
			fi
		done
	done
else
	sed -E -i "${tftpdir}/ltsp/ltsp.ipxe" -e "/# (BEGIN|END): Debian-Installer other versions/d"
fi
