#!/bin/sh

# ClonePanel - Manages duplicate accounts on two or more webservers,
# including snapshot backups, monitoring and failover dns.
# Copyright (C)2006 Chris Cheers, Internet Lynx.
# Contact chris[at]clonepanel[dot]com.
# Internet Lynx, PO Box 7117, Mannering Park, NSW 2259, Australia

# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

Version=0.33
# set_status -h for built-in documentation

set -u
# Be strict about variable declaration

unset PATH
#avoid use of $PATH - limit script to system commands we choose

PROGRAM_DIR=$(/bin/echo $0 |/bin/sed -e "s/\/[a-zA-Z0-9_]*$//")
# Extract the working directory from command line
# NB - if your system doesn't have echo and sed in these locations
# then this line will need to be changed in all shell scripts

# Standard include files:
. $PROGRAM_DIR/includes

MAIL=/bin/mail
# Not included with other commands - don't want this enabled by default

# Built-in documentation:
function showdocs {
	$CAT <<-EODOC
		Change the status of a server between states: RED AMBER GREEN and DISABLED
		and modifies zone files for all accounts affected by the change.
		Attempts to update dns servers on hosts in GREEN / AMBER state, with fall-back
		to try again repeatedly using cron job set_dns
		Updates on hosts in RED or DISABLED state go straight to cron job
		FAILOVER_STATUS and FAILBACK_STATUS determine status values (RED and GREEN by default).
		Inputs may be given as command line parameters or interactively.
		
		Usage:
		./set_status
		Command line options: 
		-h			Print these instructions and exit
		-H hostname	Host name (nickname)
		-s status		Allowable options are $STATUS_CODES

EODOC
	exit $DOC_REQUEST
}

# Initialise own input variables:
host=''
status=''

# Start real script

# Check for help request and input variables in the command line options:
while getopts ":hH:s:" opt
do
	case $opt in
		h)	showdocs
			;;
		H)	host=$OPTARG
			;;
		s)	status=$OPTARG
			;;
		*)	$ECHO "Unknown option. Use -h for instructions"; exit $E_UNKNOWN_OPT
			;;
	esac
done
shift $(($OPTIND - 1))

OPTIND=1
# reset getopts for next time

if [ ! $host ]; then
	cecho -n -c $prompt "Enter host name: "
	read host
fi

if [ ! $status ]; then
	cecho -n -c $prompt "Enter current status: "
	read status
fi

if [ ! $host -o ! $status ]; then
	cecho -c $error "Host name and status must be specified"
	exit $E_BLANK_INPUTS
fi

if [ ! "`$ECHO $STATUS_CODES |$GREP $status`" ]; then
	cecho -c $error "Unknown status keyword - use $STATUS_CODES"
	exit $E_UNKNOWN_STATUS
fi

config -H $host
# Config specific to this host
 
host_ip=$SERVER
# Get remote server ip address from hosts file
if [ ! $host_ip ]; then
	cecho -c $error "Host name not found - check hosts/$host/config for SERVER"
	exit $E_NO_HOST
fi

current_status=`$GREP "^$host=" $STATUS_FILE |$CUT -d= -f2`
if [ ! $current_status ]; then
	cecho -c $error "No match for $host found in $STATUS_FILE"
	exit $E_NO_STATUS
fi

if [ $status == $current_status ]; then
	cecho -c $info "Status of $host is already $status - no further action needed"
	exit $NO_ACTION_REQUIRED
fi

$GREP -v "^$host=" $STATUS_FILE > $STATUS_TMP
checkerror $? $E_TEMP_STATUSFILE_FAILED
# Copy all except this host's record to a temp file
$MV $STATUS_TMP $STATUS_FILE
checkerror $? $E_TEMP_STATUSFILE_FAILED
# and write temp file back over status
$ECHO "$host=$status" >>$STATUS_FILE
checkerror $? $E_APPEND_STATUSFILE_FAILED
# with new status of this host included

emessage="$host=$status written to $STATUS_FILE"
subject="CPstatus $status: $host"
cecho -c $info $message
written=''

if [ "$WRITE_STOPS_EMAIL_ON_ERROR" == "y" ]; then
	write_stops_e=y
else
	write_stops_e=''
fi

if [ "$WRITE_STOPS_EMAIL_ON_STATUS_CHANGE" == "y" ]; then
	write_stops_s=y
else
	write_stops_s=''
fi

# Should we write an alert?
if [ "$WRITE_ON_STATUS_CHANGE" == "y" ]; then
        me=`$WHOAMI`
        if [ "`$WHO |$GREP $me`" ]; then
# I am online!
                $ECHO $emessage |$WRITE $me
                written=y
        fi
fi

# Do we have an e-mail address for error reports?
if [ "$ERROR_REPORT_EMAIL" ]; then
# And do we suppress it if already written as a console alert?
	if [ "$written" -a "$write_stops_e" ]; then
		cecho -c $warning "Email suppressed - alert written to console"
	else
		$ECHO $emessage |$MAIL -s "$subject" $ERROR_REPORT_EMAIL
        fi
fi

if [ "$STATUS_CHANGE_EMAIL" ]; then
# And do we suppress it if already written as a console alert?
	if [ "$written" -a "$write_stops_s" ]; then
		cecho -c $warning "Email suppressed - alert written to console"
	else
		if [ -x $SYSTEM_DIR/$STATUS_CHANGE_EMAIL ]; then
#Status change e-mail may be name of script in system dir - if so execute it
			$SYSTEM_DIR/$STATUS_CHANGE_EMAIL $emessage
		else
			$ECHO $emessage |$MAIL -s "$subject" $STATUS_CHANGE_EMAIL
		fi
        fi
fi

# Now handle failover...
if [ $FAILOVER_AUTO != "n" ]; then
# config settings - n disables auto-failover completely, y enables on enabled zones
	for user in `$LS $ACCOUNTS_DIR`
	do
		$PROGRAM_DIR/failover -u $user -H $host -v
# failover script will choose appropriate action based on new status of host
	done
fi
cecho -c $ok "Done set_status!"
 
