#!/bin/bash
# Using /bin/bash and not /bin/sh to get a shell with support for random number
# generation.
#
# Automatically turn off computers at night, defined as 16:00 - 06:00.
# Should schedule wakeup in the morning.

# How do we decide if it should be enabled for this host?  Netgroup
# membership?  LDAP search?  Flag file?

#set -e

wakeuptime="07:00"

hostname="$(uname -n)"
netgroupname="shutdown-at-night-hosts"

in_netgroup() {
    # Try both long and short name
    for h in "$(uname -n)" "$(hostname -s)" ; do
	if innetgr -h "$h" "$netgroupname" ; then
	    return 0
	fi
    done
    return 1
}

enabled_for_host() {
    # Flag for now
    if [ -f /etc/shutdown-at-night/shutdown-at-night ] || in_netgroup; then
        return 0
    fi
    return 1
}

nvramwakeup() {
# http://www.vdr-portal.de/board/thread.php?threadid=75582&sid=b7aced20e710aef12ffa56b5197fe168
    wakeuptime=$1
    # Spread the BIOS wakeup time across a 20 minute period, to avoid all of them
    # waking up at the same time, killing a fuse.
    when=$(( $(date +%s -d "tomorrow $wakeuptime") - 600 + $RANDOM % 1200))

    # Make sure HW clock is correct, as it is used to decide when to
    # wake up.
    /etc/init.d/hwclock.sh stop > /dev/null

    # Make sure /dev/nvram is available
    modprobe nvram

    # This require a supported motherboard
    if nvram-wakeup -s $when > /dev/null ; then
        logger -t shutdown-at-night "scheduled $hostname to turn itself on at $wakeuptime using nvram-wakeup."
        return 0
    else
        return 1
    fi
}

prepare_wakeonlan() {
    interface="$(/sbin/route -n | awk '/^0\.0\.0\.0 / { print $8 }')"
    ethtool -s $interface wol g
}

is_host_unused() {
    # Logged in users, or ldm connection to a remote server
    if [ "$(who)" ] ||  ps -efwww | egrep -q ' ssh .*LTSP_CLIEN[T]' ; then
	return 1
    fi
    # Uptime is less than one hour
    if (( $(cat /proc/uptime  | awk '{print int($1)}') < 3600 )) ; then
        return 1
    fi
    return 0
}

fatal() {
    logger -t shutdown-at-night "$1"
    exit 1
}

if enabled_for_host ; then
    if is_host_unused; then
	logger -t shutdown-at-night "turning off unused client $hostname."
	if type nvram-wakeup >/dev/null 2>&1 ; then
	    nvramwakeup $wakeuptime
	fi
	prepare_wakeonlan || fatal "unable to enable wake-on-lan - aborting shutdown."
	shutdown -h 5 "Unused host being turned off for the night (cron)." < /dev/null > /dev/null 2>&1 &
    else 
      logger -t shutdown-at-night "client $hostname is in use; shutdown sequence will NOT be initiated."
    fi
else
    logger -t shutdown-at-night "shutdown-at-night is not enabled for client $hostname."
fi

