#!/bin/bash
#
# This is designed to be called from cron

debug() {
    [ $DEBUG -eq 1 ] && echo "DEBUG: $*"
}

complain() {
    if [ $DEBUG -eq 1 ]; then
	echo "ERROR: $*"
    else
	logger -t "athena-auto-upgrade" -p user.notice "$*"
    fi
}

maybe_quit() {
    if [ $FORCE -eq 1 ]; then
        echo "Would normally quit here, but you passed -f, so we keep going..."
    else
        exit 0
    fi
}

DEBUG=0
MAYBE=""
FORCE=0

UPGRADE_TO_TESTING=no
UPGRADE_ANYWAY=no
[ -f /etc/default/debathena-auto-update ] && . /etc/default/debathena-auto-update

while getopts "fdt" opt; do
    case "$opt" in
        d) 
            DEBUG=1
            MAYBE=echo
	    UPGRADE_ANYWAY=yes
            ;;
        f) 
            FORCE=1
	    ;;
        t)
	    UPGRADE_TO_TESTING=yes
	    ;;
        \?)
            echo "Usage: $0 [-d] [-t] [-f]"
	    ;;
    esac
done

if [ $DEBUG -eq 1 ] && [ $FORCE -eq 1 ]; then
    echo "ERROR: -d and -f are mutually exclusive."
    exit 2
fi
if [ $FORCE -eq 1 ]; then
    echo "Using -f is a terrible idea.  Press Ctrl-C to reconsider and"
    echo "save your machine, or Enter to continue."
    read r
fi

if [ $DEBUG -ne 1 ]; then
    # Redirect output to a log file
    # Unless we're in debug mode
    exec >>/var/log/athena-upgrade 2>&1
fi

echo "Starting upgrade at $(date)"

# Not supported on Debian
if [ "$(lsb_release -si)" != "Ubuntu" ]; then
    debug "Only supported on Ubuntu.".
    exit 0
fi

# Skip other sanity checks in debug mode
if [ $DEBUG -ne 1 ]; then
    # Only run this on cluster
    if [ "$(machtype -L)" != "debathena-cluster" ] && \
       [ "$UPGRADE_ANYWAY" != "yes" ]; then
	debug "Not a cluster machine and UPGRADE_ANYWAY != yes.".
	exit 0
    fi
    
    # Bail if someone is logged in (stolen from auto-update)
    ttys=$(w -h -s | awk '{print $2}')
    for tty in $ttys; do
	pids=$(ps --no-heading -j -t "$tty" 2>/dev/null \
            | awk '($1 == $3) {print $1}')
	if [ -n "$pids" ]; then
	    debug "Users logged in, won't continue."
	    debug "PIDs: $pids"
	    maybe_quit
	fi
    done
    # screen processes count as logins.
    if pgrep '^screen' > /dev/null; then
	debug "Screen processes found, won't continue."
	maybe_quit
    fi
fi

CLUSTERINFO=`getcluster -b $(lsb_release -sr)`
[ $? != 0 ] && complain "Failed to get clusterinfo" && exit 1
eval $CLUSTERINFO
if [ ! -z "$NEW_PRODUCTION_RELEASE" ]; then
    debug "Taking new production release: $NEW_PRODUCTION_RELEASE"
    NEWCLUSTER=`getcluster -b $NEW_PRODUCTION_RELEASE`
    [ $? != 0 ] && complain "Failed to get clusterinfo" && exit 1
    eval $NEWCLUSTER
elif [ ! -z "$NEW_TESTING_RELEASE" ] && \
    [ "$UPGRADE_TO_TESTING" = "yes" ]; then
    debug "Taking new testing release: $NEW_TESTING_RELEASE"
    NEWCLUSTER=`getcluster -b $NEW_TESTING_RELEASE`
    [ $? != 0 ] && complain "Failed to get clusterinfo" && exit 1
    eval $NEWCLUSTER
else
    debug "No new releases."
    exit 0
fi
if [ "$(lsb_release -sc)" = "$UBUNTU_RELEASE" ]; then
    complain "Tried to upgrade to already running release; shouldn't happen"
    exit 1
