#!/bin/sh

set -e
set -x

if ! [ -r /etc/openstack-cluster-installer/openstack-cluster-installer.conf ] ; then
	echo "Could not load /etc/openstack-cluster-installer/openstack-cluster-installer.conf"
	echo "Copy it from your OCI install if you're trying to build a foreign arch live image."
	exit 1
else
	TMPFILE=$(mktemp -t openstack-cluster-installer.XXXXXX)
	cat /etc/openstack-cluster-installer/openstack-cluster-installer.conf | grep -v '^\[' | sed 's/^\([A-Za-z_][A-Za-z0-9_]*\)=\([^"].*\)$/\1="\2"/' >${TMPFILE}
	. ${TMPFILE}
	rm ${TMPFILE}
fi

if [ -x ./openstack-cluster-installer-build-live-image-clean ] ; then
	./openstack-cluster-installer-build-live-image-clean
else
	openstack-cluster-installer-build-live-image-clean
fi

if ! [ -r /usr/share/openstack-pkg-tools/pkgos_func ] ; then
	echo "Could not read /usr/share/openstack-pkg-tools/pkgos_func."
	exit 1
fi
. /usr/share/openstack-pkg-tools/pkgos_func

ARCH=$(uname -m)

for i in $@ ; do
	case "${1}" in
	"--pxe-server-ip")
		if [ -z "${2}" ] ; then echo "Parameter for option --pxe-server-ip is missing" > /dev/stderr ; DO_EXIT="yes" ; fi
		OTCI_PXE_SERVER_IP=${2}
		shift
		shift
		;;
	"--debian-mirror-addr")
		if [ -z "${2}" ] ; then echo "Parameter for option --debian-mirror-addr is missing" > /dev/stderr ; DO_EXIT="yes" ; fi
		OTCI_DEB_MIRROR_ADDR=${2}
		shift
		shift
		;;
	"--debian-security-mirror-addr")
		if [ -z "${2}" ] ; then echo "Parameter for option --debian-mirror-addr is missing" > /dev/stderr ; DO_EXIT="yes" ; fi
		OTCI_DEB_SECURITY_MIRROR_ADDR=${2}
		shift
		shift
	;;
	*)
		;;
	esac
done

if [ -z "${OTCI_PXE_SERVER_IP}" ] ; then
	DEFROUTE_IF=`awk '{ if ( $2 == "00000000" ) print $1 }' /proc/net/route`
	if [ -n "${DEFROUTE_IF}" ] ; then
		if [ -x /bin/ip ] ; then
			DEFROUTE_IP=`LC_ALL=C ip addr show "${DEFROUTE_IF}" | grep inet | head -n 1 | awk '{print $2}' | cut -d/ -f1 | grep -E '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'`
		else
			DEFROUTE_IP=`hostname -i | grep -E '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'`
		fi
	fi
	if [ -n "${DEFROUTE_IP}" ] ; then
		OTCI_PXE_SERVER_IP=${DEFROUTE_IP}
	else
		OTCI_PXE_SERVER_IP=$(ipcalc ${OPENSTACK_CLUSTER_NETWORK} | grep HostMin | awk '{print $2}')
	fi
        echo "No --pxe-server-ip given, using ${OTCI_PXE_SERVER_IP} as default." > /dev/stderr
        OTCI_PXE_SERVER_IP=${OTCI_PXE_SERVER_IP}
fi

if [ -z "${OTCI_DEB_MIRROR_ADDR}" ] ; then
	echo "No Debian mirror address given, using ${debian_mirror} as default."
	OTCI_DEB_MIRROR_ADDR=${debian_mirror}
fi
if [ -z "${OTCI_DEB_SECURITY_MIRROR_ADDR}" ] ; then
	echo "No security mriror address given, using ${debian_security_mirror} as default."
	OTCI_DEB_SECURITY_MIRROR_ADDR=${debian_security_mirror}
fi

if [ "${DO_EXIT}" = "yes" ] ; then
	echo "Parameters not validated: will exit now!" > /dev/stderr
	echo "Example call: $0 --pxe-server-ip ${OTCI_PXE_SERVER_IP} --debian-mirror-addr http://${OTCI_PXE_SERVER_IP}:9999/debian" > /dev/stderr
	exit 1
fi

##################################################################
### Create the SSH root ca for signing the live image host key ###
##################################################################
# Create the ssh CA key, which we push into the image, so the
# image can sign host keys on boot. This isn't very safe to do
# that, but that's still safer than randomly trusting SSH host keys
# of new machines.
mkdir -p /etc/openstack-cluster-installer/live-image-ssh-host-key
if ! [ -e /etc/openstack-cluster-installer/live-image-ssh-host-key/ca ] ; then
	ssh-keygen -P '' -f /etc/openstack-cluster-installer/live-image-ssh-host-key/ca
