#!/bin/sh
# Copyright:
#   (c) 2013-2019, Thomas Goirand <zigo@debian.org>
#   (c) 2015-2016, Bastian Blank
# License: Apache 2.0, see LICENSE.txt for details.

set -e

export DEBIAN_FRONTEND=noninteractive

if [ "$UNSHARED" != true ] ; then
	exec env UNSHARED=true unshare --mount --pid --fork --mount-proc "$0" "$@"
fi

LC_ALL=C
export LC_ALL

# Parse input parameters
usage() {
	echo "Usage: $0 --release|-r <jessie|wheezy|stretch|buster|bullseye|bookworm|trixie|sid|unstable> [options]
Options are:
 --minimal|-m
 --azure|-az
 --boot-manager|-bm <grub|syslinux> (default: grub)
 --debootstrap-url|-u <debootstrap-mirror> (default: http://deb.debian.org/debian)
 --sources.list-mirror|-s <source-list-mirror> (default: http://deb.debian.org/debian)
 --extra-packages|-e <package>,<package>,...
 --rescue (implies: --permit-ssh-as-root --add-serial-getty ttyS0 --tty-autologin yes)
 --hook-script|-hs <hook-script>
 --image-size|-is <image-size> (default: 2G)
 --automatic-resize|-ar
 --automatic-resize-space|-ars <suplementary-space> (default: 50M)
 --login|-l <userlogin> (default: debian)
 --password|-p <root-password> (dangerous option: avoid it if possible)
 --boot-type|-bt <boot type> (default: mbr)
 --architecture|-a <architecture> (default: amd64)
 --dest-hdd <dest-hdd> / raid personality (ie: raid0, raid1, raid10)
 --raid-devices <sda,sdb> (only valid if --dest-hdd = raidX)
 --no-cloud-init
 --root-ssh-key <path-to-id_rsa.pub>
 --permit-ssh-as-root
 --no-remove-host-keys (no effect if not generating a VM image using --dest-hdd)
 --hostname <hostname>
 --static-iface type=<normal,bond,bondvlan,bondvlanbridge,bgp>,iface0=eth0,addr=<CIDR-address><:gateway>[,iface1=eth1][,vlannum=85][,bridgename=br85][,ovsifaces=yes][,asnum=<ASNUM>][,addbgpip=<IP>] (can be specified multiple times)
       type= Type of setup (ie: normal, bonding, binding with vlan, bonding with vlan and bridging)
     iface0= Name of the first interface.
     iface1= Name of the 2nd interface (only useful when using bridging)
       addr= Ip address in CIDR format, eventually postfixed with :gateway
    vlannum= Number of the vlan
 bridgename= Name of the bridge
        dns= Address of the DNS servers, separated by :
 dns-search= Search namespace in resolv.conf
        mtu= MTU for this network setup
      ovsbr= Name of the OVS bridge to use
 vmnet_addr= IP address of the VM trafic network
 vmnet_vlan= Number of the vlan for the VM trafic network
  extra_ovs=yes will Bridge a br-ex to the iface / bond
 --reboot-after-install
 --install-nonfree-repo (installs contrib and non-free)
 --postinstall-packages <packages> (useful for non-free/contrib)
 --security-mirror <security-mirror-url>
 --pre-reboot-hook <pre-reboot-script>
 --add-serial-getty <serial-console-dev>
 --tty-autologin <yes/no>
 --xfsformat <sda,sdb,...> will format /dev/sda and /dev/sdb in XFS (useful for Swift stores)
 --vgcreate <sda,sdb,...> will prepare /dev/sda and /dev/sdb volume group (useful for Cinder LVM volume groups)
 --no-cloud-kernel
 --generate-package-list
 --generate-source-tarball (implies --generate-package-list)
 --generate-sums
 --generate-sums-sign (implies --generate-sums)
 --grab-release-number
 --octavia-agent
 --manila-agent
 --trove-agent
 --extrepo <openstack-release>
 --newer-qemu
 --no-qcow2
 --kernel-from-backports <yes/no>
For more info: man $0

Example: build-openstack-debian-image -r buster -u http://mirror.infomaniak.com/debian -s http://mirror.infomaniak.com/debian --security-mirror http://mirror.infomaniak.com/debian-security --generate-package-list --grab-release-number --generate-source-tarball --generate-sums-sign
"
	exit 1
}

EXTRA=yes
AZURE=no
BOOTMANAGER=grub
BOOTTYPE=mbr
ARCH=amd64
REAL_HARDWARE=no
DEST_HDD=vda
CLOUD_INIT=yes
REBOOT_AFTER_INSTALL=no
INSTALL_NONFREE_REPO=no
REMOVE_HOST_KEYS=yes
SECURITY_MIRROR_URL=http://security.debian.org/debian-security
PERMIT_SSH_AS_ROOT=no
SERIAL_CONSOLE=no
XFSFORMAT=""
CLOUD_KERNEL=yes
TTY_AUTOLOGIN=no
BUILD_RESCUE_IMG=no
GRAB_RELEASE_NUMBER=no
GEN_PKG_LIST=no
GEN_SRC_TAR=no
GEN_SUMS=no
GEN_SUMS_SIGN=no
SETUP_OCTAVIA_AGENT=no
SETUP_MANILA_AGENT=no
AGENT_NAME=none
SETUP_EXTREPO=no
NEWER_QEMU=no
BUILD_QCOW2=yes
KERNEL_FROM_BACKPORTS=no
for i in $@ ; do
	case "${1}" in
	"--extra-packages"|"-e")
		if [ -z "${2}" ] ; then
			echo "No parameter defining the extra packages"
			usage
		fi
		EXTRA_PACKAGES=${2}
		shift
		shift
	;;
	"--debootstrap-url"|"-u")
		if [ -z "${2}" ] ; then
			echo "No parameter defining the debootstrap URL"
			usage
		fi
		DEB_MIRROR=${2}
		shift
		shift
	;;
	"--minimal"|"-m")
		EXTRA=no
		shift
	;;
	"--rescue")
		BUILD_RESCUE_IMG=yes
		TTY_AUTOLOGIN=yes
		PERMIT_SSH_AS_ROOT=yes
                SERIAL_CONSOLE=yes
                SERIAL_CONSOLE_DEV=ttyS0
		shift
	;;
	"--azure"|"-az")
		AZURE=yes
		shift
	;;
	"--boot-manager"|"-bm")
		if [ "${2}" != "grub" ] && [ "${2}" != "syslinux" ] ; then
			echo "No recognized parameter defining the boot manager"
			usage
		fi
		BOOTMANAGER=${2}
		shift
		shift
	;;
	"--boot-type"|"-bt")
		if [ "${2}" != "mbr" ] && [ "${2}" != "uefi" ] ; then
			echo "No recognized parameter defining the boot type"
			usage
		fi
		BOOTTYPE=${2}
		shift
		shift
	;;
	"--architecture"|"-a")
		if [ "${2}" != "amd64" ] && [ "${2}" != "arm64" ] ; then
			echo "No recognized parameter defining the architecture (currently support amd64 and arm64)"
			usage
		fi
		ARCH=${2}
		shift
		shift
	;;
	"--automatic-resize"|"-ar")
		AUTOMATIC_RESIZE=yes
		shift
	;;
	"--automatic-resize-space"|"-ars")
		if [ -z "${2}" ] ; then
			echo "No parameter defining the suplementary space"
			usage
		fi
		AUTOMATIC_RESIZE_SPACE=${2}
		shift
		shift
	;;
	"--image-size"|"-is")
		if [ -z "${2}" ] ; then
			echo "No parameter defining the image size"
			usage
		fi
		IMAGE_SIZE=${2}
		shift
		shift
	;;
	"--hook-script"|"-hs")
		if [ -z "${2}" ] ; then
			echo "No parameter defining the hook script"
			usage
		fi
		if ! [ -x "${2}" ] ; then
			echo "Hook script not executable"
		fi
		HOOK_SCRIPT=${2}
		shift
		shift
	;;
	"--sources.list-mirror"|"-s")
		if [ -z "${2}" ] ; then
			echo "No parameter defining the hook script"
			usage
		fi
		SOURCE_LIST_MIRROR=${2}
		shift
		shift
	;;
	"--release"|"-r")
		if [ "${2}" = "wheezy" ] || [ "${2}" = "jessie" ] || [ "${2}" = "stretch" ] || [ "${2}" = "buster" ] || [ "${2}" = "bullseye" ] || [ "${2}" = "bookworm" ] || [ "${2}" = "trixie" ] || [ "${2}" = "sid" ] || [ "${2}" = "unstable" ]; then
			RELEASE=${2}
			if [ "${RELEASE}" = "unstable" ] ; then
				RELEASE="sid"
			fi
			shift
			shift
		else
			echo "Release not recognized."
			usage
		fi
	;;
	"--login"|"-l")
		if [ -z "${2}" ] ; then
			echo "No parameter defining the user login"
			usage
		fi
		USER_LOGIN=${2}
		shift
		shift
	;;
	"--password"|"-p")
		if [ -z "${2}" ] ; then
			echo "No parameter defining the root password"
			usage
		fi
		ROOT_PASSWORD=${2}
		shift
		shift
	;;
	"--root-ssh-key")
		if [ -z "${2}" ] ; then
			echo "No parameter for the id_rsa.pub"
			usage
		fi
		ROOT_SSH_KEY=${2}
		shift
		shift
	;;
	"--no-remove-host-keys")
		REMOVE_HOST_KEYS=no
		shift
	;;
	"--permit-ssh-as-root")
		PERMIT_SSH_AS_ROOT=yes
		shift
	;;
	"--output"|"-o")
		if [ -z "${2}" ] ; then
			echo "No output file specified"
			usage
		fi
		OUTPUT=${2}
		shift
		shift
	;;
	"--dest-hdd")
		if [ -z "${2}" ] ; then
			echo "No dest hdd specified"
			usage
		fi
		REAL_HARDWARE=yes
		DEST_HDD=${2}
		shift
		shift
	;;
	"--raid-devices")
		if [ -z "${2}" ] ; then
			echo "No raid devices specified"
			usage
		fi
		RAID_DEVS=${2}
		shift
		shift
	;;
	"--no-cloud-init")
		CLOUD_INIT=no
		shift
	;;
	"--hostname")
		if [ -z "${2}" ] ; then
			echo "No hostname specified"
			usage
		fi
		HOSTNAME=${2}
		shift
		shift
	;;
	"--static-iface")
		if [ -z "${2}" ] ; then
			echo "No IP specified"
			usage
		fi
		if [ -z "${STATIC_ETH}" ] ; then
			STATIC_ETH=${2}
		else
			STATIC_ETH="${STATIC_ETH} ${2}"
		fi
		shift
		shift
	;;
	"--reboot-after-install")
		REBOOT_AFTER_INSTALL=yes
		shift
	;;
	"--install-nonfree-repo")
		INSTALL_NONFREE_REPO=yes
		shift
	;;
	"--postinstall-packages")
		if [ -z "${2}" ] ; then
			echo "No postinstall packages specified"
			usage
		fi
		POSTINSTALL_PACKAGES=${2}
		shift
		shift
	;;
	"--security-mirror")
		if [ -z "${2}" ] ; then
			echo "No security mirror specified"
			usage
		fi
		SECURITY_MIRROR_URL="${2}"
		shift
		shift
	;;
	"--pre-reboot-hook")
		if [ -z "${2}" ] ; then
			echo "No pre-reboot hook script specified"
			usage
		fi
		PRE_REBOOT_HOOK_SCRIPT="${2}"
		shift
		shift
	;;
	"--add-serial-getty")
		if [ -z "${2}" ] ; then
			echo "No serial port specified."
			usage
		fi
		SERIAL_CONSOLE=yes
		SERIAL_CONSOLE_DEV="${2}"
		shift
		shift
	;;
	"--tty-autologin")
		if [ -z "${2}" ] ; then
			echo "No parameter for --tty-autologin"
		fi
		TTY_AUTOLOGIN=yes
		shift
		shift
	;;
	"--xfsformat")
		if [ -z "${2}" ] ; then
			echo "No device specifed for --xfsformat."
			usage
		fi
		XFSFORMAT="${2}"
		shift
		shift
	;;
	"--vgcreate")
		if [ -z "${2}" ] ; then
			echo "No device specifed for --vgcreate."
			usage
		fi
		VGCREATE="${2}"
		shift
		shift
	;;
	"--no-cloud-kernel")
		CLOUD_KERNEL=no
		shift
	;;
	"--grab-release-number")
		GRAB_RELEASE_NUMBER=yes
		shift
	;;
	"--generate-package-list")
		GEN_PKG_LIST=yes
		shift
	;;
	"--generate-source-tarball")
		GEN_SRC_TAR=yes
		shift
	;;
	"--generate-sums")
		GEN_SUMS=yes
		shift
	;;
	"--generate-sums-sign")
		GEN_SUMS=yes
		GEN_SUMS_SIGN=yes
		shift
	;;
	"--octavia-agent")
		SETUP_OCTAVIA_AGENT=yes
		AGENT_NAME=octavia
		shift
	;;
	"--manila-agent")
		SETUP_MANILA_AGENT=yes
		AGENT_NAME=manila
		shift
	;;
	"--trove-agent")
		SETUP_TROVE_AGENT=yes
		AGENT_NAME=TROVE
		shift
	;;
	"--extrepo")
		if [ -z "${2}" ] ; then
			echo "No parameter for --extrepo."
			usage
		fi
		SETUP_EXTREPO=yes
		EXTREPO_FLAVOR=$2
		shift
		shift
	;;
	"--newer-qemu")
		NEWER_QEMU=yes
		shift
	;;
	"--no-qcow2")
		BUILD_QCOW2=no
		shift
	;;
	"--kernel-from-backports")
		if [ -z "${2}" ] ; then
			echo "No parameter for --kernel-from-backports."
			usage
		fi
		if [ "${2}" = "yes" ] ; then
			KERNEL_FROM_BACKPORTS=yes
		else
			KERNEL_FROM_BACKPORTS=no
		fi
		shift
		shift
	;;
	*)
	;;
	esac
done

if [ -z "${RELEASE}" ] ; then
	echo "Release not recognized: please specify the -r parameter."
	usage