fi
debug "OK, trying to upgrade to $UBUNTU_RELEASE"

# That's a space and then a tab inside the brackets
if egrep -q '^flags[ 	].* lm( |$)' /proc/cpuinfo; then 
    arch=amd64
else 
    arch=i386
fi
debug "Arch: $arch"
IPADDR=
NETMASK=
eval `ifconfig eth0 |perl -ne'/^\s+inet addr:([\d\.]+).*? Mask:([\d\.]+)/ && print "IPADDR=$1 NETMASK=$2"'`
if [ -z "$IPADDR" ]; then
    complain "Couldn't get IPADDR from ifconfig!"
    exit 0
fi
GATEWAY=`route -n | awk '/^0\.0\.0\.0/ { print $2 }'`
debug "Using IPADDR=$IPADDR"
debug "Using NETMASK=$NETMASK"
debug "Using GATEWAY=$GATEWAY"
if [ -n "$NETMASK" ] && [ -n "$GATEWAY" ]; then
  knetinfo="netcfg/get_hostname=$(hostname) \
            netcfg/disable_dhcp=true \
            netcfg/get_domain=mit.edu \
            netcfg/get_nameservers=\"18.72.0.3 18.70.0.160\"\
            netcfg/get_ipaddress=$IPADDR \
            netcfg/get_netmask=$NETMASK \
            netcfg/get_gateway=$GATEWAY \
            netcfg/confirm_static=true"
else
  knetinfo="netcfg/dhcp_timeout=60 netcfg/get_hostname=$(hostname)"
fi

$MAYBE mkdir /h
$MAYBE cd /h
$MAYBE wget -N http://debathena.mit.edu/net-install/${UBUNTU_RELEASE}/${arch}/initrd.gz
$MAYBE wget -N http://debathena.mit.edu/net-install/${UBUNTU_RELEASE}/${arch}/linux
case "$UBUNTU_RELEASE" in
    natty)
        # Sigh
        kbdcode="keyboard-configuration/layoutcode=us"
        ;;
    *)
        kbdcode="console-setup/layoutcode=us"
        ;;
esac
# This is just the guts of the hackboot script:
dkargs="DEBCONF_DEBUG=5"
kargs="$knetinfo locale=en_US $kbdcode \
       interface=auto \
       url=http://18.9.60.73/installer/${UBUNTU_RELEASE}/debathena.preseed \
       debathena/pxetype=cluster --"
product_name="$(cat /sys/class/dmi/id/product_name | sed -e 's/[ ]*$//')"
# Yes, really.  The actual value of product_name on the Vostro is:
# "Vostro 320                   "
case "$product_name" in
  "OptiPlex 790")
    debug "Adding 'reboot=pci' for Dell 790"
    kargs="$kargs reboot=pci"
    ;;
esac
if [ $(echo $kargs | wc -c) -ge 512 ]; then
  complain "kargs exceeds 512 bytes.  That's not good."
fi
# This is not so much Vostro 320-specific as it is i915 specific
# Known to be necessary on PCI ID 8086:2e32, rev 03
# Actually, on all hardware, because Dell sucks.  Or possibly Ubuntu.
debug "Waving dead chicken..."
# Run the video card's POST to reset it
vbetool post
# Disable the framebuffer, falling back to VGA
echo 0 > /sys/class/vtconsole/vtcon1/bind
# Don't kexec -e here, because modern Ubuntu is unable to kexec while
# X is running.  Instead, kexec -l and let the init script take care of.
# Until Oneiric, when this will probably stop working if kexec-tools hasn't
# been Upstartified.
$MAYBE /sbin/kexec -l linux --append="$dkargs $kargs" --initrd=initrd.gz
[ $DEBUG -eq 1 ] && exit 0
if [ "`cat /sys/kernel/kexec_loaded`" != "1" ]; then
  echo "Hrm, looks like kexec -l didn't work.  This upgrade might fail."
else
  echo "Kernel loaded.  Rebooting in order to exec it."
fi
reboot
exit 0
