#!/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
# account -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

# Built-in documentation:
function showdocs {
	$CAT <<-EODOC
		Setup new CPanel account in clonepanel system.
		ssh (secure shell) access MUST ALREADY BE ENABLED on remote account!
		
		This script creates the local file and directory structure for the account,
		then calls setup_remote_keys to setup remote access, finally calls
		sync_remote to setup the file and directory structure on the remote
		accounts. Inputs may be given as command line parameters or interactively.
		
		Read the remote_key built-in documentation for security information - 
		./setup_remote_key -h

                Inputs may be given as command line parameters or interactively.
                Usage:
                1. List accounts already defined:
                ./account
                2. Add a new account, or add a new host to an existing account:
                ./account -u myaccount add
		3. Delete an account:
		./account -u myaccount del
		
		Command line options: 
		-h		Print these instructions and exit
		-H host		Nickname of the server hosting the account
		-r role		Role of this server - usually MASTER or SLAVE
		-u user		CPanel username of the account
		-p secret	Password for this username (not yet implemented)
		-o "REMOTEHOST_USERNAME=fred"
		-o "MIRROR_DIR_WEB=public_html" Extra configuration options

EODOC
	exit $DOC_REQUEST
}

# Get account name(s) based on user input (if any)
function get_account {
        n_matches=0
        if [ "$user" ]; then
                matches=`$FIND $ACCOUNTS_DIR -maxdepth 1 -mindepth 1 -type d -name $user -printf "%f "`
        else
                matches=`$FIND $ACCOUNTS_DIR -maxdepth 1 -mindepth 1 -type d -printf "%f "`
        fi
        if [ ! "$matches" ]; then
                return
        fi
        n_matches=`$ECHO $matches |$WC -w`
}

function remove_account {
	for match in $1
	do
		cecho -c $warning "This will remove account $match entirely and DELETE ALL BACKUP SNAPSHOTS"
		cecho -n -c $prompt "If you are sure you wish to continue type 'I understand' "
		read input
		if [ "$input" != "I understand" ]; then
			cecho -c $error "Delete aborted"
			exit $USER_ABORT
		fi 
		$RM -rf $ACCOUNTS_DIR/$match
		checkerror $? $E_DELETE_ACOUNT_FAILED
	done
}
function remove_host {
	$GREP -v =$host$ $ROLES_FILE >$TEMP_DIR/roles.tmp
# Clean out any existing roles for this host from the roles file (keep only other hosts)
# NB - grep will throw an error on no match

	$MV $TEMP_DIR/roles.tmp $ROLES_FILE 
	checkerror $? $E_COPY_ROLES_FAILED
}

function run_sync_setup {
# After making changes to database setup, recommend syncing these to remote hosts
        cecho -c $warning "Changes made must be synchronised with remote host(s)"
        cecho -n -c $prompt "Run sync program now? (y/n):"
        read response
        if [ "$response" == "y" ]; then
                $PROGRAM_DIR/sync_remote -u $user
        fi
}







# Initialise own input variables:
command=list
host=''
role=''
user=''
password=''
force='n'
extras=''
hostfrom=''

# Start real script

# Check for help request and input variables in the command line options:
while getopts ":hc:H:u:p:r:o:f" opt
do
	case $opt in
		h)	showdocs
			;;
		H)	host=$OPTARG
			;;
		u)	user=$OPTARG
			;;
		p)	password=$OPTARG
			;;
		o)	extras="$OPTARG\n$extras"
			;;
		r)	role=$OPTARG
			;;
		f)	force='y'
			;;
		*)	$ECHO "Unknown option. Use -h for instructions"; exit $E_UNKNOWN_OPT
			;;
	esac
done
shift $(($OPTIND - 1))

OPTIND=1
# reset getopts for next time

if [ $# -gt 0 ]; then
        command=$1
fi

case $command in
        list)
                cecho -c $ok "Accounts list:"
                get_account

                if [ $n_matches -gt 0 ]; then
                        for username in $matches
                        do
				cecho -c $info $username
				$CAT $ACCOUNTS_DIR/$username/$ROLES_FILENAME
				cecho
                        done
                        cecho -c $ok "$n_matches account(s) listed"
		else
			cecho -c $warning "No matching accounts"
		fi
		;;
	del)
		get_account
		if [ "$host" ]; then
			hostfrom=" $host from"