fi
case "${RELEASE}" in
	"wheezy")
		RELEASE_NUM=7
	;;
	"jessie")
		RELEASE_NUM=8
	;;
	"stretch")
		RELEASE_NUM=9
	;;
	"buster")
		RELEASE_NUM=10
	;;
	"bullseye")
		RELEASE_NUM=11
	;;
	"bookworm")
		RELEASE_NUM=12
	;;
	"trixie")
		RELEASE_NUM=12
	;;
	"sid")
		RELEASE_NUM=sid
	;;
esac

if [ -z "${DEB_MIRROR}" ] ; then
	DEB_MIRROR=http://deb.debian.org/debian
fi
if [ -z "${EXTRA_PACKAGES}" ] ; then
	EXTRA_PACKAGES=bash-completion,joe,most,screen,less,vim,bzip2,nano
fi
if [ -z "${SOURCE_LIST_MIRROR}" ] ; then
	SOURCE_LIST_MIRROR=http://deb.debian.org/debian
fi
if [ -z "${IMAGE_SIZE}" ] ; then
	IMAGE_SIZE=2
fi
if [ -z "${AUTOMATIC_RESIZE_SPACE}" ] ; then
	AUTOMATIC_RESIZE_SPACE=50
fi
if [ -z "${USER_LOGIN}" ] ; then
	USER_LOGIN=debian
fi

if [ "${RELEASE}" = "jessie" ] || [ "${RELEASE}" = "wheezy" ] || [ "${RELEASE}" = "stretch" ]; then
	if [ "${SETUP_EXTREPO}" = "yes" ] ; then
		echo "Extrepo is only available with Buster and up. Do not use --extrepo with ${RELEASE}."
		exit 1
	fi
fi

set -x

if [ "${GRAB_RELEASE_NUMBER}" = "yes" ] ; then
	if [ "${RELEASE}" = "stretch" ] ; then
		rm -f Release Release.gpg
		wget -q ${DEB_MIRROR}/dists/${RELEASE}/Release -O Release
		wget -q ${DEB_MIRROR}/dists/${RELEASE}/Release.gpg -O Release.gpg
		gpg --no-default-keyring --keyring /usr/share/keyrings/debian-archive-keyring.gpg --verify Release.gpg Release 2>&1 | grep "Good signature from"
	else
		wget -q ${DEB_MIRROR}/dists/${RELEASE}/InRelease -O InRelease
		gpg --no-default-keyring --keyring /usr/share/keyrings/debian-archive-keyring.gpg --verify InRelease 2>&1 | grep "Good signature from"
		cp InRelease Release.gpg || true
		gpg --no-default-keyring --keyring /usr/share/keyrings/debian-archive-keyring.gpg Release.gpg || true
		rm Release.gpg InRelease
	fi

	SUITE_NAME=$(cat Release | grep -E '^Suite: ' | sed -e 's/Suite: //')
	if [ "${SUITE_NAME}" = "stable" ] || [ "${SUITE_NAME}" = "oldstable" ] || [ "${SUITE_NAME}" = "oldoldstable" ] ; then
		RELEASE_VERSION=$(cat Release | grep -E '^Version: ' | sed -e 's/Version: //')
		if [ -e current_point_release ] ; then
			OLD_POINT_RELEASE=$(cat current_point_release)
			if [ "${RELEASE_VERSION}" != ${OLD_POINT_RELEASE} ] ; then
				echo ${RELEASE_VERSION} >current_point_release
				MINOR_VERSION=0
				echo 0 >current_minor_version
			else
				if [ -e current_minor_version ] ; then
					MINOR_VERSION=$(cat current_minor_version)
					MINOR_VERSION=$((${MINOR_VERSION} + 1))
				else
					MINOR_VERSION=0
				fi
				echo ${MINOR_VERSION} >current_minor_version
			fi
		else
			echo ${RELEASE_VERSION} >current_point_release
			MINOR_VERSION=0
			echo 0 >current_minor_version
		fi
	else
		echo "${RELEASE_NUM}~" >current_point_release
	fi
	rm -f Release.gpg Release InRelease
fi

# debian-bullseye-victoria-octavia-amphora-2021.04.27-16.04-amd64.raw

if [ -z "${OUTPUT}" ] ; then
	if [ -n "${RELEASE_VERSION}" ] && [ -n "${MINOR_VERSION}" ] ; then
		if [ "${MINOR_VERSION}" = 0 ] ; then
			if [ "${SETUP_OCTAVIA_AGENT}" = "yes" ] || [ "${SETUP_MANILA_AGENT}" = "yes" ] || [ "${SETUP_TROVE_AGENT}" = "yes" ] ; then
				if [ "${SETUP_EXTREPO}" = "yes" ] ; then
					OUTPUT=debian-${RELEASE}-${EXTREPO_FLAVOR}-${AGENT_NAME}-${RELEASE_VERSION}.${MINOR_VERSION}-${ARCH}
				else
					OUTPUT=debian-${RELEASE}-${AGENT_NAME}-${RELEASE_VERSION}.${MINOR_VERSION}-${ARCH}
				fi
			else
				OUTPUT=debian-${RELEASE}-${RELEASE_VERSION}.${MINOR_VERSION}-${ARCH}
			fi
		else
			if [ "${SETUP_OCTAVIA_AGENT}" = "yes" ] || [ "${SETUP_MANILA_AGENT}" = "yes" ] || [ "${SETUP_TROVE_AGENT}" = "yes" ]; then
				if [ "${SETUP_EXTREPO}" = "yes" ] ; then
					OUTPUT=debian-${RELEASE}-${EXTREPO_FLAVOR}-${AGENT_NAME}-${RELEASE_VERSION}.${MINOR_VERSION}-$(TZ=UTC date '+%Y%m%d')-${ARCH}
				else
					OUTPUT=debian-${RELEASE}-${AGENT_NAME}-${RELEASE_VERSION}.${MINOR_VERSION}-$(TZ=UTC date '+%Y%m%d')-${ARCH}
				fi
			else
				OUTPUT=debian-${RELEASE}-${RELEASE_VERSION}.${MINOR_VERSION}-$(TZ=UTC date '+%Y%m%d')-${ARCH}
			fi
		fi
	else
		if [ "${RELEASE_NUM}" = "sid" ] ; then
			if [ "${SETUP_OCTAVIA_AGENT}" = "yes" ] || [ "${SETUP_MANILA_AGENT}" = "yes" ] || [ "${SETUP_TROVE_AGENT}" = "yes" ]; then
				OUTPUT=debian-${RELEASE}-${AGENT_NAME}-$(TZ=UTC date '+%Y.%m.%d-%H.%M')-${ARCH}
			else
				OUTPUT=debian-${RELEASE}-$(TZ=UTC date '+%Y.%m.%d-%H.%M')-${ARCH}
			fi
		else
			if [ "${SETUP_OCTAVIA_AGENT}" = "yes" ] || [ "${SETUP_MANILA_AGENT}" = "yes" ] || [ "${SETUP_TROVE_AGENT}" = "yes" ]; then
				if [ "${SETUP_EXTREPO}" = "yes" ] ; then
					OUTPUT=debian-${RELEASE}-${RELEASE_NUM}-${EXTREPO_FLAVOR}-${AGENT_NAME}-$(TZ=UTC date '+%Y.%m.%d-%H.%M')-${ARCH}
				else
					OUTPUT=debian-${RELEASE}-${RELEASE_NUM}-${AGENT_NAME}-$(TZ=UTC date '+%Y.%m.%d-%H.%M')-${ARCH}
				fi
			else
				OUTPUT=debian-${RELEASE}-${RELEASE_NUM}-$(TZ=UTC date '+%Y.%m.%d-%H.%M')-${ARCH}
			fi
		fi
	fi
	echo ${OUTPUT} > latest
fi

if [ "${BOOTTYPE}" = "uefi" ] && [ "${BOOTMANAGER}" != "grub" ] ; then
	echo "uefi boot type is only compatible with grub"
	usage
fi

if [ "${ARCH}" = "arm64" ] ; then
	if [ "${BOOTMANAGER}" != "grub" ] || [ "${BOOTTYPE}" != "uefi" ] ; then
		echo "arm64 depends on using grub and uefi"
		usage
	fi
fi

if [ -n "${SERIAL_CONSOLE_DEV}" ] ; then
	CONSOLE=${SERIAL_CONSOLE_DEV}
else
	CONSOLE=ttyS0
	if [ "${ARCH}" = "arm64" ] ; then
		CONSOLE=ttyAMA0
	fi
fi

if [ "${BOOTMANAGER}" = "grub" ] ; then
	if [ "${BOOTTYPE}" = "uefi" ] ; then
		BOOT_MGR_PKG="grub-efi-${ARCH}"
		if [ "${ARCH}" = "arm64" ] ; then
			GRUB_TARGET="arm64-efi"
		else
			GRUB_TARGET="x86_64-efi"
		fi
	else
		BOOT_MGR_PKG="grub-pc"
		GRUB_TARGET="i386-pc"
	fi
else
	BOOT_MGR_PKG="extlinux"
fi

if [ "${REAL_HARDWARE}" = "no" ] ; then
	RAW_NAME=${OUTPUT}.raw
	QCOW2_NAME=${OUTPUT}.qcow2
	rm -f ${RAW_NAME}
	qemu-img create ${RAW_NAME} ${IMAGE_SIZE}G
	DEVICES_TO_PARTITION=${RAW_NAME}
	RAID_PKG=""
else
	case "${DEST_HDD}" in
	raid0|raid1|raid10)
		RAID_DEVICES=$(echo ${RAID_DEVS} | tr , " ")
		DEVICES_TO_PARTITION=""
		for i in ${RAID_DEVICES} ; do
			if [ -n "${DEVICES_TO_PARTITION}" ] ; then
				DEVICES_TO_PARTITION="${DEVICES_TO_PARTITION} /dev/${i}"
			else
				DEVICES_TO_PARTITION="/dev/${i}"
			fi
		done
	;;
	*)
		RAW_NAME=/dev/${DEST_HDD}
		DEVICES_TO_PARTITION=/dev/${DEST_HDD}
	;;
	esac
	RAID_PKG=",mdadm"
fi

IF_PKG=""
if echo "${STATIC_ETH}" | grep -q bond ; then
	IF_PKG="${IF_PKG},ifenslave,ethtool"
fi

if echo "${STATIC_ETH}" | grep -q bridge ; then
	IF_PKG="${IF_PKG},bridge-utils"
fi

if echo "${STATIC_ETH}" | grep -q vlan ; then
	IF_PKG="${IF_PKG},vlan"
fi

if echo "${STATIC_ETH}" | grep -q bgp ; then
	IF_PKG="${IF_PKG},ethtool,bridge-utils,vlan,frr"
fi

NEEDED_PACKAGES=sudo,adduser,lsb-release,busybox-static,console-setup,locales,${BOOT_MGR_PKG},openssh-server,file,kbd,file${IF_PKG}${RAID_PKG}
if [ "${RELEASE}" = "wheezy" ] ; then
	# These are needed by cloud-init and friends, and since we don't want backports of them,
	# but just normal packages from Wheezy, we resolve dependencies by hand, prior to using
	# apt-get -t wheezy-backports install cloud-init cloud-utils cloud-initramfs-growroot
	NEEDED_PACKAGES=${NEEDED_PACKAGES},python,python-paramiko,python-argparse,python-cheetah,python-configobj,python-oauth,python-software-properties,python-yaml,python-boto,python-prettytable,initramfs-tools,python-requests,acpid,acpi-support-base
else
	if [ "${RELEASE}" = "jessie" ] ; then
		if [ "${CLOUD_INIT}" = "yes" ] ; then
			NEEDED_PACKAGES=${NEEDED_PACKAGES},cloud-initramfs-growroot
		fi
	fi
	NEEDED_PACKAGES=${NEEDED_PACKAGES},dbus,unscd
	if [ "${CLOUD_INIT}" = "yes" ] ; then
		NEEDED_PACKAGES=${NEEDED_PACKAGES},cloud-init,cloud-utils,resolvconf
	fi
fi
if [ "${BUILD_RESCUE_IMG}" = "yes" ] ; then
	NEEDED_PACKAGES=${NEEDED_PACKAGES},parted,mbr,kpartx,dosfstools,e2fsprogs,qemu-utils,scrub,testdisk,scalpel,gpart,gddrescue,foremost,ddrutility,btrfs-progs,fdisk
fi

# This is a workaround for python3-cryptography failing to install
if [ "${RELEASE_NUM}" = "sid" ] || [ "${RELEASE_NUM}" -ge 9 ] ; then
	NEEDED_PACKAGES=${NEEDED_PACKAGES},python3-cffi-backend
fi

if [ ${EXTRA} = "no" ] ; then
	PKG_LIST=${NEEDED_PACKAGES}
else
	PKG_LIST=${NEEDED_PACKAGES},${EXTRA_PACKAGES}
fi
if ! [ `whoami` = "root" ] ; then
	echo "You have to be root to run this script"
	exit 1
fi

set -x

######################################
### Prepare the HDD (format, ext.) ###
######################################
PARTED=/sbin/parted

for BLOCKDEV in ${DEVICES_TO_PARTITION} ; do
	if [ "${BOOTTYPE}" = "mbr" ] ; then
		${PARTED} -s ${BLOCKDEV} mktable msdos
		${PARTED} -s -a optimal ${BLOCKDEV} mkpart primary ext4 1Mi 100%
		${PARTED} -s ${BLOCKDEV} set 1 boot on
		if [ -n "${RAID_DEVICES}" ] ; then
			${PARTED} -s ${BLOCKDEV} set 1 raid on
			# Make sure the partition first blocks is erased, otherwise,
			# RAID creation may fail.
			sleep 5
			dd if=/dev/zero of=${BLOCKDEV}1 bs=4M count=1
		fi
		install-mbr --force ${BLOCKDEV}

		if [ "${REAL_HARDWARE}" = "no" ] ; then
			RESULT_KPARTX=$(kpartx -asv ${RAW_NAME} 2>&1)
			if echo "${RESULT_KPARTX}" | grep "^add map" ; then
				LOOP_DEVICE=$(echo ${RESULT_KPARTX} | cut -d" " -f3)
				LOOPRAW_DEVICE=${LOOP_DEVICE%p*}
				echo "kpartx mounted using: ${LOOP_DEVICE} via ${LOOPRAW_DEVICE}"
			else
				echo "It seems kpartx didn't mount the image correctly: exiting."
				exit 1
			fi
		else
			sync
			partprobe
		fi
	else # uefi
		${PARTED} -s ${BLOCKDEV} mktable gpt
		${PARTED} -s -a optimal ${BLOCKDEV} mkpart ESP fat32 1Mi 2001Mi
		${PARTED} -s -a optimal ${BLOCKDEV} -- mkpart ROOT ext4 2002Mi -64s
		${PARTED} -s ${BLOCKDEV} set 1 esp on

		if [ "${REAL_HARDWARE}" = "no" ] ; then
			RESULT_KPARTX=$(kpartx -asv ${RAW_NAME} 2>&1 | tail -1)
			if echo "${RESULT_KPARTX}" | grep "^add map" ; then
				LOOP_DEVICE=$(echo ${RESULT_KPARTX} | cut -d" " -f3)
				LOOPRAW_DEVICE=${LOOP_DEVICE%p*}
				echo "kpartx mounted using: ${LOOP_DEVICE} via ${LOOPRAW_DEVICE}"
			else
				echo "It seems kpartx didn't mount the image correctly: exiting."
				exit 1
			fi
			LOOP_DEVICE_ESP="${LOOPRAW_DEVICE}"p1
		else
			sync
			partprobe
		fi
	fi