fi
# Make sure that the ca.pub is in OCI's /etc/ssh/ssh_known_hosts
CA_PUBKEY_CONTENT=$(cat /etc/openstack-cluster-installer/live-image-ssh-host-key/ca.pub)
if ! grep -q "${CA_PUBKEY_CONTENT}" /etc/ssh/ssh_known_hosts ; then
	echo "@cert-authority * ${CA_PUBKEY_CONTENT}" >>/etc/ssh/ssh_known_hosts
fi
# Push the CA key-pair in the live image, so that it can be used
# to sign the host key at boot time.
mkdir -p config/includes.chroot/root/ssh-ca
cp /etc/openstack-cluster-installer/live-image-ssh-host-key/ca config/includes.chroot/root/ssh-ca
cp /etc/openstack-cluster-installer/live-image-ssh-host-key/ca.pub config/includes.chroot/root/ssh-ca

########################################################
### Manage the ssh authorized_keys of the live image ###
########################################################
if [ -e /etc/openstack-cluster-installer/id_rsa.pub ] ; then
	echo "Will use existing /etc/openstack-cluster-installer/id_rsa.pub file"
else
	echo "No ssh key found, generating one"
	ssh-keygen -b 4096 -t rsa -f /etc/openstack-cluster-installer/id_rsa -q -N ""
fi
# If there's no /etc/openstack-cluster-installer/authorized_keys, then
# we create one with the OCI public key, and what's already in
# /root/.ssh/authorized_keys
if ! [ -e /etc/openstack-cluster-installer/authorized_keys ] ; then
	cat /etc/openstack-cluster-installer/id_rsa.pub >/etc/openstack-cluster-installer/authorized_keys
	if [ -e /root/.ssh/authorized_keys ] ; then
		cat /root/.ssh/authorized_keys >>/etc/openstack-cluster-installer/authorized_keys
	fi
	chown www-data:www-data /etc/openstack-cluster-installer/id_rsa*
fi


# Copy the configured /root/.ssh/authorized_keys in the live image
mkdir -p config/includes.chroot/root/.ssh/
chmod 700 config/includes.chroot/root/.ssh/
cp /etc/openstack-cluster-installer/authorized_keys config/includes.chroot/root/.ssh/authorized_keys
chmod 600 config/includes.chroot/root/.ssh/authorized_keys

# OCI_LIVE_PACKAGE_LIST is the union of the live_package_list
# directives of all the repository templates installed in the live
# system.
OCI_LIVE_PACKAGE_LIST=""

#######################################################
### Configure the default Debian repos in the image ###
#######################################################
# Add our repository with updated openstack-debian-images and lshw
mkdir -p config/archives/
##########################################
### Install the repositories templates ###
##########################################
# Everything under /etc/openstack-cluster-installer/repos/<family> is
# now data-driven: the .sources template, the GPG key and the pinning
# file of a repository folder are all optional, and the code adapts to
# what is present. Only the folders activated with the
# install_repo_in_live directive of their repo.conf are installed in
# the live system.
# The precedence of a repository folder when two folders write the
# same deb822 file: a folder named after the distribution being
# built (eg: bullseye-security) wins over an unrestricted one (eg:
# security).
live_repo_precedence () {
	case $1 in
	${debian_release}-*)
		echo 2
	;;
	*)
		echo 1
	;;
	esac
}

# The deb822 file a repository folder writes in the live image: the
# filename directive of repo.conf wins, otherwise the name is
# derived from the family and the folder name.
live_repo_sources_target () {
	R=$1
	FAMILY=$2
	REPO_DIR=$3
	pkgos_inifile get ${R}/repo.conf DEFAULT filename
	if [ "${RET}" != "NOT_FOUND" ] && [ -n "${RET}" ] ; then
		echo ${RET}
		return 0
	fi
	case "${FAMILY}" in
	debian)
		case "${REPO_DIR}" in
		base)
			echo debian.sources
		;;
		security)
			echo debian-security.sources
		;;
		backports)
			echo debian-backports.sources
		;;
		incoming)
			echo debian-incoming.sources
		;;
		*)
			echo oci-debian-${REPO_DIR}.sources
		;;
		esac
	;;
	vendors)
		echo oci-vendor-${REPO_DIR}.sources
	;;
	*)
		echo oci-${FAMILY}-${REPO_DIR}.sources
	;;
	esac
}

