#! /bin/sh


set -e


test -e /etc/cubbli/cubbli.conf && . /etc/cubbli/cubbli.conf

CONFIGFILE=/etc/cubbli/cubbli.conf

INSTALLER_DIR=/etc/cubbli/installer
VAR_DIR=/var/lib/cubbli-installer
ERROR_FILE="$VAR_DIR/errors"

PING_HOST="$CUBBLI_SERVER"
test "$PING_HOST" || PING_HOST=cubbli.cs.helsinki.fi

# New var. We should try to get rid of VAR_DIR.
# init-script will only run this script if $donestamp does not exist.
vardir=/var/lib/cubbli/installer
donestamp="$vardir/done"


test -d "$INSTALLER_DIR" || mkdir -p "$INSTALLER_DIR"
test -e "$CONFIGFILE" && . "$CONFIGFILE"

test -f "$VAR_DIR/updated" && rm "$VAR_DIR/updated"

APT=aptitude


has_stamp() {
	test -f "$INSTALLER_DIR/$1" && return 0 || return 1
}


make_stamp() {
	touch "$INSTALLER_DIR/$1"
}


error() {
	echo $@ >>"$ERROR_FILE"
}


get_cpus() {
	test -e /sys/devices/system/cpu/present || return 0

	last=$(sed 's/.*[^0-9]//' /sys/devices/system/cpu/present)
	seq 1 $last
}


disable_cores() {
	test -e /sys/devices/system/cpu/present || return 0

	for i in $(get_cpus); do
		echo 0 >"/sys/devices/system/cpu/cpu$i/online"
	done
	# make sure cores are re-enabled
	trap 'enable_cores' 0
}


enable_cores() {
	test -e /sys/devices/system/cpu/present || return 0

	for i in $(get_cpus); do
		echo 1 >"/sys/devices/system/cpu/cpu$i/online"
	done
}


wait_network() {
	announced=""
	for a in $(seq 1 60); do
		if ping -c 1 "$PING_HOST" >/dev/null 2>&1; then
			return 0
		else
			test "$announced" || echo "Waiting for network..."
			announced=yes
			sleep 2
		fi
	done
	echo "Server unreachable!"
	/sbin/ip addr || true
	/sbin/ip route || true
	/sbin/ip -6 route || true
	return 1
}


apt_update() {
	if ! test -f "$VAR_DIR/updated"; then
		$APT update
		touch "$VAR_DIR/updated"
	fi
}


apt_install() {
	RET=0
	apt_update

	# 11 Jun 2009 [TS]: Disable "other" cores to avoid race condition.
	#	We don't care what cores were enabled beforehand.
	#	Please get rid of this hack.
	#
	disable_cores

	echo ":: Installing: $@"
	$APT -q -y -o Acquire::http::Timeout=360 install $@ || RET=1
	enable_cores

	$APT autoclean
	return $RET
}


# set debconf options
#
debconf_config() {
	has_stamp debconf && return 0 || true

	# Set debconf noninteractive
	cat <<EOF | debconf-set-selections
	debconf debconf/priority select critical
	debconf debconf/frontend select noninteractive
EOF

	make_stamp debconf
}


config_pending() {
	# configure pending packages
	dpkg --configure --pending
}


# preseed debconf values
#
debconf_preseed() {
	has_stamp preseed && return 0 || true

	# - disable generating /var/lib/samba/passdb.tdb
	# - don't update /etc/wvdial.conf -- doing so freezes installation
	cat <<EOF | debconf-set-selections
	debconf samba/generate_smbpasswd boolean false
	debconf wvdial/wvdialconf boolean false
EOF

	make_stamp preseed
}


# update /etc/cubbli/cubbli.conf
#
cubbli_config() {
	test "$POSTMASTER" && return 0

	case "$DOMAIN" in
	  cs.helsinki.fi)
		ADMIN="itsupport@cs.helsinki.fi"
		POSTMASTER="postmaster@cs.helsinki.fi"
		;;
	  *)
		ADMIN="itsupport@cs.helsinki.fi <FIXME>"
		POSTMASTER="postmaster@cs.helsinki.fi <FIXME>"
		;;
	esac

	cat >>"$CONFIGFILE" <<EOF