done

# Wait for the kernel to see the new partitions
sleep 5

cleanup(){
	error=$?
	[ ! -d "${MOUNT_DIR}" ] && return
	if [ "$error" -gt 0 ]; then
		echo
		echo "Error $error"
	else
		echo "Finished."
	fi

	set +e

	sync
	chroot ${MOUNT_DIR} umount /proc || true
	chroot ${MOUNT_DIR} umount /sys || true
	chroot ${MOUNT_DIR} umount /dev || true
	umount -l ${MOUNT_DIR}
	rmdir ${MOUNT_DIR}

	if [ "${REAL_HARDWARE}" = "no" ] ; then
		kpartx -d ${RAW_NAME}
	fi
	if [ -n "${RAID_DEVICES}" ] ; then
		mdadm --stop /dev/md0
	fi
	exit $error
}
trap "cleanup" EXIT TERM INT

if [ -n "${RAID_DEVICES}" ] ; then
	# Transform the list "sda sdb" to "/dev/sda1 /dev/sdb1"
	# if UEFI, then use "/dev/sda2 /dev/sdb2"
	if [ "${BOOTTYPE}" = "mbr" ] ; then
		RAID_PART_NUM=1
	else
		RAID_PART_NUM=2
	fi
	RAID_DLIST=""
	NUM_DEVS=0
	FIRST_RAID_ESP_DEV=""
	for i in ${DEVICES_TO_PARTITION} ; do
		if [ -n "${RAID_DLIST}" ] ; then
			RAID_DLIST="${RAID_DLIST} ${i}${RAID_PART_NUM}"
		else
			RAID_DLIST="${i}${RAID_PART_NUM}"
		fi
		if [ -z "${FIRST_RAID_DEV}" ] && [ "${BOOTTYPE}" = "uefi" ] ; then
			# This is the UEFI partition of the first RAID device
			FIRST_RAID_ESP_DEV=/dev/${i}1
		fi
		NUM_DEVS=$((${NUM_DEVS} + 1))
	done

	# Slow down RAID rebuild to 10 MB/s, to speedup OS install
	# (it will continue rebuild at 200 MB/s after reboot)
	echo 10000 >/proc/sys/dev/raid/speed_limit_max

	case "${DEST_HDD}" in
	"raid0")
		echo "raid 0: Currently unsupported"
		exit 1
		mdadm --create --run --verbose /dev/md0 --level=0 --raid-devices=${NUM_DEVS} ${RAID_DLIST}
		GRUB_MODULES=mdraid1x
	;;
	"raid1")
		mdadm --create --run --verbose /dev/md0 --level=1 --raid-devices=${NUM_DEVS} ${RAID_DLIST}
		GRUB_MODULES=mdraid1x
	;;
	"raid10")
		echo "raid 10: Currently unsupported"
		exit 1
		mdadm --create --run --verbose /dev/md0 --level=10 --raid-devices=${NUM_DEVS} ${RAID_DLIST}
		GRUB_MODULES=mdraid1x
	;;
	*)
		echo "Unrecognized RAID type"
		exit 1
	;;
	esac
fi

if [ "${REAL_HARDWARE}" = "no" ] ; then
	DEST_PART=/dev/mapper/${LOOP_DEVICE}
	DEST_PART_ESP=/dev/mapper/${LOOP_DEVICE_ESP}
else
	if [ -n "${RAID_DEVICES}" ] ; then
		DEST_PART=/dev/md0
		if [ "${BOOTTYPE}" = "uefi" ] ; then
			DEST_PART_ESP=${FIRST_RAID_ESP_DEV}
		fi
	else
		if [ "${BOOTTYPE}" = "mbr" ] ; then
			DEST_PART=/dev/${DEST_HDD}1
		else
			DEST_PART_ESP=/dev/${DEST_HDD}1
			DEST_PART=/dev/${DEST_HDD}2
		fi
	fi
fi

mkfs.ext4 -F ${DEST_PART}
UUID=$(blkid -o value -s UUID ${DEST_PART})

# No fsck because of X days without checks
tune2fs -i 0 ${DEST_PART}

MOUNT_DIR=`mktemp -d -t build-debimg.XXXXXX`

mount ${DEST_PART} ${MOUNT_DIR}
if [ "${BOOTTYPE}" = "uefi" ] ; then
	mkfs.vfat ${DEST_PART_ESP}
	UUID_ESP=$(blkid -o value -s UUID ${DEST_PART_ESP})
	mkdir -p ${MOUNT_DIR}/boot/efi
	mount ${DEST_PART_ESP} ${MOUNT_DIR}/boot/efi
fi

debootstrap --verbose \
	--include=${PKG_LIST} \
	${RELEASE} ${MOUNT_DIR} ${DEB_MIRROR}


if [ -n "${XFSFORMAT}" ] ; then
	XFS_HDDS=$(echo ${XFSFORMAT} | tr , " ")
	for i in ${XFS_HDDS} ; do
		if [ -x /sbin/mkfs.xfs ] ; then
			echo "===> Formating /dev/${i}"
			mkfs.xfs -f /dev/${i}
		else
			echo "===> Could not find mkfs.xfs, so wont format /dev/${i}"
		fi
	done
fi

if [ -n "${VGCREATE}" ] ; then
	if [ -x /sbin/lvcreate ] ; then
		VG_HDDS=$(echo ${VGCREATE} | tr , " ")
		VG_DEVS=""
		for i in ${VG_HDDS} ; do
			echo "===> Creating PV for /dev/${i}"
			pvcreate -ff -y /dev/${i}
			VG_DEVS="${VG_DEVS} /dev/${i}"
		done
		if [ -x /sbin/vgcreate ] ; then
			vgcreate ocivg0 ${VG_DEVS}
			vgchange -a y ocivg0
		else
			echo "===> Could not find vgcreate, so wont create volume groups."
		fi
	else
		echo "===> Could not find pvcreate, so wont create volume groups."
	fi
fi

############################
### Customize the distro ###
############################
### Fixup mdadm.conf if using RAID ###
######################################
if [ -n "${RAID_DEVICES}" ] ; then
	mkdir -p ${MOUNT_DIR}/etc/mdadm
	RAID_UUID=$(echo ${UUID} | sed s/-/:/g)
	echo "# mdadm.conf
#
# Please refer to mdadm.conf(5) for information about this file.
#

# by default (built-in), scan all partitions (/proc/partitions) and all
# containers for MD superblocks. alternatively, specify devices to scan, using
# wildcards if desired.
#DEVICE partitions containers

# auto-create devices with Debian standard permissions
CREATE owner=root group=disk mode=0660 auto=yes

# automatically tag new arrays as belonging to the local system
HOMEHOST <system>

# instruct the monitoring daemon where to send mail alerts
MAILADDR root@localhost

# definitions of existing MD arrays
" >${MOUNT_DIR}/etc/mdadm/mdadm.conf
	mdadm --detail --scan >>${MOUNT_DIR}/etc/mdadm/mdadm.conf
	chmod 644 /etc/mdadm/mdadm.conf
fi

### Customize: access to the VM ###
# # # # # # # # # # # # # # # # # #
# Setup default root password to what has been set on the command line
if [ -n "${ROOT_PASSWORD}" ] ; then
	chroot ${MOUNT_DIR} sh -c "echo root:${ROOT_PASSWORD} | chpasswd"
fi

if [ -n "${ROOT_SSH_KEY}" ] ; then
	mkdir -p ${MOUNT_DIR}/root/.ssh
	chmod 700 ${MOUNT_DIR}/root/.ssh
	cat <${ROOT_SSH_KEY} >${MOUNT_DIR}/root/.ssh/authorized_keys
	chmod 600 ${MOUNT_DIR}/root/.ssh/authorized_keys
fi

if [ "${CLOUD_INIT}" = "yes" ] ; then
	# Add a default user which is used by cloud-init by default.
	# This isn't needed for at least stretch and on, because cloud-init
	# creates the user, and it's best to give users a choice to overwrite it.
	if [ "${RELEASE}" = "wheezy" ] || [ "${RELEASE}" = "jessie" ] ; then
		chroot ${MOUNT_DIR} adduser --gecos Cloud-init-user --disabled-password --quiet ${USER_LOGIN}
	fi

	# Adds the "debian" user to sudoers, since that is the way
	# cloud-init grant access
	mkdir -p ${MOUNT_DIR}/etc/sudoers.d
	echo "${USER_LOGIN} ALL = NOPASSWD: ALL" >${MOUNT_DIR}/etc/sudoers.d/debian-cloud-init
	chmod 0440 ${MOUNT_DIR}/etc/sudoers.d/debian-cloud-init
fi

### Customize: misc stuff ###
# # # # # # # # # # # # # # #
# Setup fstab
if [ -n "${RAID_DEVICES}" ] ; then
	echo "# /etc/fstab: static file system information.
/dev/md0	/	ext4	errors=remount-ro	0	1
" > ${MOUNT_DIR}/etc/fstab
else
	echo "# /etc/fstab: static file system information.
UUID=${UUID}	/	ext4	errors=remount-ro	0	1
" > ${MOUNT_DIR}/etc/fstab
fi
if [ "${BOOTTYPE}" = "uefi" ] ; then
	echo "UUID=${UUID_ESP}	/boot/efi	vfat	errors=remount-ro	0	0" >> ${MOUNT_DIR}/etc/fstab
fi
mount -t proc proc ${MOUNT_DIR}/proc

if [ "${REAL_HARDWARE}" = "no" ] ; then
	echo "# disable pc speaker
blacklist pcspkr" >${MOUNT_DIR}/etc/modprobe.d/blacklist.conf
fi

# No clear for the tty1 console
if [ "${RELEASE}" = "wheezy" ] ; then
	sed -i "s#1:2345:respawn:/sbin/getty 38400 tty1#1:2345:respawn:/sbin/getty --noclear 38400 tty1#" ${MOUNT_DIR}/etc/inittab
else
	# XXX: the serial port on Microsoft Azure plattform can't cope with
	# lots of data, keep this option disabled.
	#echo ForwardToConsole=yes >> ${MOUNT_DIR}/etc/systemd/journald.conf
	:
fi

if [ "${SERIAL_CONSOLE}" = "yes" ] ; then
	PROC_MANUFACTURER=$(dmidecode -s processor-manufacturer | head -n 1)
	if [ "${REAL_HARDWARE}" = "yes" ] && [ "${PROC_MANUFACTURER}" = "QEMU" ] ; then
		echo "Probably setting-up on a virtualized OCI PoC: will not setup getty on ttyS1."
	else
		mkdir -p ${MOUNT_DIR}/etc/systemd/system/getty.target.wants
		if [ "${TTY_AUTOLOGIN}" = "yes" ] ; then
			AUTOLOGIN_TXT="--autologin root --noclear "
		else
			AUTOLOGIN_TXT=""
		fi
		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_TXT}--keep-baud 115200,38400,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
" >${MOUNT_DIR}/etc/systemd/system/serial-getty@${SERIAL_CONSOLE_DEV}.service
		ln -s ../serial-getty@${SERIAL_CONSOLE_DEV}.service ${MOUNT_DIR}/etc/systemd/system/getty.target.wants/serial-getty@${SERIAL_CONSOLE_DEV}.service
	fi
fi

if [ "${TTY_AUTOLOGIN}" = "yes" ] ; then
	if [ "${TTY_AUTOLOGIN}" = "yes" ] ; then
		AUTOLOGIN_TXT="--autologin root"
	else
		AUTOLOGIN_TXT="-o '-p -- \\\\u'"
	fi
	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=Getty on %I
Documentation=man:agetty(8) man:systemd-getty-generator(8)
Documentation=http://0pointer.de/blog/projects/serial-console.html
After=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

# On systems without virtual consoles, don't start any getty. Note
# that serial gettys are covered by serial-getty@.service, not this
# unit.
ConditionPathExists=/dev/tty0

[Service]
# the VT is cleared by TTYVTDisallocate
# 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_TXT} --noclear %I \$TERM
Type=idle
Restart=always
RestartSec=0
UtmpIdentifier=%I
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes

# Unset locale for the console getty since the console has problems
# displaying some internationalized messages.
UnsetEnvironment=LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION

[Install]
WantedBy=getty.target
DefaultInstance=tty1
" >${MOUNT_DIR}/etc/systemd/system/getty@.service
	rm -f ${MOUNT_DIR}/etc/systemd/system/getty.target.wants/getty@tty1.service
	ln -s ../getty@.service ${MOUNT_DIR}/etc/systemd/system/getty.target.wants/getty@tty1.service
fi