install_live_repos () {
	FAMILY=$1
	OCI_FAMILY_INSTALLED=no
	REPOS_DIR=/etc/openstack-cluster-installer/repos/${FAMILY}
	if ! [ -d ${REPOS_DIR} ] ; then
		return 0
	fi
	mkdir -p config/includes.chroot/etc/apt/sources.list.d
#	mkdir -p config/includes.binary/etc/apt/sources.list.d
	mkdir -p config/includes.chroot/etc/apt/keyrings
#	mkdir -p config/includes.binary/etc/apt/keyrings
	mkdir -p config/includes.chroot/etc/apt/preferences.d
#	mkdir -p config/includes.binary/etc/apt/preferences.d
	# First pass: apply the activation gates, then keep, for each
	# deb822 file, the most specific matching folder, so that two
	# repository folders never fight over the same file.
	SELECT_FILE=$(mktemp)
	for REPO_DIR in $(ls -1 ${REPOS_DIR}) ; do
		R=${REPOS_DIR}/${REPO_DIR}
		if ! [ -d ${R} ] ; then
			continue
		fi
		if ! [ -e ${R}/repo.conf ] ; then
			continue
		fi
		# Activation check: install_repo_in_live defaults to no.
		pkgos_inifile get ${R}/repo.conf DEFAULT install_repo_in_live
		case "${RET}" in
		yes|1|true|on)
			:
		;;
		*)
			continue
		;;
		esac
		# Codename gate: the repository may be restricted to some
		# distributions.
		pkgos_inifile get ${R}/repo.conf DEFAULT supported_codename
		if [ "${RET}" != "NOT_FOUND" ] && [ -n "${RET}" ] ; then
			found_codename=no
			for c in $(echo ${RET} | sed 's/,/ /g') ; do
				if [ "$c" = "${debian_release}" ] ; then
					found_codename=yes
				fi
			done
			if [ "${found_codename}" = "no" ] ; then
				continue
			fi
		fi
		# Deny-list gate: the repository may also be disabled on
		# some distributions.
		pkgos_inifile get ${R}/repo.conf DEFAULT unsupported_codename
		if [ "${RET}" != "NOT_FOUND" ] && [ -n "${RET}" ] ; then
			for c in $(echo ${RET} | sed 's/,/ /g') ; do
				if [ "$c" = "${debian_release}" ] ; then
					continue 2
				fi
			done
		fi
		# Architecture gate.
		pkgos_inifile get ${R}/repo.conf DEFAULT supported_arch
		if [ "${RET}" != "NOT_FOUND" ] && [ -n "${RET}" ] ; then
			found_arch=no
			for a in $(echo ${RET} | sed 's/,/ /g') ; do
				if [ "$a" = "${ARCH}" ] ; then
					found_arch=yes
				fi
			done
			if [ "${found_arch}" = "no" ] ; then
				continue
			fi
		fi
		# Machine role gate: the live system has no machine role,
		# so role specific repositories never land in it.
		pkgos_inifile get ${R}/repo.conf DEFAULT supported_role
		if [ "${RET}" != "NOT_FOUND" ] && [ -n "${RET}" ] ; then
			continue
		fi
		echo "$(live_repo_precedence ${REPO_DIR}) ${REPO_DIR} $(live_repo_sources_target ${R} ${FAMILY} ${REPO_DIR})" >>${SELECT_FILE}
	done
	WINNERS=$(sort -k3,3 -k1,1nr ${SELECT_FILE} | awk '!seen[$3]++ { print $2 }')
	rm -f ${SELECT_FILE}
	# Second pass: the winners only.
	for REPO_DIR in ${WINNERS} ; do
		R=${REPOS_DIR}/${REPO_DIR}
		OCI_FAMILY_INSTALLED=yes
		# GPG key.
		for KEY in ${R}/*.asc ; do
			if [ -e "$KEY" ] ; then
				cp $KEY config/includes.chroot/etc/apt/keyrings/oci-${FAMILY}-${REPO_DIR}.asc
			fi
		done
		# Pinning file.
		if [ -e ${R}/repo.pref ] ; then
			case "${FAMILY}" in
			vendors)
				cp ${R}/repo.pref config/includes.chroot/etc/apt/preferences.d/oci-vendor-${REPO_DIR}.pref
			;;
			*)
				cp ${R}/repo.pref config/includes.chroot/etc/apt/preferences.d/oci-${FAMILY}-${REPO_DIR}.pref
			;;
			esac
		fi
		# Sources template, with its tokens.
		if [ -e ${R}/repo.sources ] ; then
			SOURCES_TARGET=$(live_repo_sources_target ${R} ${FAMILY} ${REPO_DIR})
			SOURCES_FILE=config/includes.chroot/etc/apt/sources.list.d/${SOURCES_TARGET}
			cp ${R}/repo.sources ${SOURCES_FILE}
			sed -i "s#%%OS_VERSION%%#${debian_release}#g; s#%%OPENSTACK_RELEASE%%#${openstack_release}#g" ${SOURCES_FILE}
			# Resolve the remaining tokens: first from the [<codename>]
			# section of repo.conf, then from the [repo_tokens] section
			# of openstack-cluster-installer.conf, then from the
			# [DEFAULT] section of repo.conf, and finally from the
			# server side values. A token which cannot be resolved at
			# all makes the .sources file invalid: skip the folder.
			for TOKEN in $(grep -o '%%[A-Za-z0-9_]*%%' ${SOURCES_FILE} | sort -u | sed 's/%%//g') ; do
				pkgos_inifile get ${R}/repo.conf ${debian_release} ${TOKEN}
				if [ "${RET}" = "NOT_FOUND" ] || [ -z "${RET}" ] ; then
				case ${TOKEN} in
				OPENSTACK_RELEASE) RET="" ;;
				*) pkgos_inifile get /etc/openstack-cluster-installer/openstack-cluster-installer.conf repo_tokens ${TOKEN} ;;
				esac
				fi
				if [ "${RET}" = "NOT_FOUND" ] || [ -z "${RET}" ] ; then
					pkgos_inifile get ${R}/repo.conf DEFAULT ${TOKEN}
				fi
				if [ "${RET}" = "NOT_FOUND" ] || [ -z "${RET}" ] ; then
					case ${TOKEN} in
					DEBIAN_MIRROR) RET=${debian_mirror} ;;
					DEBIAN_SECURITY_MIRROR) RET=${debian_security_mirror} ;;
					DEBIAN_BACKPORT_MIRROR) RET=${official_backports_repo_url} ;;
					DEBIAN_INCOMING_BUILDD) RET=${debian_incoming_buildd} ;;
					esac
				fi
				if [ "${RET}" = "NOT_FOUND" ] || [ -z "${RET}" ] ; then
					echo "? Could not resolve %%${TOKEN}%% of ${FAMILY}/${REPO_DIR}: skipping the folder."
					rm -f ${SOURCES_FILE} config/includes.chroot/etc/apt/keyrings/oci-${FAMILY}-${REPO_DIR}.asc
					case "${FAMILY}" in
					vendors)
						rm -f config/includes.chroot/etc/apt/preferences.d/oci-vendor-${REPO_DIR}.pref
					;;
					*)
						rm -f config/includes.chroot/etc/apt/preferences.d/oci-${FAMILY}-${REPO_DIR}.pref
					;;
					esac
					continue 2
				fi
				sed -i "s#%%${TOKEN}%%#${RET}#g" ${SOURCES_FILE}
			done
		fi
		# Packages from this repository to install in the live system.
		pkgos_inifile get ${R}/repo.conf DEFAULT live_package_list
		if [ "${RET}" != "NOT_FOUND" ] && [ -n "${RET}" ] ; then
			OCI_LIVE_PACKAGE_LIST="${OCI_LIVE_PACKAGE_LIST} $(echo ${RET} | sed 's/,/ /g')"
		fi
	done
}

# The osbpo.debian.net repository, and its optional add-ons.
install_live_repos osbpo

# The official Debian repositories.
install_live_repos debian

# Install keyring, if configured
if [ -n "${debian_keyring_package}" ]; then
	cd config/archives
	apt-get download ${debian_keyring_package}
	cd ../..
fi

# Add the IP of the PXE server in a configuration file
# for later use during the install process
mkdir -p config/includes.chroot/etc/oci
echo ${OTCI_PXE_SERVER_IP} >config/includes.chroot/etc/oci/pxe-server-ip

echo ${openstack_release} >config/includes.chroot/etc/oci_openstack_release
echo ${debian_release} >config/includes.chroot/etc/oci_debian_release

echo ${production_system_setup_backports_repo} >config/includes.chroot/etc/oci/production_system_setup_backports_repo
echo ${production_system_setup_nonfree_repo} >config/includes.chroot/etc/oci/production_system_setup_nonfree_repo
echo ${production_system_install_nonfree_firmware_from_backports} >config/includes.chroot/etc/oci/production_system_install_nonfree_firmware_from_backports
echo ${production_system_install_firmware_from_backports_list} >config/includes.chroot/etc/oci/production_system_install_firmware_from_backports_list

############################################################
### Customize the PXE Linux splash screen with OCI's svg ###
############################################################
cp -auxf /usr/share/live/build/bootloaders config/
cp /usr/share/openstack-cluster-installer/splash.svg config/bootloaders/extlinux
cp /usr/share/openstack-cluster-installer/splash.svg config/bootloaders/grub-legacy
cp /usr/share/openstack-cluster-installer/splash.svg config/bootloaders/grub-pc
cp /usr/share/openstack-cluster-installer/splash.svg config/bootloaders/isolinux
cp /usr/share/openstack-cluster-installer/splash.svg config/bootloaders/pxelinux
cp /usr/share/openstack-cluster-installer/splash.svg config/bootloaders/syslinux

# Customize root and user ~/.screenrc
mkdir -p config/includes.chroot/root
echo "startup_message off
defscrollback 5000
caption always \"%{= kw}%-w%{= BW}%n %t%{-}%+w %-= @%H  -  %d.%m.%Y  - %c\"
termcapinfo xterm 'Co#256:AB=\E[48;5;%dm:AF=\E[38;5;%dm'
defbce on
term screen-256color
termcapinfo konsole-256color ti@:te@" >config/includes.chroot/root/.screenrc

mkdir -p config/includes.chroot/home/user
echo "startup_message off
defscrollback 5000
caption always \"%{= kw}%-w%{= BW}%n %t%{-}%+w %-= @%H  -  %d.%m.%Y  - %c\"
termcapinfo xterm 'Co#256:AB=\E[48;5;%dm:AF=\E[38;5;%dm'
defbce on
term screen-256color
termcapinfo konsole-256color ti@:te@" >config/includes.chroot/home/user/.screenrc

# and /root/.bashrc and /home/user/.bashrc
echo "# ~/.bashrc: executed by bash(1) for non-login shells.

export LS_OPTIONS='--color=auto'
eval \"\$(dircolors)\"
alias ls='ls \${LS_OPTIONS}'

SYSTEM_SERIAL_NUM=\$(oci-system-serial)

  BLUE=\"\\[\\033[1;34m\\]\"
 LGRAY=\"\\[\\033[0;37m\\]\"
NO_COL=\"\\[\\033[0m\\]\"
 LBLUE=\"\\[\\033[1;36m\\]\"
   RED=\"\\[\\033[1;31m\\]\"

export PS1=\${RED}'\\u'\${LGRAY}@\${BLUE}\${SYSTEM_SERIAL_NUM}\${LGRAY}'>_'\${NO_COL}' \\w # '

alias ssh='ssh -A -X'

if [ -f /etc/bash_completion ]; then
	. /etc/bash_completion
fi

export PAGER=most
" > config/includes.chroot/root/.bashrc

echo "HISTCONTROL=ignoreboth
shopt -s histappend
HISTSIZE=1000
HISTFILESIZE=2000
shopt -s checkwinsize

export LS_OPTIONS='--color=auto'
eval \"\$(dircolors)\"
alias ls='ls \${LS_OPTIONS}'

SYSTEM_SERIAL_NUM=\$(oci-system-serial)

  BLUE=\"\\[\\033[1;34m\\]\"
 LGRAY=\"\\[\\033[0;37m\\]\"
NO_COL=\"\\[\\033[0m\\]\"
 LBLUE=\"\\[\\033[1;36m\\]\"
   RED=\"\\[\\033[1;31m\\]\"
 GREEN=\"\\[\\033[1;32m\\]\"
export PS1=\${GREEN}'\\u'\${LGRAY}@\${BLUE}\${SYSTEM_SERIAL_NUM}\${LGRAY}'>_'\${NO_COL}' \\w # '
export PAGER=most
" >config/includes.chroot/home/user/.bashrc

mkdir -p config/includes.chroot/etc/network
echo "auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp" >config/includes.chroot/etc/network/interfaces

######################################
### Install vendor repository list ###
######################################
# The hardware vendor repositories.
install_live_repos vendors

# All the packages of the live image are installed from this hook,
# once the deb822 repository templates are in place in the chroot, so
# that apt sees all the repositories the templates manage (eg: the
# non-free firmware). The packages are expanded here, at hook
# generation time, on a single apt-get command line.
OCI_LIVE_ALL_PACKAGES="${OCI_LIVE_PACKAGE_LIST} bash-completion bc bind9-host curl dmidecode debootstrap dosfstools firmware-linux-free firmware-misc-nonfree gnupg2 ipcalc ipmitool iproute2 joe jq kbd kpartx lldpd less lshw lvm2 mbr mdadm most net-tools nmap openssh-server openssh-client openstack-cluster-installer-agent openstack-debian-images openstack-pkg-tools parted pciutils plymouth qemu-utils screen syslinux-common tcpdump util-linux vim wget xfsprogs kbuild dkms libpcap-dev mstflint"

if [ "${ARCH}" = "aarch64" ] ; then
	OCI_LIVE_ALL_PACKAGES="${OCI_LIVE_ALL_PACKAGES} linux-headers-arm64 firmware-qlogic"
else
	OCI_LIVE_ALL_PACKAGES="${OCI_LIVE_ALL_PACKAGES} linux-headers-amd64 extlinux firmware-bnx2 firmware-bnx2x firmware-qlogic"
	if [ ${debian_release} != "buster" ] && [ ${debian_release} != "bullseye" ] ; then
		OCI_LIVE_ALL_PACKAGES="${OCI_LIVE_ALL_PACKAGES} ilorest"
	fi
fi

mkdir -p config/hooks/live
echo "#!/bin/sh
set -e

# The live image's base and updates sources are managed by
# live-build's own classic /etc/apt/sources.list: it stays in
# place. The deb822 repository templates manage everything it
# doesn't cover (the security suite, backports, the osbpo and
# vendor repositories), so apt sees all of them without any
# duplication.
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get install -y --allow-downgrades ${OCI_LIVE_ALL_PACKAGES}
DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y -o Dpkg::Options::=--force-confold --allow-downgrades
" >config/hooks/live/install-osbpo.hook.chroot
chmod +x config/hooks/live/install-osbpo.hook.chroot


##################################################
### Install vendor packages in the live distro ###
##################################################

#############################
### Set HTTP proxy config ###
#############################
pkgos_inifile get /etc/openstack-cluster-installer/openstack-cluster-installer.conf network USE_HTTP_PROXY
USE_HTTP_PROXY=$RET
if [ "${USE_HTTP_PROXY}" = "yes" ] ; then
	pkgos_inifile get /etc/openstack-cluster-installer/openstack-cluster-installer.conf network HTTP_PROXY_ADDR
	mkdir -p config/includes.chroot/etc/oci
	echo $RET >config/includes.chroot/etc/oci/http_proxy_addr
fi

##########################
### Add serial console ###
##########################
mkdir -p config/includes.chroot/etc/systemd/system/getty.target.wants
echo "#  SPDX-License-Identifier: LGPL-2.1+
#
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Serial Getty on %I
Documentation=man:agetty(8) man:systemd-getty-generator(8)
Documentation=http://0pointer.de/blog/projects/serial-console.html
BindsTo=dev-%i.device
After=dev-%i.device systemd-user-sessions.service plymouth-quit-wait.service getty-pre.target
After=rc-local.service

# If additional gettys are spawned during boot then we should make
# sure that this is synchronized before getty.target, even though
# getty.target didn't actually pull it in.
Before=getty.target
IgnoreOnIsolate=yes

# IgnoreOnIsolate causes issues with sulogin, if someone isolates
# rescue.target or starts rescue.service from multi-user.target or
# graphical.target.
Conflicts=rescue.service
Before=rescue.service

[Service]
# The '-o' option value tells agetty to replace 'login' arguments with an
# option to preserve environment (-p), followed by '--' for safety, and then
# the entered username.
ExecStart=-/sbin/agetty --autologin root --keep-baud 9600 %I \$TERM
Type=idle
Restart=always
UtmpIdentifier=%I
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes

[Install]
WantedBy=getty.target
" >config/includes.chroot/etc/systemd/system/serial-getty@ttyS1.service
cp config/includes.chroot/etc/systemd/system/serial-getty@ttyS1.service config/includes.chroot/etc/systemd/system/serial-getty@ttyS0.service
ln -s ../serial-getty@ttyS1.service config/includes.chroot/etc/systemd/system/getty.target.wants/serial-getty@ttyS1.service
ln -s ../serial-getty@ttyS0.service config/includes.chroot/etc/systemd/system/getty.target.wants/serial-getty@ttyS0.service

# Configure autologin for tty0
mkdir -p config/includes.chroot/etc/systemd/system/getty@.service.d
echo "[Service]\nExecStart=\nExecStart=-/sbin/agetty --autologin root --noclear %I \$TERM" >config/includes.chroot/etc/systemd/system/getty@.service.d/root-autologin.conf

# Copy the customization by the user
if [ -d /etc/openstack-cluster-installer/live-image-additions ] ; then
	if [ -n "$(ls /etc/openstack-cluster-installer/live-image-additions)" ] ; then
		if [ -r /etc/openstack-cluster-installer/oci-firmware-upgrade-config.json ] ; then
			mkdir -p config/includes.chroot/etc/oci
			cp /etc/openstack-cluster-installer/oci-firmware-upgrade-config.json config/includes.chroot/etc/oci/
			cp -auxf /etc/openstack-cluster-installer/live-image-additions/* config/includes.chroot/
		fi
	fi
fi
	
# Configure debootstrap to trust our archive keyring
if [ -n "${debian_keyring_file}" ]; then
	export DEBOOTSTRAP_OPTIONS="${DEBOOTSTRAP_OPTIONS} --keyring=${debian_keyring_file}"
fi

lb clean
# Let live-build out of the security suite management: the repository
# templates manage it (deb822 files, shipped in the squashfs), and
# live-build's own security line in the classic sources.list conflicts
# with any deb822 stanza carrying the Check-Valid-Until option (eg: the
# bullseye-security take-over).
lb config --mirror-binary http://${OTCI_PXE_SERVER_IP}:9999/debian --security false -b netboot --bootappend-live "boot=live iomem=relaxed console=tty0 console=ttyS0,115200 console=ttyS1,115200 earlyprintk=ttyS1,115200 consoleblank=0 systemd.show_status=true components url=http://${OTCI_PXE_SERVER_IP} fetch=http://${OTCI_PXE_SERVER_IP}/openstack-cluster-installer/filesystem.squashfs" --net-root-path /var/lib/openstack-cluster-installer --net-root-server ${OTCI_PXE_SERVER_IP}

# Change the default mirror in the config
if [ -n "${OTCI_DEB_MIRROR_ADDR}" ] ; then
	for i in LB_PARENT_MIRROR_BOOTSTRAP LB_PARENT_MIRROR_CHROOT LB_PARENT_MIRROR_DEBIAN_INSTALLER LB_MIRROR_BOOTSTRAP LB_MIRROR_CHROOT LB_MIRROR_DEBIAN_INSTALLER \
		LB_PARENT_MIRROR_BINARY LB_MIRROR_BINARY ; do
		sed -i 's|^'${i}'=.*|'${i}'="'${OTCI_DEB_MIRROR_ADDR}'"|' config/bootstrap
	done
fi

sed -i 's/^LB_BOOTLOADERS=.*/LB_BOOTLOADERS="syslinux"/' config/binary

