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

DEBUG=0
FORCE=0
# You can set DEBUG_RELEASE in the environment for testing
DEBUG_RELEASE=""
VERBOSE=0
FAKE=0
UPGRADE_TO_TESTING=no
UPGRADE_ANYWAY=no

# Read defaults here so as not to clobber command-line args later
[ -f /etc/default/debathena-auto-update ] && . /etc/default/debathena-auto-update

while getopts "vfdt" opt; do
    case "$opt" in
        d) 
            DEBUG=1
            FAKE=1
            UPGRADE_ANYWAY=yes
            ;;
        f) 
            FORCE=1
	    UPGRADE_ANYWAY=yes
            ;;
        t)
            UPGRADE_TO_TESTING=yes
            ;;
        v) # Spam level
            VERBOSE=1
            ;;
        \?)
            cat<<END
    Usage: $0 [OPTION]

            -d         debug mode, bypasses all checks, only prints
            -t         upgrade to testing
            -f         bypasses login checks
            -v         echo the cmds that are run

END
            
            ;;
    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

function pie_grub() {
    # change DEFAULT in /etc/grub to SAVED
    if [[ $FAKE == 1 ]]; then
        echo perl -i.bak -pe 's/^GRUB_DEFAULT=.*$/GRUB_DEFAULT=saved/' /etc/default/grub
    elif [[ $VERBOSE == 0 ]]; then
        perl -i.bak -pe 's/^GRUB_DEFAULT=.*$/GRUB_DEFAULT=saved/' /etc/default/grub >/dev/null 2>&1
    else
        echo perl -i.bak -pe 's/^GRUB_DEFAULT=.*$/GRUB_DEFAULT=saved/' /etc/default/grub
        perl -i.bak -pe 's/^GRUB_DEFAULT=.*$/GRUB_DEFAULT=saved/' /etc/default/grub 
    fi
    if [[ $? -ne 0 ]]; then
        complain "Setting DEFAULT in /etc/default/grub returned a non-zero exit status"
        exit 1
    fi

}


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



function runcmd()
{
    CMD=$1
    if [[ $FAKE == 1 ]]; then
        echo $CMD
    elif [[ $VERBOSE == 0 ]]; then
        $CMD > /dev/null 2>&1
    else
        echo $CMD
        $CMD
    fi
    if [[ $? -ne 0 ]]; then
        complain "$CMD returned a non-zero exit status"
        exit 1
    fi
}

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

function maybe_quit() {
    if [ $FORCE -eq 1 ]; then
        echo "Would normally quit here, but you passed -f, so we keep going..."
    else
	echo "Ending upgrade at $(date)"
        exit 0
    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
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
export 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
    if [[ ! -z "$DEBUG_RELEASE" ]]; then
        UBUNTU_RELEASE=$DEBUG_RELEASE
    else
	echo "No new releases found."
        exit 0
    fi
fi
if [ "$(lsb_release -sc)" = "$UBUNTU_RELEASE" ]; then
    complain "Tried to upgrade to already running release; shouldn't happen"
    exit 1
fi
echo "Found $UBUNTU_RELEASE, starting upgrade"

# 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"

nodhcp="netcfg/disable_dhcp=true"
case "$UBUNTU_RELEASE" in
    oneiric|precise)
        kbdcode="keyboard-configuration/layoutcode=us"
	# "Yay"
	nodhcp="netcfg/disable_autoconfig=true"
	;;
    natty)
        # Sigh
        kbdcode="keyboard-configuration/layoutcode=us"
        ;;
    *)
        kbdcode="console-setup/layoutcode=us"
        ;;
esac

if [ -n "$NETMASK" ] && [ -n "$GATEWAY" ]; then
  knetinfo="netcfg/get_hostname=$(hostname) \
            $nodhcp \
            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

runcmd "rm -rf /auto-upgrade"
runcmd "mkdir -p /auto-upgrade" 
runcmd "wget http://debathena.mit.edu/net-install/${UBUNTU_RELEASE}/${arch}/initrd.gz -O /auto-upgrade/initrd.gz" 
runcmd "wget http://debathena.mit.edu/net-install/${UBUNTU_RELEASE}/${arch}/linux -O /auto-upgrade/linux" 

# This is just the guts of the hackboot script:
dkargs="DEBCONF_DEBUG=5"
kargs="$knetinfo locale=en_US $kbdcode \
       quiet \
       panic=5 \
       interface=auto \
       url=http://18.9.60.73/installer/${UBUNTU_RELEASE}/debathena.preseed \
       da/pxe=cluster --"

debug "USING kargs=$kargs"

if [ $(echo $kargs | wc -c) -ge 512 ]; then
    complain "kargs exceeds 512 bytes.  That's not good."
    exit 1
fi

tmpfile="/tmp/$(basename $0).$RANDOM.tmp"

cat >"$tmpfile"<<END
#!/bin/sh

echo "Adding auto-upgrade /auto-upgrade/linux" >&2
cat<<EOF
menuentry "auto-upgrade" {
  insmod ext2
  insmod part_msdos
  insmod lvm
  search --no-floppy --fs-uuid --set=root \${GRUB_DEVICE_UUID}
  echo "Loading auto-upgrade kernel for ${UBUNTU_RELEASE}" 
  linux /auto-upgrade/linux $kargs
  echo "Loading auto-upgrade ramdisk for ${UBUNTU_RELEASE}" 
  initrd /auto-upgrade/initrd.gz
}
EOF

END


debug "$(cat $tmpfile)"
runcmd "cp $tmpfile /etc/grub.d/49_auto-upgrade"
rm -f $tmpfile
runcmd "chmod 755 /etc/grub.d/49_auto-upgrade" 

pie_grub

runcmd "/usr/sbin/grub-set-default 0"
runcmd "/usr/sbin/grub-reboot auto-upgrade" 
runcmd "/usr/sbin/update-grub" 

# rebooting into the installer kernel
runcmd "/sbin/reboot"