# If running on real hardware, hard-wire eth names in udev rules,
# because they can change over time, especially since OCI potentially removes
# some drivers from the initrd.
if [ "${REAL_HARDWARE}" = "yes" ] ; then
	mkdir -p ${MOUNT_DIR}/etc/udev/rules.d
	echo "# Persistent-net rules written by openstack-debian-images" >${MOUNT_DIR}/etc/udev/rules.d/70-persistent-net.rules
	for i in $(ip link show | grep -v '^ ' | grep -v 'lo:' | cut -d' ' -f2 | cut -d: -f1 | grep -v grep -v -E 'bond|.*@.*|qvb.*|qvo.*|vxlan.*|tap.*|qbr.*|qr.*|sg-.*|ha-.*|ovs.*|qg-.*|sg-.*|fg-.*|ovs-system|br-ex|br-int|br-tun|vlan.*|usb.*|docker0|kube-ipvs0|nodelocaldns|idrac|cali.*@if\d') ; do
	        MAC_ADDR=$(ip link show dev $i | grep 'link/ether' | awk '{print $2}')
	        ETH_SPEED=$(( $(lshw -class network 2>/dev/null -json | jq '.[] | select(.serial|test("'${MAC_ADDR}'")) | .capacity' | head -n 1) / 1000000))
	        if [ "${ETH_SPEED}" = 25000 ] ; then
			NICE_SPEED="25 Gbits/s"
	        elif [ "${ETH_SPEED}" = 10000 ] ; then
			NICE_SPEED="10 Gbits/s"
	        elif [ "${ETH_SPEED}" = 1000 ] ; then
			NICE_SPEED="1 Gbits/s"
	        elif [ "${ETH_SPEED}" = 100 ] ; then
			NICE_SPEED="100 Mbits/s"
	        elif [ "${ETH_SPEED}" = 10 ] ; then
			NICE_SPEED="10 Mbits/s"
	        else
			NICE_SPEED="unrecognized speed"
	        fi
		echo "# ${i}: ${NICE_SPEED}
"'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="'${MAC_ADDR}'", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="'${i}'"'"
">>${MOUNT_DIR}/etc/udev/rules.d/70-persistent-net.rules
	done
fi

# We do it *after* the debootstrap, as otherwise it fails with
# systemd-shim conflicting with systemd-sysv.
chroot ${MOUNT_DIR} apt-get update
chroot ${MOUNT_DIR} apt-get install -y -o Dpkg::Options::="--force-confnew" locales-all libpam-systemd chrony


# Turn off console blanking which is *very* annoying
# and increase KEYBOARD_DELAY because it can be annoying
# over network.
# Note: /etc/kbd/config is gone away from Stretch, but
# we still need to fix it for previous Debian releases.
# In stretch and beyond, consoleblank=0 in the kernel
# command line should be enough (TODO: check for that fact).
if [ -e ${MOUNT_DIR}/etc/kbd/config ] ; then
	sed -i s/^BLANK_TIME=.*/BLANK_TIME=0/ ${MOUNT_DIR}/etc/kbd/config
	sed -i s/^POWERDOWN_TIME=.*/POWERDOWN_TIME=0/ ${MOUNT_DIR}/etc/kbd/config
	sed -i 's/^[ \t#]KEYBOARD_DELAY=.*/KEYBOARD_DELAY=1000/' ${MOUNT_DIR}/etc/kbd/config
fi

if [ "${REAL_HARDWARE}" = "no" ] && [ "${REMOVE_HOST_KEYS}" = "yes" ] ; then
	rm -f ${MOUNT_DIR}/etc/ssh/ssh_host_*
fi

if [ "${PERMIT_SSH_AS_ROOT}" = "yes" ] ; then
	sed -i 's|[#]*PermitRootLogin.*|PermitRootLogin yes|' ${MOUNT_DIR}/etc/ssh/sshd_config
fi

if [ "${REAL_HARDWARE}" = "no" ] ; then
	rm -f ${MOUNT_DIR}/etc/udev/rules.d/70-persistent-net.rules
	rm -f ${MOUNT_DIR}/lib/udev/write_net_rules
fi

# Customize a little bit apt
echo 'pkg::Progress-Fancy "1";
APT::Color "true";' >${MOUNT_DIR}/etc/apt/apt.conf.d/99progressbar

echo 'Acquire::Languages "none";' >${MOUNT_DIR}/etc/apt/apt.conf.d/99notranslations

echo 'APT::Install-Recommends "0";' >${MOUNT_DIR}/etc/apt/apt.conf.d/80norecommends

echo 'Acquire::PDiffs "false";' >${MOUNT_DIR}/etc/apt/apt.conf.d/98nopdiff

# Setup networking
ENI=${MOUNT_DIR}/etc/network/interfaces

HAS_BGP_TO_THE_HOST=no
BGP_IP_LIST=""
BGP_IFACE_LIST=""
BGP_ASNUM=""

add_to_bgp_iface_list () {
	local NOT_IN IFACE_NAME
	IFACE_NAME=${1}

	if [ -z "${BGP_IFACE_LIST}" ] ; then
		BGP_IFACE_LIST=${IFACE_NAME}
		return
	fi

	# Check if the iface is there already
	NOT_IN=yes
	for i in $(echo "${BGP_IFACE_LIST}" | tr ',' ' ') ; do
		if [ "${i}" = "${IFACE_NAME}" ] ; then
			return
		fi
	done
	BGP_IFACE_LIST="${BGP_IFACE_LIST},${IFACE_NAME}"
}