# Fix the default syslinux timeout to 20 seconds
sed -i "s/timeout 0/timeout 20/" config/bootloaders/isolinux/isolinux.cfg
sed -i "s/timeout 0/timeout 20/" config/bootloaders/pxelinux/pxelinux.cfg/default
sed -i "s/timeout 0/timeout 20/" config/bootloaders/syslinux/syslinux.cfg
sed -i "s/timeout 0/timeout 20/" config/bootloaders/extlinux/extlinux.conf

sed -i s/ftp.debian.org/${OTCI_PXE_SERVER_IP}:9999/ config/bootstrap

# Customize the distribution name
sed -i "s#LB_DEBIAN_INSTALLER_DISTRIBUTION=.*#LB_DEBIAN_INSTALLER_DISTRIBUTION=\"${debian_release}\"#" config/binary
sed -i "s#LB_ISO_VOLUME=.*#LB_ISO_VOLUME=\"Debian ${debian_release} \$(date +%Y%m%d-%H:%M)\"#" config/binary
if [ -e config/build ] ; then
	sed -i "s#Distribution: .*#Distribution: ${debian_release}#" config/build
fi
sed -i "s#LB_DISTRIBUTION=.*#LB_DISTRIBUTION=\"${debian_release}\"#" config/bootstrap
sed -i "s#LB_PARENT_DISTRIBUTION=.*#LB_PARENT_DISTRIBUTION=\"${debian_release}\"#" config/bootstrap
sed -i "s#LB_PARENT_DEBIAN_INSTALLER_DISTRIBUTION=.*#LB_PARENT_DEBIAN_INSTALLER_DISTRIBUTION=\"${debian_release}\"#" config/bootstrap