# Some text to make the following prompt a little more informative
		fi
		case $n_matches in
			0)
				cecho -c $error "No matching accounts - nothing to delete"
				exit $E_ACCOUNT_NOT_FOUND
				;;
			1)
				if [ $force != 'y' ]; then
					cecho -n -c $prompt "1 account matches your input - delete$hostfrom it? (y/n): "
					read force
				fi
				;;
			*)
				if [ $force != 'y' ]; then
					cecho -n -c $prompt "$n_matches accounts match your input - delete$hostfrom all? (y/n): "
					read force
				fi
				;;
		esac

		if [ $force == 'y' ]; then
			if [ "$host" ]; then
				for match in $matches
				do
					config -u $match -H $host
					remove_host
				done
			else
				remove_account $matches
			fi
		else
			cecho -c $error "Aborted"
			exit $USER_ABORT
		fi
		cecho -c $ok "Account deletion complete" ;
		if [ "$host" ]; then
			run_sync_setup
# Prompt to sync to remaining host(s) - only if whole account not deleted
		fi
		;;
	add)
		if [ ! $host ]; then
			cecho -n -c $prompt "Enter host name (nickname): "
			read host
		fi

		if [ ! $user ]; then
			cecho -n -c $prompt "Enter account username: "
			read user
		fi

		if [ ! $extras ]; then
			while [ 1 ]
			do
		  		cecho -c $prompt "Enter extra config options now (<Return> to finish)."
                                cecho -c $prompt "Examples: REMOTEHOST_USERNAME=fred or MIRROR_DIR_WEB=public_html"
                                cecho -n -c $prompt "(usually only needed on non-CPanel hosts or where username differs from one host to another): "
				read input
				if [ ! "$input" ]; then
					break
				else
					extras="$input $extras"
				fi
				cecho
			done
		fi

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

# User-specific and host-specific include files (after defining $user and $host):
		config -u $user -H $host
		if [ "$extras" ]; then
			if [ -f $USER_HOSTS_FILE ]; then
				$RM $USER_HOSTS_FILE
			fi
			if [ ! -d $USER_DIR/$host ]; then
				$MKDIR $USER_DIR/$host
			fi
			for line in $extras
			do
				$ECHO $line >>$USER_HOSTS_FILE
			done
		fi

		host_ip=$SERVER
# Get remote server ip address from hosts file
		if [ ! "$host_ip" ]; then
			cecho -c $error "Unknown host name (check $HOSTS_FILE)"
			exit $E_NO_HOST
		fi

		if [ -d $USER_DIR ]; then
# Account already exists - need confirmation to overwrite
			if [ $force != "y" ]; then
				cecho -n -c $prompt "Account already exists - reconfigure? (y/n):"
				read force
				if [ $force != 'y' ]; then
					exit $E_ACCOUNT_EXISTS
				fi;
			else
				cecho -c $warning "Account already exists - force option on - will reconfigure"
			fi
			if [ ! $role ]; then
				if [ "`$GREP -l MASTER $ROLES_FILE`" ]; then
					role=SLAVE
					cecho -c $warning "Existing MASTER - role defaults to SLAVE"
				else
					role=MASTER
					cecho -c $warning "Role defaults to MASTER (no other host with that role)"
				fi
			fi
		else
			create_dir $USER_DIR
			if [ ! $role ]; then
				role=MASTER
				cecho -c $info "Role defaults to MASTER for new account"
			fi
		fi

		$CP -r $LOCAL_SKEL/* $USER_DIR
# initial setup of new account's local directory from local skeleton

# Now to create the default roles file for the account
		if [ ! -f $ROLES_FILE ]; then
			$TOUCH $ROLES_FILE
		fi
		$CHMOD 0600 $ROLES_FILE
		checkerror $? $E_CREATE_ROLES_FAILED

		remove_host
# Remove any data relating to this host from the roles file	

		$ECHO "WEB_$role=$host" >> $ROLES_FILE
		$ECHO "MAIL_$role=$host" >> $ROLES_FILE
		$ECHO "DNS_$role=$host" >> $ROLES_FILE
		$ECHO "SEND_$role=$host" >> $ROLES_FILE
# Set up roles in user dir as WEB_MASTER=HOSTNAME and MAIL_MASTER=HOSTNAME etc

# Now for the remote access keys
		if [ -f $AUTH_DIR/$host ]; then
			cecho -n -c $prompt "Key file already exists for $user on $host - replace it? (y/n):"
			read response
			if [ "$response" == "y" ]; then
				$RM $AUTH_DIR/$host
				checkerror $? $E_REMOVE_KEY_FAILED
			else
				cecho -c $info "Keeping existing key"
			fi
		fi
		if [ ! -f $AUTH_DIR/$host ]; then
			$PROGRAM_DIR/setup_remote_key -u $user -H $host -p \'$password\'
			checkerror $? $E_SETUP_KEYS_FAILED
		fi

# Now that we have access we can copy setup files and
# program files over to the remote account
		$PROGRAM_DIR/sync_remote -u $user -H $host
		checkerror $? $E_RSYNC_SCRIPTS_FAILED

		cecho -c $ok "Account setup complete" ;
		;;
	*)      cecho -c $error "Unknown option. Use -h for instructions"; exit $E_UNKNOWN_OPT
		;;
esac