# First, always add the loopback
echo "# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback
" > ${ENI}
if [ -n "${STATIC_ETH}" ] ; then
	BOND_NUMBER=0
	for i in ${STATIC_ETH} ; do
		SE_TYPE=""
		SE_IFACE0=""
		SE_IFACE1=""
		SE_ADDR=""
		SE_GW=""
		SE_VLANNUM=""
		SE_BRNAME=""
		SE_DNS=""
		SE_DNSSEARCH=""
		SE_MTU=""
		SE_OVSBR=""
		SE_VMNET_ADDR=""
		SE_VMNET_VLAN=""
		SE_VMNET_IFACE1=""
		SE_VMNET_IFACE2=""
		SE_EXTRA_OVS="no"
		SE_OVSBRIDGE_NAME=""
		SE_USE_OVS_IFACES="no"
		SE_ASNUM=""
		SE_ADD_BGP_IP=""
		ETH_PARAMS=$(echo ${i} | tr , " ")
		for ETH_PARAM in ${ETH_PARAMS} ; do
			ETH_PDIR=$(echo ${ETH_PARAM} | cut -d= -f1)
			ETH_PVAL=$(echo ${ETH_PARAM} | cut -d= -f2)
			case "${ETH_PDIR}" in
			"type")
				SE_TYPE=${ETH_PVAL}
			;;
			"iface0")
				SE_IFACE0=${ETH_PVAL}
			;;
			"iface1")
				SE_IFACE1=${ETH_PVAL}
			;;
			"addr")
				SE_ADDR=$( echo ${ETH_PVAL} | cut -d: -f1)
				SE_GW=$( echo ${ETH_PVAL} | cut -d: -f2)
			;;
			"vlannum")
				SE_VLANNUM=${ETH_PVAL}
			;;
			"bridgename")
				SE_BRNAME=${ETH_PVAL}
			;;
			"dns")
				SE_DNS=${ETH_PVAL}
				SE_ALL_NS=$(echo ${SE_DNS} | tr : " ")
			;;
			"dns-search")
				SE_DNSSEARCH=${ETH_PVAL}
			;;
			"mtu")
				SE_MTU=${ETH_PVAL}
			;;
			"ovsbr")
				SE_OVSBR=${ETH_PVAL}
			;;
			"vmnet_addr")
				SE_VMNET_ADDR=${ETH_PVAL}
			;;
			"vmnet_vlan")
				SE_VMNET_VLAN=${ETH_PVAL}
			;;
			"vmnet_iface0")
				SE_VMNET_IFACE0=${ETH_PVAL}
			;;
			"vmnet_iface1")
				SE_VMNET_IFACE1=${ETH_PVAL}
			;;
			"extra_ovs")
				SE_EXTRA_OVS="yes"
			;;
			"ovsbridgename")
				SE_OVSBRIDGE_NAME=${ETH_PVAL}
			;;
			"ovsifaces")
				if [ "${ETH_PVAL}" = "yes" ] ; then
					SE_USE_OVS_IFACES="yes"
				fi
			;;
			"asnum")
				SE_ASNUM=${ETH_PVAL}
			;;
			"addbgpi")
				SE_ADD_BGP_IP=${ETH_PVAL}
			;;
			*)
				echo "Unrecognized parameter"
			;;
			esac
		done
		IFACE_ADDR=$(echo ${SE_ADDR} | cut -d/ -f1)
		IFACE_NETWORK=$(ipcalc ${SE_ADDR} | grep '^Network:' | awk '{print $2}' | cut -d/ -f1)
		IFACE_BROADCAST=$(ipcalc ${SE_ADDR} | grep '^Broadcast:' | awk '{print $2}')
		IFACE_NETMASK=$(ipcalc ${SE_ADDR} | grep '^Netmask:' | awk '{print $2}')
		if [ -n "${SE_VMNET_ADDR}" ] ; then
			VMNET_IFACE_ADDR=$(echo ${SE_VMNET_ADDR} | cut -d/ -f1)
			VMNET_IFACE_NETWORK=$(ipcalc ${SE_VMNET_ADDR} | grep '^Network:' | awk '{print $2}' | cut -d/ -f1)
			VMNET_IFACE_BROADCAST=$(ipcalc ${SE_VMNET_ADDR} | grep '^Broadcast:' | awk '{print $2}')
			VMNET_IFACE_NETMASK=$(ipcalc ${SE_VMNET_ADDR} | grep '^Netmask:' | awk '{print $2}')
		fi

		case "${SE_TYPE}" in
		"bgp")
			HAS_BGP_TO_THE_HOST=yes

			if [ -z "${BGP_ASNUM}" ] && [ -n "${SE_ASNUM}" ] ; then
				BGP_ASNUM=${SE_ASNUM}
			fi

			# Manage a list of IP addresses added to the BGP config in FRR
			if [ -n "${BGP_IP_LIST}" ] ; then
				BGP_IP_LIST="${BGP_IP_LIST},"
			fi
			BGP_IP_LIST="${BGP_IP_LIST}${SE_ADDR}"

			if [ -n "${SE_ADD_BGP_IP}" ] ; then
				BGP_IP_LIST="${BGP_IP_LIST},${SE_ADD_BGP_IP}"
			fi

			echo "auto ${SE_IFACE0}">> ${ENI}
			echo "iface ${SE_IFACE0} inet manual">> ${ENI}
			echo "	metric 4278198272">> ${ENI}
			if [ "${SE_MTU}" ] ; then
				echo "	mtu ${SE_MTU}" >> ${ENI}
			fi
			echo "" >>${ENI}
			if [ -n "${SE_VLANNUM}" ] ; then
				echo "auto ${SE_IFACE0}.${SE_VLANNUM}">> ${ENI}
				echo "iface ${SE_IFACE0}.${SE_VLANNUM} inet manual">> ${ENI}
				if [ "${SE_MTU}" ] ; then
					echo "	mtu ${SE_MTU}" >> ${ENI}
				fi
				echo "" >>${ENI}
				add_to_bgp_iface_list ${SE_IFACE0}.${SE_VLANNUM}
			else
				add_to_bgp_iface_list ${SE_IFACE0}
			fi

			if [ -n "${SE_IFACE1}" ] ; then
				echo "auto ${SE_IFACE1}">> ${ENI}
				echo "iface ${SE_IFACE1} inet manual">> ${ENI}
				echo "	metric 4278198272">> ${ENI}
				if [ "${SE_MTU}" ] ; then
					echo "	mtu ${SE_MTU}" >> ${ENI}
				fi
				echo "" >>${ENI}
				if [ -n "${SE_VLANNUM}" ] ; then
					echo "auto ${SE_IFACE1}.${SE_VLANNUM}">> ${ENI}
					echo "iface ${SE_IFACE1}.${SE_VLANNUM} inet manual">> ${ENI}
					if [ "${SE_MTU}" ] ; then
						echo "	mtu ${SE_MTU}" >> ${ENI}
					fi
					echo "" >>${ENI}
				fi
				add_to_bgp_iface_list ${SE_IFACE1}.${SE_VLANNUM}
			else
				add_to_bgp_iface_list ${SE_IFACE1}
			fi

			# Add the br-ex interface
			if [ -n "${SE_OVSBR}" ] ; then
				echo "auto br-ex" >> ${ENI}
				echo "iface br-ex inet manual" >> ${ENI}
				echo "	ovs_type OVSBridge" >> ${ENI}
				echo "	ovs_ports lo" >> ${ENI}
				echo "" >> ${ENI}
			fi
		;;
		"ovsbridge")
			echo "auto ${SE_OVSBRIDGE_NAME}" >> ${ENI}
			echo "iface ${SE_OVSBRIDGE_NAME} inet manual" >> ${ENI}
			echo "	ovs_type OVSBridge" >> ${ENI}
			echo "	ovs_ports ${SE_IFACE0}" >> ${ENI}
			echo "	up ovs-vsctl add-port ${SE_OVSBRIDGE_NAME} ${SE_IFACE0} || true" >> ${ENI}
			echo "	up ip link set ${SE_IFACE0} up" >> ${ENI}
			echo "" >> ${ENI}
		;;
		"normal")
			if [ -n "${SE_VMNET_ADDR}" ] ; then
				echo "auto ${SE_IFACE0}" >> ${ENI}
				echo "iface ${SE_IFACE0} inet static" >> ${ENI}
				echo "	address ${IFACE_ADDR}" >> ${ENI}
				echo "	network ${IFACE_NETWORK}" >> ${ENI}
				echo "	netmask ${IFACE_NETMASK}" >> ${ENI}
				echo "	broadcast ${IFACE_BROADCAST}" >> ${ENI}
				if [ "${SE_MTU}" ] ; then
					echo "	mtu ${SE_MTU}" >> ${ENI}
				fi
				if [ -n "${SE_DNS}" ] ; then
					echo "	dns-nameservers ${SE_ALL_NS}" >> ${ENI}
				fi
				if [ -n "${SE_DNSSEARCH}" ] ; then
					echo "	dns-search ${SE_DNSSEARCH}" >> ${ENI}
				fi
				if [ -n "${SE_GW}" ] ; then
					echo "	gateway ${SE_GW}" >> ${ENI}
				fi
				echo "" >> ${ENI}

				echo "auto ${SE_VMNET_IFACE0}" >> ${ENI}
				echo "iface ${SE_VMNET_IFACE0} inet static" >> ${ENI}
				echo "	address ${VMNET_IFACE_ADDR}" >> ${ENI}
				echo "	network ${VMNET_IFACE_NETWORK}" >> ${ENI}
				echo "	netmask ${VMNET_IFACE_NETMASK}" >> ${ENI}
				echo "	broadcast ${VMNET_IFACE_BROADCAST}" >> ${ENI}
				if [ "${SE_MTU}" ] ; then
					echo "	mtu ${SE_MTU}" >> ${ENI}
				fi
				echo "" >> ${ENI}

			else
				if [ -n "${SE_OVSBR}" ] ; then
					INTERFACE=${SE_OVSBR}
					echo "# Interface ${SE_OVSBR}" >> ${ENI}
					echo "auto ${SE_OVSBR}" >> ${ENI}
				else
					INTERFACE=${SE_IFACE0}
					echo "# Interface ${INTERFACE}" >> ${ENI}
					echo "allow-hotplug ${INTERFACE}" >> ${ENI}
				fi
				echo "iface ${INTERFACE} inet static" >> ${ENI}
				if [ -n "${SE_OVSBR}" ] ; then
					echo "	ovs_type OVSBridge" >> ${ENI}
					echo "	ovs_ports ${SE_IFACE0}" >> ${ENI}
				fi
				echo "	address ${IFACE_ADDR}" >> ${ENI}
				echo "	network ${IFACE_NETWORK}" >> ${ENI}
				echo "	netmask ${IFACE_NETMASK}" >> ${ENI}
				echo "	broadcast ${IFACE_BROADCAST}" >> ${ENI}
				if [ -n "${SE_GW}" ] ; then
					echo "	gateway ${SE_GW}" >> ${ENI}
				fi
				if [ "${SE_MTU}" ] ; then
					echo "	mtu ${SE_MTU}" >> ${ENI}
				fi
				if [ -n "${SE_DNS}" ] ; then
					echo "	dns-nameservers ${SE_ALL_NS}" >> ${ENI}
				fi
				if [ -n "${SE_DNSSEARCH}" ] ; then
					echo "	dns-search ${SE_DNSSEARCH}" >> ${ENI}
				fi
				echo "" >> ${ENI}
				if [ -n "${SE_OVSBR}" ] ; then
					echo "allow-${SE_OVSBR} ${SE_IFACE0}" >> ${ENI}
					echo "iface ${SE_IFACE0} inet manual" >> ${ENI}
					echo "	ovs_bridge ${SE_OVSBR}" >> ${ENI}
					echo "	ovs_type OVSPort" >> ${ENI}
					echo "" >> ${ENI}
				fi
			fi
		;;
		"bond")
			INTERFACE=bond${BOND_NUMBER}
			BOND_NUMBER=$(( ${BOND_NUMBER} + 1 ))
			if [ "${RELEASE}" = "wheezy" ] || [ "${RELEASE}" = "stretch" ] || [ "${RELEASE}" = "buster" ] ; then
				# Iface 0
				echo "# Interface ${SE_IFACE0}" >> ${ENI}
				echo "auto ${SE_IFACE0}" >> ${ENI}
				echo "iface ${SE_IFACE0} inet manual" >> ${ENI}
				echo "	bond-master ${INTERFACE}" >> ${ENI}
				echo "" >> ${ENI}
				# Iface 1
				echo "# Interface ${SE_IFACE1}" >> ${ENI}
				echo "auto ${SE_IFACE1}" >> ${ENI}
				echo "iface ${SE_IFACE1} inet manual" >> ${ENI}
				echo "	bond-master ${INTERFACE}" >> ${ENI}
				echo "" >> ${ENI}
			fi

			# Bridge
			echo "# Interface ${INTERFACE}" >> ${ENI}
			echo "auto ${INTERFACE}" >> ${ENI}
			echo "iface ${INTERFACE} inet static" >> ${ENI}
			echo "	address ${IFACE_ADDR}" >> ${ENI}
			echo "	network ${IFACE_NETWORK}" >> ${ENI}
			echo "	netmask ${IFACE_NETMASK}" >> ${ENI}
			echo "	broadcast ${IFACE_BROADCAST}" >> ${ENI}
			if [ -n "${SE_GW}" ] ; then
				echo "	gateway ${SE_GW}" >> ${ENI}
			fi
			if [ "${SE_MTU}" ] ; then
				echo "	mtu ${SE_MTU}" >> ${ENI}
			fi
			if [ -n "${SE_DNS}" ] ; then
				echo "	dns-nameservers ${SE_ALL_NS}" >> ${ENI}
			fi
			if [ -n "${SE_DNSSEARCH}" ] ; then
				echo "	dns-search ${SE_DNSSEARCH}" >> ${ENI}
			fi
			echo "	bond-mode 802.3ad" >> ${ENI}
			echo "	bond-miimon 100" >> ${ENI}
			echo "	bond-lacp-rate 1" >> ${ENI}
			echo "	bond-slaves ${SE_IFACE0} ${SE_IFACE1}" >> ${ENI}
			echo "	bond_xmit_hash_policy layer3+4" >> ${ENI}
			echo "" >> ${ENI}
		;;
		"bondvlan")
			INTERFACE=bond${BOND_NUMBER}
			BOND_NUMBER=$(( ${BOND_NUMBER} + 1 ))
			if [ -z "${SE_OVSBR}" ] ; then
				SE_OVSBR=br-ex
			fi
			if [ "${SE_USE_OVS_IFACES}" = "yes" ] ; then
				# Iface 0
				echo "# Interface ${SE_IFACE0}" >> ${ENI}
				echo "allow-${INTERFACE} ${SE_IFACE0}" >> ${ENI}
				echo "iface ${SE_IFACE0} inet manual" >> ${ENI}
				echo "	ovs_type OVSPort" >> ${ENI}
				echo "	ovs_bonds ${INTERFACE}" >> ${ENI}
				if [ -n "${SE_MTU}" ] ; then
					echo "	up /bin/ip link set mtu ${SE_MTU} dev ${SE_IFACE0}" >> ${ENI}
				fi
				echo "" >> ${ENI}

				# Iface 1
				echo "# Interface ${SE_IFACE1}" >> ${ENI}
				echo "allow-${INTERFACE} ${SE_IFACE1}" >> ${ENI}
				echo "iface ${SE_IFACE1} inet manual" >> ${ENI}
				echo "	ovs_type OVSPort" >> ${ENI}
				echo "	ovs_bonds ${INTERFACE}" >> ${ENI}
				if [ -n "${SE_MTU}" ] ; then
					echo "	up /bin/ip link set mtu ${SE_MTU} dev ${SE_IFACE1}" >> ${ENI}
				fi
				echo >> ${ENI}

				# Ze bond
				echo "# Interface ${INTERFACE}" >> ${ENI}
				echo "auto ${INTERFACE}" >> ${ENI}
				echo "allow-${SE_OVSBR} ${INTERFACE}" >> ${ENI}
				echo "iface ${INTERFACE} inet manual" >> ${ENI}
				echo "	ovs_bridge ${SE_OVSBR}" >> ${ENI}
				echo "	ovs_type OVSBond" >> ${ENI}
				echo "	ovs_bonds ${SE_IFACE0} ${SE_IFACE1}" >> ${ENI}
				echo "	ovs_options bond_mode=balance-tcp lacp=active other_config:lacp-time=fast" >> ${ENI}
				if [ -n "${SE_MTU}" ] ; then
					echo "	ovs_mtu ${SE_MTU}" >> ${ENI}
				fi
				echo "	up ifup ${SE_IFACE0}" >> ${ENI}
				echo "	up ifup ${SE_IFACE1}" >> ${ENI}
				if [ -n "${SE_MTU}" ] ; then
					echo "	up ovs-vsctl set Interface \${IFACE} mtu_request=${SE_MTU}" >> ${ENI}
					echo "	up /bin/sleep 1 ; /bin/ip link set mtu ${SE_MTU} dev ${INTERFACE}" >> ${ENI}
				fi
				echo "" >> ${ENI}

				# First VLAN (and maybe unique?)
				echo "# Interface vlan${SE_VLANNUM}" >> ${ENI}
				echo "auto vlan${SE_VLANNUM}" >> ${ENI}
				echo "allow-${SE_OVSBR} vlan${SE_VLANNUM}" >> ${ENI}
				echo "iface vlan${SE_VLANNUM} inet static" >> ${ENI}
				echo "	ovs_type OVSIntPort" >> ${ENI}
				echo "	ovs_bridge ${SE_OVSBR}" >> ${ENI}
				echo "	ovs_options tag=${SE_VLANNUM}" >> ${ENI}
				echo "	ovs_extra set interface \${IFACE} external-ids:iface-id=\$(hostname -s)-\${IFACE}-vif" >> ${ENI}
				if [ -n "${SE_MTU}" ] ; then
					echo "	ovs_mtu ${SE_MTU}" >> ${ENI}
				fi
				echo "	address ${IFACE_ADDR}" >> ${ENI}
				echo "	network ${IFACE_NETWORK}" >> ${ENI}
				echo "	netmask ${IFACE_NETMASK}" >> ${ENI}
				echo "	broadcast ${IFACE_BROADCAST}" >> ${ENI}
				if [ -n "${SE_GW}" ] ; then
					echo "	gateway ${SE_GW}" >> ${ENI}
				fi
				echo "" >> ${ENI}

				# The VLAN for vxlan traffic, if present
				if [ -n "${SE_VMNET_ADDR}" ] ; then
					echo "# Interface vlan${SE_VMNET_VLAN}" >> ${ENI}
					echo "auto vlan${SE_VMNET_VLAN}" >> ${ENI}
					echo "allow-${SE_OVSBR} vlan${SE_VMNET_VLAN}" >> ${ENI}
					echo "iface vlan${SE_VMNET_VLAN} inet static" >> ${ENI}
					echo "	ovs_type OVSIntPort" >> ${ENI}
					echo "	ovs_bridge ${SE_OVSBR}" >> ${ENI}
					echo "	ovs_options tag=${SE_VMNET_VLAN}" >> ${ENI}
					echo "	vs_extra set interface \${IFACE} external-ids:iface-id=\$(hostname -s)-\${IFACE}-vif" >> ${ENI}
					if [ -n "${SE_MTU}" ] ; then
						echo "	ovs_mtu ${SE_MTU}" >> ${ENI}
					fi
					echo "	address ${VMNET_IFACE_ADDR}" >> ${ENI}
					echo "	network ${VMNET_IFACE_NETWORK}" >> ${ENI}
					echo "	netmask ${VMNET_IFACE_NETMASK}" >> ${ENI}
					echo "	broadcast ${VMNET_IFACE_BROADCAST}" >> ${ENI}
				fi
				echo "" >> ${ENI}

				echo "auto ${SE_OVSBR}" >> ${ENI}
				echo "iface ${SE_OVSBR} inet manual" >> ${ENI}
				echo "	ovs_type OVSBridge" >> ${ENI}
				if [ -z "${SE_VMNET_ADDR}" ] ; then
					echo "	ovs_ports bond0 vlan${SE_VLANNUM}" >> ${ENI}
				else
					echo "	ovs_ports bond0 vlan${SE_VLANNUM} vlan${SE_VMNET_VLAN}" >> ${ENI}
				fi
				if [ -n "${SE_MTU}" ] ; then
					echo "	ovs_mtu ${SE_MTU}" >> ${ENI}
				fi
				echo "" >> ${ENI}
			else
				if [ "${RELEASE}" = "wheezy" ] || [ "${RELEASE}" = "stretch" ] || [ "${RELEASE}" = "buster" ] ; then
					# Iface 0
					echo "# Interface ${SE_IFACE0}" >> ${ENI}
					echo "auto ${SE_IFACE0}" >> ${ENI}
					echo "iface ${SE_IFACE0} inet manual" >> ${ENI}
					echo "	bond-master ${INTERFACE}" >> ${ENI}
					echo "" >> ${ENI}
					# Iface 1
					echo "# Interface ${SE_IFACE1}" >> ${ENI}
					echo "auto ${SE_IFACE1}" >> ${ENI}
					echo "iface ${SE_IFACE1} inet manual" >> ${ENI}
					echo "	bond-master ${INTERFACE}" >> ${ENI}
					echo "" >> ${ENI}
				fi

				# Bonding interface
				echo "# Interface ${INTERFACE}" >> ${ENI}
				echo "auto ${INTERFACE}" >> ${ENI}
				echo "iface ${INTERFACE} inet manual" >> ${ENI}
				if [ -n "${SE_DNS}" ] ; then
					echo "	dns-nameservers ${SE_ALL_NS}" >> ${ENI}
				fi
				if [ -n "${SE_DNSSEARCH}" ] ; then
					echo "	dns-search ${SE_DNSSEARCH}" >> ${ENI}
				fi
				echo "	bond-mode 802.3ad" >> ${ENI}
				echo "	bond-miimon 100" >> ${ENI}
				echo "	bond-lacp-rate 1" >> ${ENI}
				echo "	bond-slaves ${SE_IFACE0} ${SE_IFACE1}" >> ${ENI}
				echo "	bond_xmit_hash_policy layer3+4" >> ${ENI}
				if [ "${SE_EXTRA_OVS}" = "yes" ] ; then
					echo "	up ifup ${SE_OVSBR}" >> ${ENI}
				fi
				if [ -n "${SE_MTU}" ] ; then
					echo "	mtu 9000" >> ${ENI}
				fi
				echo "" >> ${ENI}

				# a vlan device using the bond interface
				echo "# Interface vlan${SE_VLANNUM}" >> ${ENI}
				echo "auto vlan${SE_VLANNUM}" >> ${ENI}
				echo "iface vlan${SE_VLANNUM} inet static" >> ${ENI}
				echo "	vlan-raw-device ${INTERFACE}" >> ${ENI}
				echo "	pre-up ip link set up dev ${SE_IFACE0}" >> ${ENI}
				echo "	pre-up ip link set up dev ${SE_IFACE1}" >> ${ENI}
				echo "	address ${IFACE_ADDR}" >> ${ENI}
				echo "	network ${IFACE_NETWORK}" >> ${ENI}
				echo "	netmask ${IFACE_NETMASK}" >> ${ENI}
				echo "	broadcast ${IFACE_BROADCAST}" >> ${ENI}
				if [ -n "${SE_GW}" ] ; then
					echo "	gateway ${SE_GW}" >> ${ENI}
				fi
				if [ -n "${SE_MTU}" ] ; then
					echo "	mtu 9000" >> ${ENI}
				fi
				echo "" >>${ENI}


				if [ -n "${SE_VMNET_ADDR}" ] ; then
					echo "# Interface vlan${SE_VMNET_VLAN}" >> ${ENI}
					echo "auto vlan${SE_VMNET_VLAN}" >> ${ENI}
					echo "iface vlan${SE_VMNET_VLAN} inet static" >> ${ENI}
					echo "	vlan-raw-device ${INTERFACE}" >> ${ENI}
					echo "	pre-up ip link set up dev ${SE_IFACE0}" >> ${ENI}
					echo "	pre-up ip link set up dev ${SE_IFACE1}" >> ${ENI}
					echo "	address ${VMNET_IFACE_ADDR}" >> ${ENI}
					echo "	network ${VMNET_IFACE_NETWORK}" >> ${ENI}
					echo "	netmask ${VMNET_IFACE_NETMASK}" >> ${ENI}
					echo "	broadcast ${VMNET_IFACE_BROADCAST}" >> ${ENI}
					if [ -n "${SE_MTU}" ] ; then
						echo "	mtu 9000" >> ${ENI}
					fi
					echo "" >>${ENI}

				fi
				if [ "${SE_EXTRA_OVS}" = "yes" ] ; then
					echo "auto ${SE_OVSBR}" >> ${ENI}
					echo "iface ${SE_OVSBR} inet manual" >> ${ENI}
					echo "	ovs_type OVSBridge" >> ${ENI}
					echo "	ovs_ports ${INTERFACE}" >> ${ENI}
					echo "	up ovs-vsctl add-port ${SE_OVSBR} ${INTERFACE} || true" >> ${ENI}
					echo "" >> ${ENI}
				fi
			fi
		;;
		"bondvlanbridge")
			INTERFACE=bond${BOND_NUMBER}
			BOND_NUMBER=$(( ${BOND_NUMBER} + 1 ))
			if [ "${RELEASE}" = "wheezy" ] || [ "${RELEASE}" = "stretch" ] || [ "${RELEASE}" = "buster" ] ; then
				# Iface 0
				echo "# Interface ${SE_IFACE0}" >> ${ENI}
				echo "auto ${SE_IFACE0}" >> ${ENI}
				echo "iface ${SE_IFACE0} inet manual" >> ${ENI}
				echo "	bond-master ${INTERFACE}" >> ${ENI}
				echo "" >> ${ENI}
				# Iface 1
				echo "# Interface ${SE_IFACE1}" >> ${ENI}
				echo "auto ${SE_IFACE1}" >> ${ENI}
				echo "iface ${SE_IFACE1} inet manual" >> ${ENI}
				echo "	bond-master ${INTERFACE}" >> ${ENI}
				echo "" >> ${ENI}
			fi

			# Bond iface
			echo "# Interface ${INTERFACE}" >> ${ENI}
			echo "auto ${INTERFACE}" >> ${ENI}
			echo "iface ${INTERFACE} inet manual" >> ${ENI}
			echo "	bond-mode 802.3ad" >> ${ENI}
			echo "	bond-miimon 100" >> ${ENI}
			echo "	bond-lacp-rate 1" >> ${ENI}
			echo "	bond-slaves ${SE_IFACE0} ${SE_IFACE1}" >> ${ENI}
			echo "	bond_xmit_hash_policy layer3+4" >> ${ENI}
			if [ -n "${SE_MTU}" ] ; then
				echo "	mtu 9000" >> ${ENI}
			fi
			echo "" >> ${ENI}
			# Vlan
			echo "# Interface vlan${SE_VLANNUM}" >> ${ENI}
			echo "auto vlan${SE_VLANNUM}" >> ${ENI}
			echo "iface vlan${SE_VLANNUM} inet manual" >> ${ENI}
			echo "	vlan-raw-device ${INTERFACE}" >> ${ENI}
			if [ -n "${SE_MTU}" ] ; then
				echo "	mtu 9000" >> ${ENI}
			fi
			echo "" >> ${ENI}
			# Bridge
			echo "# Interface ${SE_BRNAME}" >> ${ENI}
			echo "auto ${SE_BRNAME}" >> ${ENI}
			echo "iface ${SE_BRNAME} inet static" >> ${ENI}
			echo "	bridge_ports vlan${SE_VLANNUM}" >> ${ENI}
			echo "	bridge_maxwait 0" >> ${ENI}
			echo "  pre-up ip link set up dev ${SE_IFACE0}" >> ${ENI}
			echo "  pre-up ip link set up dev ${SE_IFACE1}" >> ${ENI}
			echo "	address ${IFACE_ADDR}" >> ${ENI}
			echo "	network ${IFACE_NETWORK}" >> ${ENI}
			echo "	netmask ${IFACE_NETMASK}" >> ${ENI}
			echo "	broadcast ${IFACE_BROADCAST}" >> ${ENI}
			if [ -n "${SE_GW}" ] ; then
				echo "	gateway ${SE_GW}" >> ${ENI}
			fi
			if [ -n "${SE_DNS}" ] ; then
				echo "	dns-nameservers ${SE_ALL_NS}" >> ${ENI}
			fi
			if [ -n "${SE_DNSSEARCH}" ] ; then
				echo "	dns-search ${SE_DNSSEARCH}" >> ${ENI}
			fi
			if [ -n "${SE_MTU}" ] ; then
				echo "	mtu 9000" >> ${ENI}
			fi
			echo "" >> ${ENI}
		;;
		esac
	done
	if echo "${STATIC_ETH}" | grep -q bond ; then
		mkdir -p ${MOUNT_DIR}/etc/modprobe.d
		echo "options bonding mode=4 lacp_rate=1 xmit_hash_policy=layer3+4" >${MOUNT_DIR}/etc/modprobe.d/bonding.conf
	fi