# New names to tweak starting with Bullseye
sed -i "s#LB_DISTRIBUTION_CHROOT=.*#LB_DISTRIBUTION_CHROOT=\"${debian_release}\"#" config/bootstrap
sed -i "s#LB_PARENT_DISTRIBUTION_CHROOT=.*#LB_PARENT_DISTRIBUTION_CHROOT=\"${debian_release}\"#" config/bootstrap
sed -i "s#LB_DISTRIBUTION_BINARY=.*#LB_DISTRIBUTION_BINARY=\"${debian_release}\"#" config/bootstrap
sed -i "s#LB_PARENT_DISTRIBUTION_BINARY=.*#LB_PARENT_DISTRIBUTION_BINARY=\"${debian_release}\"#" config/bootstrap

# Sid has no updates suite
if [ "${debian_release}" = "sid" ] ; then
	sed -i "s#LB_UPDATES=.*#LB_UPDATES=\"false\"#" config/chroot
fi

lb build

# Copy the tftp stuff
mkdir -p /var/lib/openstack-cluster-installer/tftp
cp -r tftpboot/* /var/lib/openstack-cluster-installer/tftp
mkdir -p /var/lib/openstack-cluster-installer/tftp/live
cp -auxf tftpboot/live/vmlinuz* tftpboot/live/initrd* /var/lib/openstack-cluster-installer/tftp/live
cp binary/live/filesystem.squashfs /var/lib/openstack-cluster-installer

# Copy it also to the web path, so it works over iPXE
mkdir -p /usr/share/openstack-cluster-installer/live
cp -auxf tftpboot/live/vmlinuz* tftpboot/live/initrd* /usr/share/openstack-cluster-installer/live

# Add the UEFI files
mkdir -p /var/lib/openstack-cluster-installer/tftp/efi64
cp /usr/lib/ipxe/undionly.kpxe /usr/share/openstack-cluster-installer/
if [ -d /usr/lib/SYSLINUX.EFI/efi64 ] ; then
	cp /usr/lib/SYSLINUX.EFI/efi64/* /var/lib/openstack-cluster-installer/tftp/efi64
fi
if [ -d /usr/lib/syslinux/modules/efi64 ] ; then
	cp /usr/lib/syslinux/modules/efi64/* /var/lib/openstack-cluster-installer/tftp/efi64
fi

# Create the ipxe-boot-script, needed for ipxe support.
echo "#!ipxe

chain tftp://${OTCI_PXE_SERVER_IP}/lpxelinux.0
" > /var/lib/openstack-cluster-installer/tftp/ipxe-boot-script

cp /usr/lib/PXELINUX/lpxelinux.0 /var/lib/openstack-cluster-installer/tftp

##############################################
### Grub + SHIM install in the TFTP folder ###
##############################################
# Copy shim + grub, so we can support secure boot.
# Note: these files aren't available in all arch,
# so this must be conditional copies.
if [ -e /usr/lib/shim/shimx64.efi.signed ] ; then
	cp /usr/lib/shim/shimx64.efi.signed /var/lib/openstack-cluster-installer/tftp/
fi
if [ -e /usr/lib/grub/x86_64-efi-signed/grubnetx64.efi.signed ] ; then
	cp /usr/lib/grub/x86_64-efi-signed/grubnetx64.efi.signed /var/lib/openstack-cluster-installer/tftp/grubx64.efi
fi

mkdir -p /var/lib/openstack-cluster-installer/tftp/grub
for i in http smbios serial ; do
	if [ -e /usr/lib/grub/x86_64-efi/${i}.mod ] ; then
		mkdir -p /var/lib/openstack-cluster-installer/tftp/grub/x86_64-efi
		cp /usr/lib/grub/x86_64-efi/${i}.mod /var/lib/openstack-cluster-installer/tftp/grub/x86_64-efi/
	fi
done

# smbios.system.vendor → manufacturer (e.g. "Dell Inc.")
# smbios.system.product → product name/model
# smbios.system.version → system version string
# smbios.bios.vendor → BIOS vendor
# smbios.bios.version → BIOS version
echo "set menu_color_normal=white/black
set menu_color_highlight=black/light-gray
set timeout=5

insmod serial
if [ \$grub_cpu = x86_64 ]; then
	insmod smbios
	if [ \$smbios_system_vendor = \"Dell Inc.\" ]; then
		boot_console=\"ttyS1\"
		grub_ttys_console=\"1\"
	else
		boot_console=\"ttyS0\"
		grub_ttys_console=\"0\"
	fi
	serial --unit=\${grub_ttys_console} --speed=115200 --word=8 --parity=no --stop=1
else
	boot_console=\"ttyAMA0\"
	serial --speed=115200 --word=8 --parity=no --stop=1
fi
terminal_input console serial
terminal_output console serial


if [ \$grub_cpu = x86_64 ]; then
	menuentry \"OpenStack cluster installer\" {
	    linux    live/vmlinuz boot=live iomem=relaxed console=tty0 console=\${boot_console},115200n8 earlyprintk=\${boot_console},115200 consoleblank=0 systemd.show_status=true components url=http://${OTCI_PXE_SERVER_IP} fetch=http://${OTCI_PXE_SERVER_IP}/openstack-cluster-installer/filesystem.squashfs iommu=pt
	    initrd   live/initrd.img
	}
elif [ \$grub_cpu = arm64 ]; then
	menuentry \"OpenStack cluster installer\" {
	    linux    live/vmlinuz-arm64 boot=live iomem=relaxed console=tty0 console=\${boot_console},115200n8 earlyprintk=\${boot_console},115200 consoleblank=0 systemd.show_status=true components url=http://${OTCI_PXE_SERVER_IP} fetch=http://${OTCI_PXE_SERVER_IP}/openstack-cluster-installer/filesystem_arm64.squashfs
	    initrd   live/initrd-arm64.img
	}
fi

menuentry \"UEFI Firmware Settings\" { fwsetup }
menuentry \"Reboot\" { reboot }
menuentry \"Shutdown\" { halt }
" >/var/lib/openstack-cluster-installer/tftp/grub/grub.cfg

###############################################################################
### Customization of syslinux to load the kernel over http rather than tftp ###
###############################################################################
# Patch live.cfg so that it uses http instead of tftp for loading the
# kernel and initrd, which is much faster.

# No PXELINUX in arm64, so no live.cfg
if [ "${ARCH}" != "aarch64" ] ; then
	sed -i 's#linux /live/vmlinuz#linux http://'${OTCI_PXE_SERVER_IP}'/openstack-cluster-installer/tftp/live/vmlinuz#' /var/lib/openstack-cluster-installer/tftp/live.cfg
	sed -i 's#initrd /live/initrd.img#initrd http://'${OTCI_PXE_SERVER_IP}'/openstack-cluster-installer/tftp/live/initrd.img#' /var/lib/openstack-cluster-installer/tftp/live.cfg
fi

# Set the syslinux menu type.
# The menu.c32 is needed for the non-vesa menu type.
# Let's copy it in the tftp folder, always...
cp chroot/usr/lib/syslinux/modules/bios/menu.c32 /var/lib/openstack-cluster-installer/tftp

# No PXELINUX in arm64
if [ "${ARCH}" != "aarch64" ] ; then
	if [ "${force_syslinux_text_menu}" = "yes" ] ; then
		sed -i 's/default vesamenu.c32/default menu.c32/' /var/lib/openstack-cluster-installer/tftp/pxelinux.cfg/default
	else
	        sed -i 's/default menu.c32/default vesamenu.c32/' /var/lib/openstack-cluster-installer/tftp/pxelinux.cfg/default
	fi
fi

# Hack the initrd file to remove drivers
if [ "${remove_drivers_from_initrd}" = "yes" ] ; then
	TMPDIR=$(mktemp --directory)
	INITRD_PATH=/var/lib/openstack-cluster-installer/tftp/live/initrd.img
	MYCWD=$(pwd)

	cd ${TMPDIR}
	# Uncompress the initrd
	zcat ${INITRD_PATH} | cpio -idmv
	for i in ${remove_drivers_from_initrd_list} ; do
		rm lib/modules/*/kernel/drivers/net/ethernet/${i}
	done
	find . | cpio --create --format='newc' | gzip -9 >${INITRD_PATH}
	rm -rf ${TMPDIR}
	cd ${MYCWD}
fi

echo "All done, your OCI Live image is ready..."