ADMIN="$ADMIN"
POSTMASTER="$POSTMASTER"
EOF
}


# setup resolv conf
#
resolv_setup() {
	# Add stuff to resolv.conf search
	sed -i "s/^search.*/search $DOMAIN helsinki.fi/" /etc/resolv.conf
}


# update X confi
#
x_setup() {
	has_stamp x-setup && return 0 || true
	
	if debconf-show xserver-xorg | grep -q "xserver-xorg/config/device/driver: nv$"; then
		$APT -y install nvidia-glx nvidia-glx-dev &&
				nvidia-glx-config enable && NVIDIA=yes
	fi

	if test "$NVIDIA"; then
		# Ditch the logo. It might get back sometime since this is not
		# in debconf, but that's not too critical.
		sed -i "s/^\(.*Driver.*\"nvidia\"\)$/\1\n\tOption\t\t\"NoLogo\"\t\"true\"/" /etc/X11/xorg.conf
		md5sum /etc/X11/xorg.conf >/var/lib/xfree86/xorg.conf.md5sum
	fi

	make_stamp x-setup
}


# initial update/upgrade since repositories have probably been changed after
# Debian installer.
#
initial_upgrade() {
	has_stamp init-upgrade && return 0 || true

	apt_update
	if $APT -q -y dist-upgrade; then
		make_stamp init-upgrade
	fi
}


# install base packages
#
base_install() {
	has_stamp base && return 0 || true

	if apt_install cubbli-base; then
		mount -a
		make_stamp base
	fi
}


install_packages() {
	OK=1
	file="$VAR_DIR/packages"
	test "$1" && file="$file-$1"

	test -r "$file" || return 1

	echo ":: Installing from $file"
	# I'd rather use "while read line" but I think aptitude steals stdio
	for pkg in $(cat "$file"); do
		apt_install "$pkg" || error "Failed to install: $pkg"
	done
	mv "$file" "$file.old"

	return 0
}


# make sure desktop manager doesn't touch /opt
#
fix_gdm() {
	find -L /etc/gdm/ -maxdepth 2 -mindepth 2 -type f -name Default |
	while read gdmfile; do
		sed -i 's|:/opt/X11R6/bin||' "$gdmfile"
	done
}


reload_start_gdm() {
	# If reloading GDM fails GDM is either not running or it's uninstalled.
	# Either way reload || start won't do any harm. I hope service takes
	# care of run levels.
	service gdm reload || service gdm start || true
}


debconf_config	# make debconf non-interactive
config_pending	# configure pending packages == fix partially installed packages
debconf_preseed	# preseed some debconf values
cubbli_config	# finalise /etc/cubbli/cubbli.conf
resolv_setup	# finalise /etc/resolv.conf

if ! wait_network; then
	echo "Giving up waiting for network!"
	exit 1
fi

initial_upgrade	# initial update/upgrade
base_install	# install base packages (i.e. cubbli-base)

# install additional software
#
# When GDM is first installed its postinst script tries to reload it. Since GDM
# isn't running, this doesn't work. This is OK, because we also want to install
# window managers before GDM is started.
#
# The whole installer was originally built so that GDM could be started as soon
# as window managers and basic applications are installed, but it has been
# decided that mass-installs are easier if GDM is started only when all is
# done. This way it is easy to recognize a computer that's fully installed.

install_packages pre-gdm || true
x_setup
fix_gdm
install_packages || true

if test -s "$ERROR_FILE"; then
	cat "$ERROR_FILE"

	# TODO we may want to set GDM background to reflect failed install or
	# something...

	mail -s "$(hostname -f): cubbli-installer failed" root <"$ERROR_FILE" \
			&& rm "$ERROR_FILE"
fi

reload_start_gdm

echo "All done."

# create stamp
test -d "$vardir" || mkdir -p "$vardir"
touch "$donestamp"