else
# If no --static-iface param is set, then DHCP by default
	echo "# The normal eth0
allow-hotplug eth0
iface eth0 inet dhcp

# Additional interfaces, just in case we're using
# multiple networks
allow-hotplug eth1
iface eth1 inet dhcp

allow-hotplug eth2
iface eth2 inet dhcp

# Set this one last, so that cloud-init or user can
# override defaults.
source /etc/network/interfaces.d/*
" >> ${MOUNT_DIR}/etc/network/interfaces
fi

if [ "${HAS_BGP_TO_THE_HOST}" = "yes" ] ; then
	# Ensure the BGP daemon will run
	sed -i 's/bgpd=.*/bgpd=yes/' ${MOUNT_DIR}/etc/frr/daemons

	echo "log syslog informational

!
service integrated-vtysh-config
!
log syslog informational
!
int lo" >>${MOUNT_DIR}/etc/frr/frr.conf
	for i in $(echo ${BGP_IP_LIST} | tr ',' ' ') ; do
		LOIPTOADD=$(echo ${i} | cut -d/ -f1)
		echo " ip address ${LOIPTOADD}/32" >>${MOUNT_DIR}/etc/frr/frr.conf
	done
	echo "!" >>${MOUNT_DIR}/etc/frr/frr.conf

	ROUTER_ID=$(echo ${BGP_IP_LIST} | cut -d, -f1 | cut -d/ -f1)

	echo "router bgp ${BGP_ASNUM}
 bgp router-id ${ROUTER_ID}
 bgp bestpath as-path multipath-relax
 bgp bestpath compare-routerid
 neighbor pg-leaf peer-group
 neighbor pg-leaf remote-as external
 neighbor pg-leaf capability extended-nexthop" >>${MOUNT_DIR}/etc/frr/frr.conf
	for i in $(echo ${BGP_IFACE_LIST} | tr ',' ' ') ; do
		echo " neighbor ${i} interface peer-group pg-leaf" >>${MOUNT_DIR}/etc/frr/frr.conf
	done
	echo " !
 address-family ipv4 unicast
  redistribute connected route-map map-redistribute
  neighbor pg-leaf soft-reconfiguration inbound
  neighbor pg-leaf route-map map-leaf-in in
  neighbor pg-leaf route-map map-leaf-out out
 exit-address-family
 !
 address-family ipv6 unicast
  redistribute connected route-map map-redistribute
  neighbor pg-leaf activate
  neighbor pg-leaf soft-reconfiguration inbound
  neighbor pg-leaf route-map map-leaf-in in
  neighbor pg-leaf route-map map-leaf-out out
 exit-address-family
!
route-map map-redistribute permit 10
 match interface lo
!
route-map map-leaf-out permit 10
 match interface lo
!
route-map map-leaf-in permit 10
!
" >>${MOUNT_DIR}/etc/frr/frr.conf
fi

mkdir -p ${MOUNT_DIR}/etc/udev/rules.d
echo '# set deadline scheduler for all sdX disks
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/scheduler}="deadline"
' >${MOUNT_DIR}/etc/udev/rules.d/60-deadline-scheduler-to-all-sdx.rules

# Setup the default hostname (will be set by cloud-init at boot,
# though for installing real hardware, we do care)
if [ -z "${HOSTNAME}" ] ; then
	HOSTNAME="debian.example.com"
fi
echo "${HOSTNAME}" >${MOUNT_DIR}/etc/hostname
echo "127.0.0.1	localhost
127.0.1.1	${HOSTNAME}

::1	localhost ip6-localhost ip6-loopback
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
" >${MOUNT_DIR}/etc/hosts

# This should be a correct default everywhere
if [ "${INSTALL_NONFREE_REPO}" = yes ] ; then
	NON_FREE=" contrib non-free"
else
	NON_FREE=""
fi
echo "deb ${SOURCE_LIST_MIRROR} ${RELEASE} main${NON_FREE}
deb-src ${SOURCE_LIST_MIRROR} ${RELEASE} main${NON_FREE}" >${MOUNT_DIR}/etc/apt/sources.list

if [ "${RELEASE}" != "sid" ] && [ "${RELEASE}" != "unstable" ] ; then
	if [ "${RELEASE}" = "wheezy" ] || [ "${RELEASE}" = "jessie" ] || [ "${RELEASE}" = "stretch" ] || [ "${RELEASE}" = "buster" ] ; then
		SECURITY="/updates"
	else
		SECURITY="-security"
	fi
	echo "deb ${SOURCE_LIST_MIRROR} ${RELEASE}-updates main${NON_FREE}
deb-src ${SOURCE_LIST_MIRROR} ${RELEASE}-updates main${NON_FREE}
deb ${SECURITY_MIRROR_URL} ${RELEASE}${SECURITY} main${NON_FREE}
deb-src ${SECURITY_MIRROR_URL} ${RELEASE}${SECURITY} main${NON_FREE}
" >>${MOUNT_DIR}/etc/apt/sources.list
fi

if [ "${RELEASE}" = "jessie" ] && [ "${AZURE}" = "yes" ] ; then
	echo "deb ${SOURCE_LIST_MIRROR}-azure jessie-backports main${NON_FREE}
deb-src ${SOURCE_LIST_MIRROR}-azure jessie-backports main${NON_FREE}
" >>${MOUNT_DIR}/etc/apt/sources.list
fi

if [ "${AZURE}" = "yes" ] ; then
	chroot ${MOUNT_DIR} apt-key add - <<EOF
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1

mQENBFYWcbkBCADKvo4KT/ic3wb4AoNFtWvoS1Ae3NFcvM/6WR/n9BTsayOlnjDu
EFh7yH16nIhuO5pZFocY+32BWMEmiK6/0pkk1lB9+XfNB8yqDCJ/ItzADfuKQv6g
smfx4tLa1Vj+jUbrgiIG7MYTCPlpkSuPA+FgntlR4JBxOy2g4fqqp3of+xM8tfSN
4I7/g1989YU9EQN53c1HGLdsc5x5Y5Kezd46H4IK5oyri7BaG4zRzpJLYa4yxB2W
re+HXP0a5SN/zQq1oq8pvkPubEBPKhdypZzzoHWPkZqXh1pHsMMNRkwsLW/3iwzE
IjDKrbdILz3/b+iLLIvYo9RlTycRO0XeS/B3ABEBAAG0UkRlYmlhbiBmb3IgQXp1
cmUgQXJjaGl2ZSBBdXRvbWF0aWMgU2lnbmluZyBLZXkgKDgvamVzc2llKSA8bWlj
cm9zb2Z0QGNyZWRhdGl2LmNvbT6JAT4EEwECACgFAlYWcbkCGwMFCQPCZwAGCwkI
BwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEAbqSemobK1/2c8H/1j4HK/izt7aw7Kk
g+ChRDhltb4LiYTZNgHaBnLGkKewkA1vYIHQjdu/pVnJjh1JzvOBFV+rhJ4Cc60D
s4JDqkrl8LpA4jsLb/PW1bRtbW92mPfhWgjyWs6S2tRBsBy1m2+SLZKeaDUq/PCD
VnaClzDh2fQYimI8IQk5U/u8VHXtDm3qYQSq7dJMTTnDcBC1oCjEYN+uPm9M+tUI
ik2hIE4VmjIXYTQVTa1lD+qyJvZ9hCsBUxAGllFpcWlyexN5orer6c+30XY/0Y4i
Q+zzVPrp1s6MgM9F8ofgd2+MhL57fwyj2A+Tbyzm7xYhzPPMx/mopo4pi884+5lo
FY6A20E=
=X0jG
-----END PGP PUBLIC KEY BLOCK-----
EOF
fi

# From now on, always install the backports repo, except for not-yet-released suites
if [ "${RELEASE}" = "bookworm" ] || [ "${RELEASE}" = "trixie" ] || [ "${RELEASE}" = "sid" ] || [ "${RELEASE}" = "unstable" ] ; then
	echo "${RELEASE} do not have -backports, skipping setup..."
else
	echo "deb ${SOURCE_LIST_MIRROR} ${RELEASE}-backports main
deb-src ${SOURCE_LIST_MIRROR} ${RELEASE}-backports main
" >>${MOUNT_DIR}/etc/apt/sources.list
fi

chroot ${MOUNT_DIR} apt-get update
if [ "${AZURE}" = "yes" ] ; then
	chroot ${MOUNT_DIR} apt-get install -y -o Dpkg::Options::="--force-confnew" debian-azure-archive-keyring unscd
	chroot ${MOUNT_DIR} apt-get update
fi

if [ -n "${POSTINSTALL_PACKAGES}" ] ; then
	chroot ${MOUNT_DIR} apt-get install -y -o Dpkg::Options::="--force-confnew"  $(echo ${POSTINSTALL_PACKAGES} | tr "," " ")
fi

# Run dist-upgrade here - some security updates may involve installing
# packages with new names, like kernels with a new ABI chroot
chroot ${MOUNT_DIR} apt-get --no-install-recommends dist-upgrade -y -o Dpkg::Options::="--force-confnew" 

########################
### Install a kernel ###
########################
if [ "${RELEASE_NUM}" = "sid" ] || [ "${RELEASE_NUM}" -ge 10 ] && [ "${ARCH}" = "amd64" ] ; then
	if [ "${REAL_HARDWARE}" = "no" ] && [ "${CLOUD_KERNEL}" = "yes" ] ; then
		KERNEL_PACKAGE_NAME=linux-image-cloud-${ARCH}
	else
		KERNEL_PACKAGE_NAME=linux-image-${ARCH}
	fi
else
	KERNEL_PACKAGE_NAME=linux-image-${ARCH}
fi
if [ "${KERNEL_FROM_BACKPORTS}" = "yes" ] ; then
	BACKPORTS_CMD_LINE="-t ${RELEASE}-backports"
else
	BACKPORTS_CMD_LINE=""
fi
chroot ${MOUNT_DIR} apt-get install -y ${BACKPORTS_CMD_LINE} -o Dpkg::Options::="--force-confnew" ${KERNEL_PACKAGE_NAME}

###########################################
### Remove older releases of the kernel ###
###########################################
# Specifically remove all but the highest-versioned kernel
# image. Let's not waste space on older kernels we won't use...
OLD_KERNELS=$(COLUMNS=200 chroot ${MOUNT_DIR} dpkg -l | awk '/^ii  linux-image-[0-9]/ {print $2}' | sort -u | head -n -1)
NUM_KERNELS=$(echo $OLD_KERNELS | wc -w)
if [ $NUM_KERNELS -gt 0 ]; then
    echo "Removing old kernels: $OLD_KERNELS"
    chroot ${MOUNT_DIR} apt-get remove --purge -y $OLD_KERNELS
fi

# And run autoremove to remove any dependencies that might have been
# brought in too
echo "Running apt-get autoremove:"
chroot ${MOUNT_DIR} apt-get autoremove -y

# Setup cloud-init, cloud-utils and cloud-initramfs-growroot
# These are only available from backports in Wheezy
if [ "${RELEASE}" = "wheezy" ] ; then
	chroot ${MOUNT_DIR} apt-get -t wheezy-backports install -y -o Dpkg::Options::="--force-confnew" cloud-init cloud-utils cloud-initramfs-growroot
	cat > ${MOUNT_DIR}/etc/apt/preferences.d/linux.pref <<EOF
Package: linux-image-${ARCH} initramfs-tools
Pin: release n=wheezy-backports
Pin-Priority: 500
EOF
fi

##########################
### Install cloud init ###
##########################
if [ "${CLOUD_INIT}" = "yes" ] ; then
	if [ "${AZURE}" = "yes" ] ; then
		echo "# to update this file, run dpkg-reconfigure cloud-init
datasource_list: [Azure]" >${MOUNT_DIR}/etc/cloud/cloud.cfg.d/90_dpkg.cfg
	else
		# DigitalOcean is available in cloud-init only starting on Jessie and on
		# (ie: cloud-init >= 0.7.6)
		if ! [ "${RELEASE}" = "wheezy" ] ; then
			DIGITAL_OCEAN_SOURCE="DigitalOcean, "
		else
			DIGITAL_OCEAN_SOURCE=""
		fi
		echo "# to update this file, run dpkg-reconfigure cloud-init
datasource_list: [ NoCloud, AltCloud, ConfigDrive, OpenStack, CloudStack, ${DIGITAL_OCEAN_SOURCE} Ec2, MAAS, OVF, GCE, None ]" >${MOUNT_DIR}/etc/cloud/cloud.cfg.d/90_dpkg.cfg
	fi

	# Needed to have automatic mounts of /dev/vdb
	echo "mount_default_fields: [~, ~, 'auto', 'defaults,nofail', '0', '2']" >>${MOUNT_DIR}/etc/cloud/cloud.cfg
	echo "manage_etc_hosts: true" >>${MOUNT_DIR}/etc/cloud/cloud.cfg

	# Set the cloud init default user (required for the keypair to be put in the right home directory)
	sed -i "s/name: debian/name: ${USER_LOGIN}/" ${MOUNT_DIR}/etc/cloud/cloud.cfg
fi

if [ "${AZURE}" = "yes" ] ; then
	unshare --pid --fork --mount-proc chroot ${MOUNT_DIR} apt-get install -y -o Dpkg::Options::="--force-confnew" waagent
	rm -f ${MOUNT_DIR}/var/log/waagent.log
fi

# Setting-up initramfs
chroot ${MOUNT_DIR} update-initramfs -u

rm ${MOUNT_DIR}/var/cache/apt/archives/*.deb

# Set console for emergency and rescue shells
SYSTEMD_DIR="${MOUNT_DIR}/etc/systemd/system/"
for service in emergency.service rescue.service ; do
	mkdir "${SYSTEMD_DIR}/${service}.d"
	echo '[Service]
ExecStart=
ExecStart=-/bin/sh -c "/sbin/sulogin /dev/tty0; /bin/systemctl --fail --no-block default"' > "${SYSTEMD_DIR}/${service}.d/console.conf"
done

###################################
### Setting-up extlinux or grub ###
###################################
mkdir -p ${MOUNT_DIR}/boot/extlinux 
if [ "${RELEASE}" = "wheezy" ] ; then
	append="rootdelay=30"
fi

# In Buster, with the console activated on Qemu, everything is busted, so let's unbust.
if [ "${REAL_HARDWARE}" = "yes" ] && [ "${PROC_MANUFACTURER}" = "QEMU" ] ; then
	CONSOLE_PARAM="console=tty0"
else
	CONSOLE_PARAM="console=tty0 console=$CONSOLE,115200 earlyprintk=$CONSOLE,115200"
fi

KERNEL_PARAMS="text biosdevname=0 net.ifnames=0 ${CONSOLE_PARAM} consoleblank=0 systemd.show_status=true processor.max_cstate=0 systemd.unified_cgroup_hierarchy=false systemd.legacy_systemd_cgroup_controller=false $append"
if [ "${BOOTMANAGER}" = "grub" ] ; then
	sed -i -e 's|^[ #\t]*GRUB_CMDLINE_LINUX_DEFAULT[ #\t]*=.*|GRUB_CMDLINE_LINUX_DEFAULT="'"${KERNEL_PARAMS}"'"|' ${MOUNT_DIR}/etc/default/grub
	echo "
# openstack-debian-images disables OS prober to avoid
# loopback detection which breaks booting
GRUB_DISABLE_OS_PROBER=true" >>${MOUNT_DIR}/etc/default/grub

	if [ "${SERIAL_CONSOLE}" = "yes" ] ; then
		echo "GRUB_TERMINAL=\"console serial\"
GRUB_SERIAL_COMMAND=\"serial --unit=1 --speed=115200 --word=8 --parity=no --stop=1\"
" >>${MOUNT_DIR}/etc/default/grub
	fi

	# Tell grub about our loopback devices first
	mkdir -p ${MOUNT_DIR}/boot/grub
	mount --bind /dev ${MOUNT_DIR}/dev
	mount --bind /proc ${MOUNT_DIR}/proc
	mount --bind /sys ${MOUNT_DIR}/sys
	echo "grub-efi-${ARCH} grub2/force_efi_extra_removable boolean true" | chroot ${MOUNT_DIR} debconf-set-selections
	chroot ${MOUNT_DIR} grub-mkconfig -o /boot/grub/grub.cfg
	# Run grub from the chroot, pointing to the bind mounted /dev device.
	if [ -n "${RAID_DEVICES}" ] ; then
		for i in ${RAID_DEVICES} ; do
			chroot ${MOUNT_DIR} grub-install --target=${GRUB_TARGET} --no-nvram --force-extra-removable --no-floppy --modules="part_msdos part_gpt ${GRUB_MODULES}" --grub-mkdevicemap=/boot/grub/device.map /dev/${i}
		done
	else
		if [ "${REAL_HARDWARE}" = "no" ] ; then
			GRUB_DESTINATION_DEV=/dev/${LOOPRAW_DEVICE}
		else
			GRUB_DESTINATION_DEV=/dev/${DEST_HDD}
		fi
		chroot ${MOUNT_DIR} grub-install --target=${GRUB_TARGET} --no-nvram --force-extra-removable --no-floppy --modules="part_msdos part_gpt" --grub-mkdevicemap=/boot/grub/device.map ${GRUB_DESTINATION_DEV}
	fi
	umount ${MOUNT_DIR}/sys
	umount ${MOUNT_DIR}/dev
	umount ${MOUNT_DIR}/proc
else
	KERNEL_PARAMS="initrd=/initrd.img root=UUID=${UUID} ${KERNEL_PARAMS} ro"
	echo "default linux
timeout 1
label linux
kernel /vmlinuz
append ${KERNEL_PARAMS}" > ${MOUNT_DIR}/boot/extlinux/extlinux.conf
	extlinux --install ${MOUNT_DIR}/boot/extlinux
fi

##########################
### Configuring rescue ###
##########################
if [ "${BUILD_RESCUE_IMG}" = "yes" ] ; then
	sed -i 's/disable_root: .*/disable_root: False/' ${MOUNT_DIR}/etc/cloud/cloud.cfg
	sed -i 's/lock_passwd: .*/lock_passwd: False/' ${MOUNT_DIR}/etc/cloud/cloud.cfg
	sed -i "s/mount_default_fields: .*/mount_default_fields: [~, ~, 'auto', 'defaults,nobootwait,nofail', '0', '2']/" ${MOUNT_DIR}/etc/cloud/cloud.cfg
	echo 'ssh_pwauth: True' >>${MOUNT_DIR}/etc/cloud/cloud.cfg
fi

#####################
### Setup extrepo ###
#####################
if [ "${SETUP_EXTREPO}" = "yes" ] ; then
	chroot ${MOUNT_DIR} apt-get install -y extrepo
	chroot ${MOUNT_DIR} extrepo enable openstack_${EXTREPO_FLAVOR}
	chroot ${MOUNT_DIR} apt-get update
fi

if [ "${SETUP_OCTAVIA_AGENT}" = "yes" ] ; then
	chroot ${MOUNT_DIR} apt-get install -y cryptsetup acl apparmor at cloud-guest-utils cron curl dbus dmeventd ifenslave ifupdown iptables iputils-tracepath lsof net-tools netbase netcat-openbsd open-vm-tools rsyslog socat tcpdump uuid-runtime vim-tiny vlan debconf dbconfig-common gpg gpg-agent dirmngr keepalived ipvsadm iputils-ping haproxy ethtool
	chroot ${MOUNT_DIR} apt-get install -y octavia-agent anacron
	chroot ${MOUNT_DIR} update-rc.d haproxy disable
	chroot ${MOUNT_DIR} update-rc.d -f haproxy remove

	# Fix defaults of haproxy logrotate, so that we don't keep too much
	# log files, as the Amphora image is kind of super small.
	echo "/var/log/haproxy.log {
    hourly
    rotate 3
    missingok
    notifempty
    compress
    copytruncate
}" >${MOUNT_DIR}/etc/logrotate.d/haproxy
	# Call logrotate every hours, not just every day
	# othewrise logs can accumulate too fast and fill-up
	# the Amphora disk. Do it with both anacron + systemd timer.
	cp ${MOUNT_DIR}/etc/cron.daily/logrotate ${MOUNT_DIR}/etc/cron.hourly
	mkdir -p ${MOUNT_DIR}/etc/systemd/system/logrotate.timer.d
	echo "[Timer]
OnCalendar=hourly
" >${MOUNT_DIR}/etc/systemd/system/logrotate.timer.d/hourly.conf
fi

if [ "${SETUP_MANILA_AGENT}" = "yes" ] ; then
	# These are general purposes:
	chroot ${MOUNT_DIR} apt-get install -y crudini curl rpcbind iptables inetutils-ping net-tools qemu-guest-agent wget
	# These are for CEPHFS shares:
	chroot ${MOUNT_DIR} apt-get install -y fuse ceph-common ceph-fuse
	# These are for CIFS shares:
	chroot ${MOUNT_DIR} apt-get install -y samba samba-common samba-common-bin cifs-utils
	# This is for NFS
	chroot ${MOUNT_DIR} apt-get install -y nfs-kernel-server
	# This is for the CephFS + NFS:
	chroot ${MOUNT_DIR} apt-get install -y nfs-ganesha nfs-ganesha-ceph nfs-ganesha-gluster
	# Enable registry in samba config
	sed -i "s/\[global\]/\[global\]\\n\\n   include = registry\\n/g" ${MOUNT_DIR}/etc/samba/smb.conf

#	# Add manila-share
#	chroot ${MOUNT_DIR} apt-get install -y manila-share
fi

if [ "${SETUP_TROVE_AGENT}" = "yes" ] ; then
	chroot ${MOUNT_DIR} DEBIAN_FRONTEND=noninteractive apt-get install -y trove-guestagent acl apparmor apt-transport-https build-essential cloud-guest-utils anacron dbus dmeventd ethtool gpg-agent iptables iptables-persistent libxml2-dev libxslt1-dev libffi-dev libssl-dev libyaml-dev less logrotate netbase open-vm-tools openssh-client openssh-server pollinate psmisc python3-dev python3-pip python3-setuptools python3-sqlalchemy python3-venv rsync rsyslog ureadahead uuid-runtime sudo ca-certificates
# Useful only when testing
#	# Enable ssh as root in the image
#	sed -i "s/disable_root: true/disable_root: false/" ${MOUNT_DIR}/etc/cloud/cloud.cfg
#	sed -i 's/[#]PasswordAuthentication .*/PasswordAuthentication yes/' ${MOUNT_DIR}/etc/ssh/sshd_config
#	sed -i 's/[#]PermitRootLogin .*/PermitRootLogin yes/' ${MOUNT_DIR}/etc/ssh/sshd_config
#	# Allow password auth in the client
#	sed -i 's/[# ]*PasswordAuthentication .*/   PasswordAuthentication yes/' ${MOUNT_DIR}/etc/ssh/ssh_config

	# Add docker
	chroot ${MOUNT_DIR} DEBIAN_FRONTEND=noninteractive apt-get install -y docker.io
	# Add the trove username to docker group
	chroot ${MOUNT_DIR} usermod -aG docker trove

	# Add ip forwarding
	sed -i -r 's/^\s*#(net\.ipv4\.ip_forward=1.*)/\1/' ${MOUNT_DIR}/etc/sysctl.conf

	# /etc/sudoers.d/60_trove_guest
	echo "trove ALL=(ALL) NOPASSWD:ALL" >${MOUNT_DIR}/etc/sudoers.d/60_trove_guest
	chmod 0440 ${MOUNT_DIR}/etc/sudoers.d/60_trove_guest
	chown root:root ${MOUNT_DIR}/etc/sudoers.d/60_trove_guest
fi

###################
### HOOK SCRIPT ###
###################
if [ -x ${HOOK_SCRIPT} ] ; then
	export BODI_CHROOT_PATH=${MOUNT_DIR}
	export BODI_RELEASE=${RELEASE}
	${HOOK_SCRIPT}
fi

######################################
### Generate the package list file ###
######################################
if [ "${GEN_PKG_LIST}" = yes ] ; then
	chroot ${MOUNT_DIR} /usr/bin/dpkg-query -W --showformat '${source:Package} ${source:Version}\n' | sort -u >${OUTPUT}-packages.list
fi

##########################
### Unmount everything ###
##########################

cleanup(){
	# refine cleanup everything was ok
	echo "Finished."
} 

sync
chroot ${MOUNT_DIR} umount /proc || true
chroot ${MOUNT_DIR} umount /sys || true
chroot ${MOUNT_DIR} umount /boot/efi || true

# Defrag the filesystem to allow for better size reduction below
e4defrag ${DEST_PART} > /dev/null
umount ${MOUNT_DIR}

# Run FSCK so that resize can work
fsck.ext4 -f ${DEST_PART} || true

if [ "${AUTOMATIC_RESIZE}" = "yes" ] ; then
	resize2fs -M /dev/mapper/${LOOP_DEVICE}
	FS_BLOCKS=`tune2fs -l /dev/mapper/${LOOP_DEVICE} | awk '/Block count/{print $3}'`
	WANTED_SIZE=`expr $FS_BLOCKS '*' 4 '/' 1024 + ${AUTOMATIC_RESIZE_SPACE}` # Add ${AUTOMATIC_RESIZE_SPACE}M
	resize2fs /dev/mapper/${LOOP_DEVICE} ${WANTED_SIZE}M
	FINAL_FS_BLOCKS=`tune2fs -l /dev/mapper/${LOOP_DEVICE} | awk '/Block count/{print $3}'`	
fi

sync
sleep 5

if [ "${REAL_HARDWARE}" = "no" ] ; then
	kpartx -d ${RAW_NAME}
fi
rmdir ${MOUNT_DIR}

if [ "${AUTOMATIC_RESIZE}" = "yes" ] ; then
	if [ "${BOOTTYPE}" = "mbr" ] ; then
		# some blocks for mbr and multiple block size (4k)
		FINAL_IMG_SIZE=`expr '(' $FINAL_FS_BLOCKS + 258 ')' '*' 4 '/' 1024`
		# Rebuild a smaller partition table
		${PARTED} -s ${RAW_NAME} rm 1
		${PARTED} -s ${RAW_NAME} mkpart primary ext4 1Mi ${FINAL_IMG_SIZE}Mi
		${PARTED} -s ${RAW_NAME} set 1 boot on
		# Add 2M for the 1M at the beginning of the partition and some additional space
		truncate -s `expr 3 + ${FINAL_IMG_SIZE}`M ${RAW_NAME}
		install-mbr ${RAW_NAME}
	else # uefi
		# Work out the sizes of the new image
		# 1M for the GPT header, and alignment padding
		# 100M for the ESP
		# $FINAL_FS_BLOCKS for the root partition
		FINAL_IMG_SIZE=$((1 + 100 + $((${FINAL_FS_BLOCKS} * 4 / 1024)) + 1))
		# Rebuild a smaller partition table
		${PARTED} -s ${RAW_NAME} rm 2
		${PARTED} -s -a optimal ${RAW_NAME} -- mkpart ROOT ext4 102Mi -64s
		# Add 1M padding
		truncate -s $((1 + ${FINAL_IMG_SIZE}))M ${RAW_NAME}
	fi
fi

if [ "${REAL_HARDWARE}" = "no" ] && [ "${BUILD_QCOW2}" = "yes" ] ; then
	if ! [ "${AZURE}" = "yes" ] ; then
		QEMU_VERSION=`qemu-img --help | head -n 1 | cut -d" " -f3 | cut -d"," -f1`
		if dpkg --compare-versions ${QEMU_VERSION} gt 1.0 ; then
			OTHER_QEMU_IMG_OPTIONS=" -o compat=0.10"
		else
			OTHER_QEMU_IMG_OPTIONS=""
		fi

		if [ "${NEWER_QEMU}" = "yes" ] ; then
			qemu-img convert -c -p -W -m 8 -f raw ${RAW_NAME} -O qcow2 ${QCOW2_NAME}
		else
			qemu-img convert -c -f raw ${RAW_NAME}${OTHER_QEMU_IMG_OPTIONS} -O qcow2 ${QCOW2_NAME}
		fi
	fi
fi

if [ -n "${RAID_DEVICES}" ] ; then
	mdadm --stop /dev/md0
fi

if [ "${GEN_SRC_TAR}" = yes ] ; then
	if [ "${RELEASE}" = "stretch" ] ; then
		rm -f Release Release.gpg
		wget -q ${DEB_MIRROR}/dists/${RELEASE}/Release -O Release
		wget -q ${DEB_MIRROR}/dists/${RELEASE}/Release.gpg -O Release.gpg
		gpg --no-default-keyring --keyring /usr/share/keyrings/debian-archive-keyring.gpg --verify Release.gpg Release 2>&1 | grep "Good signature from"
	else
		rm -f InRelease Release Release.gpg
		wget ${DEB_MIRROR}/dists/${RELEASE}/InRelease -O InRelease
		gpg --no-default-keyring --keyring /usr/share/keyrings/debian-archive-keyring.gpg --verify InRelease 2>&1 | grep "Good signature from"
		cp InRelease Release.gpg
		gpg --no-default-keyring --keyring /usr/share/keyrings/debian-archive-keyring.gpg Release.gpg || true
		rm -f Release.gpg
	fi
	SOURCES_GZ_SHA256=$(cat Release | grep main/source/Sources.gz | tail -n 1 | awk '{print $1}')
	rm Release

	rm -f Sources.gz
	wget -q ${DEB_MIRROR}/dists/${RELEASE}/main/source/Sources.gz -O Sources.gz
	CHECK=$(sha256sum Sources.gz  | awk '{print $1}')
	if [ "${SOURCES_GZ_SHA256}" != "${CHECK}" ] ; then
		echo "SHA256 sums are not equal: authentification error, exiting..."
		exit 1
	else
		echo "Authentic Sources.gz"
	fi
	# Delete Sources before unpackgin Sources.gz, just in case
	# a file was there from previous runs...
	rm -f Sources
	gzip -d Sources.gz

	# Get the security Sources file, if we're not build the source tarball for an unstable image
	if [ "${RELEASE}" != "sid" ] && [ "${RELEASE}" != "unstable" ] ; then
		if [ "${RELEASE}" = "wheezy" ] || [ "${RELEASE}" = "jessie" ] || [ "${RELEASE}" = "stretch" ] || [ "${RELEASE}" = "buster" ] ; then
			SECURITY="/updates"
		else
			SECURITY="-security"
		fi
		rm -f SecurityRelease SecurityRelease.gpg SecurityInRelease
		wget -q ${SECURITY_MIRROR_URL}/dists/${RELEASE}${SECURITY}/InRelease -O SecurityInRelease
		gpg --no-default-keyring --keyring /usr/share/keyrings/debian-archive-keyring.gpg --verify SecurityInRelease 2>&1 | grep "Good signature from"
		cp SecurityInRelease SecurityRelease.gpg
		gpg --no-default-keyring --keyring /usr/share/keyrings/debian-archive-keyring.gpg SecurityRelease.gpg || true
		rm -f SecurityRelease.gpg SecurityInRelease

		SECURITY_SOURCES_GZ_SHA256=$(cat SecurityRelease | grep main/source/Sources.gz | tail -n 1 | awk '{print $1}')
		rm -f SecuritySources.gz
		wget -q ${SECURITY_MIRROR_URL}/dists/${RELEASE}${SECURITY}/main/source/Sources.gz -O SecuritySources.gz
		SECURITY_CHECK=$(sha256sum SecuritySources.gz  | awk '{print $1}')
		if [ "${SECURITY_SOURCES_GZ_SHA256}" != "${SECURITY_CHECK}" ] ; then
			echo "SHA256 sums for the debian-security Sources.gz are not equal: authentification error, exiting..."
			exit 1
		else
			echo "Authentic SecuritySources.gz"
		fi
		rm -f SecuritySources SecurityRelease
		gzip -d SecuritySources.gz
	fi

	rm -rf source
	mkdir source
	cd source

	for PKG_FULL in $(cat ../${OUTPUT}-packages.list | tr ' ' ',') ; do
		SRC_PKG=$(echo ${PKG_FULL} | cut -d, -f1)

		# Get the orig filename and directory of the source package
		LINE_START=$(cat ../Sources | grep -n '^Package: '${SRC_PKG}'$' | tail -n 1 | cut -d: -f1)

		# We check the security repository, to see if the package is there.
		SECURITY_LINE_START=""
		if [ -e ../SecuritySources ] ; then
			SECURITY_LINE_START=$(cat ../SecuritySources | grep -n '^Package: '${SRC_PKG}'$' | tail -n 1 | cut -d: -f1)
		fi

		# If the package is in the security repo, then we must decide which
		# one is the highest: security or normal point release.
		USE_SECURITY_VERSION=no
		FROM_FILE=../Sources
		LINE_START_REAL=${LINE_START}
		if [ -n "${SECURITY_LINE_START}" ] ; then
			SECURITY_TOT_NUM_LINES=$(cat ../Sources | wc -l)
			SECURITY_TO_END=$((${SECURITY_TOT_NUM_LINES} - ${SECURITY_LINE_START}))
			SECURITY_VERSION=$(tail -n ${SECURITY_TO_END} ../SecuritySources | grep '^Version: ' | head -n1 | sed -e 's/Version: //')

			TOT_NUM_LINES=$(cat ../Sources | wc -l)
			TO_END=$((${TOT_NUM_LINES} - ${LINE_START}))
			REL_VERSION=$(tail -n ${TO_END} ../SecuritySources | grep '^Version: ' | head -n1 | sed -e 's/Version: //')
			# If security version is higher, we use the security version
			if dpkg --compare-versions ${REL_VERSION} lt ${SECURITY_VERSION} ; then
				USE_SECURITY_VERSION=yes
				FROM_FILE=../SecuritySources
				LINE_START_REAL=${SECURITY_LINE_START}
			fi
		fi

		# TODO: LINE_START may be empty if a package is installed from: backports, extrepo, etc.
		if [ -n "${LINE_START}" ] ; then
			TOT_NUM_LINES=$(cat ${FROM_FILE} | wc -l)
			TO_END=$((${TOT_NUM_LINES} - ${LINE_START_REAL}))
			END_OF_ENTRY=$(tail -n ${TO_END} ${FROM_FILE} | grep -n '^$' | head -n1 | cut -d: -f1)

			# Isolate this source package entry as temp file
			SOURCES_ENTRY=$(mktemp -t build-openstack-debian-image.sources-entry.XXXXXX)
			tail -n ${TO_END} ${FROM_FILE} | head -n ${END_OF_ENTRY} >${SOURCES_ENTRY}

			# Get .dsc filename and directory path
			DSC_FILENAME=$(cat ${SOURCES_ENTRY} | grep .dsc | head -n1 | awk '{print $3}')
			DIRECTORY=$(cat ${SOURCES_ENTRY} | grep '^Directory: ' | sed -e 's/^Directory: //')

			# Get the list of SHA256 sums
			SHA256_START=$(grep -n -E '^Checksums-Sha256:' ${SOURCES_ENTRY} | cut -d: -f1)
			TOTAL_ENTRY_LINE=$(cat ${SOURCES_ENTRY} | wc -l)
			NUM_LINES_AFTER_SHA256=$(( ${TOTAL_ENTRY_LINE} - ${SHA256_START} ))

			# Get the first entry name right after the Checksums-Sha256: chunk
			NAME_ENTRY=$(cat ${SOURCES_ENTRY} | tail -n ${NUM_LINES_AFTER_SHA256} | grep -v '^ ' | head -n 1 | awk '{print $1}')
			NUM_LINES_CHECKSUM_ENTRIES=$(cat ${SOURCES_ENTRY} | tail -n ${NUM_LINES_AFTER_SHA256} | grep -n -E "^${NAME_ENTRY}" | cut -d: -f1)
			NUM_LINES_CHECKSUM_ENTRIES=$(( ${NUM_LINES_CHECKSUM_ENTRIES} - 1 ))

			for LINE in $(cat ${SOURCES_ENTRY} | tail -n ${NUM_LINES_AFTER_SHA256} | head -n ${NUM_LINES_CHECKSUM_ENTRIES} | sed -e 's/^ //' | tr ' ' ',') ; do
				FILE_SHA_SUM=$(echo $LINE | cut -d, -f1)
				FILE_NAME=$(echo $LINE | cut -d, -f3)
				if [ "${USE_SECURITY_VERSION}" = "yes" ] ; then
					echo "-> Downloading: ${SECURITY_MIRROR_URL}/${DIRECTORY}/${FILE_NAME}"
					wget -q ${SECURITY_MIRROR_URL}/${DIRECTORY}/${FILE_NAME}
				else
					echo "-> Downloading: ${DEB_MIRROR}/${DIRECTORY}/${FILE_NAME}"
					wget -q ${DEB_MIRROR}/${DIRECTORY}/${FILE_NAME}
				fi
				DL_SHA=$(sha256sum ${FILE_NAME} | awk '{print $1}')
				if [ "${DL_SHA}" != "${FILE_SHA_SUM}" ] ; then
					echo "Downloaded SHA256 does not match what is in Sources.gz: authentification error."
					exit 1
				fi
			done

			rm -f ${SOURCES_ENTRY}
		fi
	done
	cd ..
	tar -cvzf ${OUTPUT}-source.tar.gz source
	rm -rf source Sources SecuritySources InRelease
fi

if [ "${GEN_SUMS}" = "yes" ] ; then
	rm -f SHA512SUMS
	for i in -packages.list .qcow2 .raw -source.tar.gz ; do
		if [ -e ${OUTPUT}${i} ] ; then
			sha512sum ${OUTPUT}${i} >>SHA512SUMS
		fi
	done
	if [ "${GEN_SUMS_SIGN}" = "yes" ] ; then
		gpg --clearsign SHA512SUMS >SHA512SUMS.sign
	fi
fi

if [ "${REBOOT_AFTER_INSTALL}" = "yes" ] ; then
	if [ -x "${PRE_REBOOT_HOOK_SCRIPT}" ] ; then
		${PRE_REBOOT_HOOK_SCRIPT}
	fi
	echo "Rebooting computer in 5 seconds ..."
	sleep 5
	shutdown -r now
fi
