#! /bin/sh
#
# gfservice-agent - Utility to operate Gfarm servers.
#
# Usage:
#     gfservice-agent [-d] SUB-COMMAND [ARGUMENT...]
#
# This command is not designed to be executed directly by users.
# It is invoked from 'gfservice' command.
#

# PATH
PATH=@bindir@:/usr/bin:/bin

# Program name.
PROGRAM=gfservice-agent

# Debug flag.
DEBUG=false

# Shared secret key file.
SHARED_KEY_FILE="$HOME/.gfarm_shared_key"

# gfservice plugin directory
GFSERVICE_PLUGIN_DIR="@datadir@/gfarm/gfservice"

# Installation path of Globus Toolkit
GLOBUS_LOCATION="@globus_location@"

# Exitcode 'gfservice-timeout' returns in case of timeout.
EXITCODE_TIMEOUT=124

#
# Output a debug message.
#
log_debug()
{
	[ "X$DEBUG" != Xtrue ] && return
	echo "$PROGRAM@$HOSTID: debug: $@" 1>&2
	return 0
}

#
# Output a warning message.
#
log_warn()
{
	echo "$PROGRAM@$HOSTID: warning: $@" 1>&2
	return 0
}

#
# Output an error message.
#
log_error()
{
	echo "$PROGRAM@$HOSTID: error: $@" 1>&2
	exit 1
}

#
# Get an particular option in command line arguments.
#
get_param()
{
	log_debug "get_param: PARAMETER=$1"

	I=0
	while [ $I -lt $ARGC ]; do
		eval "ARG=\$ARGV$I"
		if expr "X$ARG" : "^X$1=.*\$" > /dev/null 2>&1; then
			echo "X$ARG" | sed -e 's/^[^=]*=//'
			log_debug "get_param: $1="`echo "X$ARG" \
				| sed -e 's/^[^=]*=//'`
			log_debug "end get_param"
			return 0
		fi
		I=`expr $I + 1`
	done

	log_debug "get_param: $1="
	log_debug "end get_param"
	return 1
}

#
# Set variables for gfmd operations.
#
set_gfmd_params()
{
	log_debug "set_gfmd_params"
	CONFIG_GFARM_OPTIONS=`get_param config-gfarm-options || echo ''`

	eval `config-gfarm -T $CONFIG_GFARM_OPTIONS`

	log_debug "set_gfmd_params: set CONFIG_PREFIX=$CONFIG_PREFIX"

	if [ "X$BACKEND_TYPE" != Xpostgresql ]; then
		log_error "backend type '$BACKEND_TYPE' unsupported"
		exit 1
	fi
	log_debug "set_gfmd_params: set BACKEND_TYPE=$BACKEND_TYPE"

	[ "X$GFMD_RC" = X ] \
		&& log_error "failed to get rc script for gfmd"
	log_debug "set_gfmd_params: set GFMD_RC=$GFMD_RC"

	[ "X$BACKEND_RC" = X ] \
		&& log_error "failed to get rc script for backend"
	log_debug "set_gfmd_params: set BACKEND_RC=$BACKEND_RC"

	[ "X$GFMD_CONF" = X ] \
		&& log_error "failed to get gfmd conf file"
	log_debug "set_gfmd_params: set GFMD_CONF=$GFMD_CONF"

	JOURNAL_DIR=$METADATA_JOURNAL_DIR
	[ "X$GFMD_MODE" != Xsingle -a "X$JOURNAL_DIR" = X ] \
		&& log_error "failed to get metadata journal directory"
	log_debug "set_gfmd_params: set JOURNAL_DIR=$JOURNAL_DIR"

	[ "X$GFMD_PID_FILE" = X ] \
		&& log_error "failed to get gfmd pid file"
	log_debug "set_gfmd_params: set GFMD_PID_FILE=$GFMD_PID_FILE"

	METADATA_DIR=$BACKEND_DATA_DIR
	[ "X$METADATA_DIR" = X ] \
		&& log_error "failed to get metadata directory"
	log_debug "set_gfmd_params: set METADATA_DIR=$METADATA_DIR"

	[ "X$GFMD_PORT" = X ] \
		&& log_error "failed to get gfmd port"
	log_debug "set_gfmd_params: set GFMD_PORT=$GFMD_PORT"

	[ "X$AUTH_TYPE" = X ] \
		&& log_error "failed to get auth type"
	log_debug "set_gfmd_params: set AUTH_TYPE=$AUTH_TYPE"

	[ "X$GFARM_CONF" = X ] \
		&& log_error "failed to get gfarm client conf file"
	log_debug "set_gfmd_params: set GFARM_CONF=$GFARM_CONF"

	log_debug "set_gfmd_params: set GFSD_CONF=$GFSD_CONF"

	log_debug "set_gfmd_params: set USERMAP_FILE=$USERMAP_FILE"

	[ "X$BACKEND_HOSTNAME" = X ] \
		&& log_error "failed to get hostname"
	log_debug "set_gfmd_params: set BACKEND_HOSTNAME=$BACKEND_HOSTNAME"

	log_debug "end set_gfmd_params"
	return 0
}

#
# Set variables for gfsd operations.
#
set_gfsd_params()
{
	log_debug "set_gfsd_params"
	CONFIG_GFSD_OPTIONS=`get_param config-gfsd-options || echo ''`

	eval `config-gfsd -T $CONFIG_GFSD_OPTIONS`
	[ "X$GFSD_RC" = X ] \
		&& log_error "failed to get rc script name for gfsd"
	log_debug "set_gfsd_params: set GFSD_RC=$GFSD_RC"

	[ "X$GFSD_PID_FILE" = X ] \
		&& log_error "failed to get gfsd pid file"
	log_debug "set_gfsd_params: set GFSD_PID_FILE=$GFSD_PID_FILE"

	[ "X$ARCH" = X ] \
		&& log_error "failed to get architecture"
	log_debug "set_gfsd_params: set ARCH=$ARCH"

	SPOOL_DIR=$SPOOL_DIRECTORY
	[ "X$SPOOL_DIR" = X ] \
		&& log_error "failed to get spool directory"
	log_debug "set_gfsd_params: set SPOOL_DIR=$SPOOL_DIR"

	[ "X$GFARM_CONF" = X ] \
		&& log_error "failed to get gfarm client conf file"
	log_debug "set_gfsd_params: set GFARM_CONF=$GFARM_CONF"

	log_debug "set_gfsd_params: set GFSD_CONF=$GFSD_CONF"

	log_debug "set_gfsd_params: set USERMAP_FILE=$USERMAP_FILE"

	[ "X$GFSD_HOSTNAME" = X ] \
		&& log_error "failed to get hostname"
	log_debug "set_gfsd_params: set GFSD_HOSTNAME=$GFHOSTNAME"

	log_debug "end set_gfsd_params"
	return 0
}

#
# Set variables for client operations.
#
set_client_params()
{
	log_debug "set_client_params"

	GFARM_CONF=`get_param gfarm-conf`
	[ "X$GFARM_CONF" = X ] \
		&& log_error "failed to get gfarm client conf file"
	log_debug "set_client_params: set GFARM_CONF=$GFARM_CONF"

	log_debug "end set_client_params"
	return 0
}

#
# Set appropriate variables with given host type.
#
set_params()
{
	log_debug "set_params"

	case $HOSTID in
	gfmd*)
		set_gfmd_params
		;;
	gfsd*)
		set_gfsd_params
		;;
	client*)
		set_client_params
		;;
	esac

	log_debug "end set_params"
	return 0
}

#
# Set a directive of a configuration file.
#
set_conf()
{
	log_debug "set_conf: FILE=$1, DIRECTIVE=$2, VALUE=$3"

	[ -f $1 ] || log_error "file $1 not found"
	trap "rm -f $1.tmp; exit 1" 1 2 3 15
	rm -f $1.tmp
	cp -f $1 $1.tmp
	cat /dev/null > $1.tmp

	(
		sed -e "/^$2[ 	]/d" $1
		echo
		echo "$2 $3"
	) > $1.tmp
	[ $? -ne 0 ] && log_error "failed to create $1.tmp"
	mv -f $1.tmp $1
	[ $? -ne 0 ] && log_error "failed to replace $1"

	log_debug "end set_conf"
	return 0
}

#
# Unset a directive of a configuration file.
#
unset_conf()
{
	log_debug "unset_conf: FILE=$1, DIRECTIVE=$2"

	[ -f $1 ] || log_error "file $1 not found"
	trap "rm -f $1.tmp; exit 1" 1 2 3 15
	rm -f $1.tmp
	cp -f $1 $1.tmp
	cat /dev/null > $1.tmp

	sed -e "/^$2[ 	]/d" $1 > $1.tmp
	[ $? -ne 0 ] && log_error "failed to create $1.tmp"
	mv -f $1.tmp $1
	[ $? -ne 0 ] && log_error "failed to replace $1"

	log_debug "end unset_conf"
	return 0
}

#
# Restore a file, reading data from standard in.
#
restore_file()
{
	log_debug "replace_file: FILE=$1 UMASK=$2"

	mkdir -p `dirname $GFARM_CONF`
	trap "rm -f $1.tmp; exit 1" 1 2 3 15
	rm -f $1.tmp
	(
	umask $2
	cp -f $1 $1.tmp
	cat /dev/null > $1.tmp

	cat > $1.tmp && mv -f $1.tmp $1
	)
	[ $? -ne 0 ] && log_error "failed to replace $1"
	rm -f $1.tmp

	log_debug "end replace_file"
}

#
# Examine if PostgreSQL is running.
#   TO DO: Don't execute $BACKEND_RC.
#
get_pgsql_status()
{
	log_debug "get_pgsql_status"

	if [ -x /bin/systemctl ]; then
		systemctl status `basename $BACKEND_RC` > /dev/null 2>&1
		RESULT=$?
	else
		$BACKEND_RC status > /dev/null 2>&1
		RESULT=$?
	fi

	if [ $RESULT -eq 0 ]; then
		log_debug "end get_pgsql_status: return 0"
		return 0
	else
		log_debug "end get_pgsql_status: return 1"
		return 1
	fi
}

#
# Examine if gfmd is running.
#   TO DO: Don't execute $GFMD_RC.
#
get_gfmd_status()
{
	log_debug "get_gfmd_status"

	if [ -x /bin/systemctl ]; then
		systemctl status `basename $GFMD_RC` > /dev/null 2>&1
		RESULT=$?
	else
		$GFMD_RC status > /dev/null 2>&1
		RESULT=$?
	fi

	if [ $RESULT -eq 0 ]; then
		log_debug "end get_gfmd_status: return 0"
		return 0
	else
		log_debug "end get_gfmd_status: return 1"
		return 1
	fi
}

#
# Examine if gfsd is running.
#   TO DO: Don't execute $GFSD_RC.
#
get_gfsd_status()
{
	log_debug "get_gfsd_status"

	if [ -x /bin/systemctl ]; then
		systemctl status `basename $GFSD_RC` > /dev/null 2>&1
		RESULT=$?
	else
		$GFSD_RC status > /dev/null 2>&1
		RESULT=$?
	fi

	if [ $RESULT -eq 0 ]; then
		log_debug "end get_gfsd_status: return 0"
		return 0
	else
		log_debug "end get_gfsd_status: return 1"
		return 1
	fi
}

#
# Start backend DB.
#
start_backend_db()
{
	log_debug "start_backend_db"

	if [ -x /bin/systemctl ]; then
		log_debug "start_backend_db: execute gfservice-timeout $1" \
			"systemctl start `basename $BACKEND_RC`"
		gfservice-timeout $1 systemctl start \
			`basename $BACKEND_RC` > /dev/null 2>&1
	else
		log_debug "start_backend_db: execute gfservice-timeout $1" \
			"$BACKEND_RC start"
		gfservice-timeout $1 $BACKEND_RC start > /dev/null 2>&1
	fi
	log_debug "end start_backend_db"
}

#
# Stop backend DB.
#
stop_backend_db()
{
	log_debug "stop_backend_db"

	TIMEOUT=`get_param timeout || echo 'no'`

	if [ -x /bin/systemctl ]; then
		log_debug "stop_backend_db: execute gfservice-timeout $1" \
			"systemctl stop `basename $BACKEND_RC`"
		gfservice-timeout $1 systemctl stop \
			`basename $BACKEND_RC` > /dev/null 2>&1
	else
		log_debug "stop_backend_db: execute gfservice-timeout $1" \
			"$BACKEND_RC stop"
		gfservice-timeout $1 $BACKEND_RC stop > /dev/null 2>&1
	fi
	log_debug "end stop_backend_db"
}

#
# Start gfmd.
#
start_gfmd()
{
	log_debug "start_gfmd"

	TIMEOUT=`get_param timeout || echo 'no'`

	if [ -x /bin/systemctl ]; then
		log_debug "start_gfmd: execute gfservice-timeout $1" \
			"systemctl start `basename $GFMD_RC`"
		gfservice-timeout $1 systemctl start \
			`basename $GFMD_RC` > /dev/null 2>&1
	else
		log_debug "start_gfmd: execute gfservice-timeout $1" \
			"$GFMD_RC start"
		gfservice-timeout $1 $GFMD_RC start > /dev/null 2>&1
	fi
	[ $? -eq $EXITCODE_TIMEOUT ] && log_error "failed to start backend DB"

	log_debug "end: start_gfmd"
}

#
# Start gfmd as a slave.
#
slavestart_gfmd()
{
	log_debug "slavestart_gfmd"

	TIMEOUT=`get_param timeout || echo 'no'`

	if [ -x /bin/systemctl ]; then
		log_debug "slavestart_gfmd: execute gfservice-timeout $1" \
			"systemctl start `basename $GFMD_RC`"
		# NOTE: "systemctl slavestart" is not defined.
		set_conf $GFMD_CONF metadb_server_force_slave enable
		gfservice-timeout $1 systemctl start \
			`basename $GFMD_RC` > /dev/null 2>&1
	else
		log_debug "slavestart_gfmd: execute gfservice-timeout $1" \
			"$GFMD_RC start"
		gfservice-timeout $1 $GFMD_RC slavestart > /dev/null 2>&1
	fi
	[ $? -eq $EXITCODE_TIMEOUT ] && log_error "failed to slavestart backend DB"

	log_debug "end: slavestart_gfmd"
}

#
# Stop gfmd.
#
stop_gfmd()
{
	log_debug "stop_gfmd"

	TIMEOUT=`get_param timeout || echo 'no'`

	if [ -x /bin/systemctl ]; then
		log_debug "stop_gfmd: execute gfservice-timeout $1" \
			"systemctl stop `basename $GFMD_RC`"
		gfservice-timeout $1 systemctl stop \
			`basename $GFMD_RC` > /dev/null 2>&1
	else
		log_debug "stop_gfmd: execute gfservice-timeout $1" \
			"$GFMD_RC stop"
		gfservice-timeout $1 $GFMD_RC stop > /dev/null 2>&1
	fi
	[ $? -eq $EXITCODE_TIMEOUT ] && log_error "failed to stop backend DB"

	log_debug "end: stop_gfmd"
}

#
# Kill gfmd.
#
kill_gfmd()
{
	log_debug "kill_gfmd"

	TIMEOUT=`get_param timeout || echo 'no'`

	if [ -x /bin/systemctl ]; then
		log_debug "start_gfmd: execute gfservice-timeout $1" \
			"systemctl kill `basename $GFMD_RC`"
		gfservice-timeout $1 systemctl kill \
			`basename $GFMD_RC` > /dev/null 2>&1
	else
		log_debug "kill_gfmd: execute gfservice-timeout $1" \
			"$GFMD_RC kill"
		gfservice-timeout $1 $GFMD_RC kill > /dev/null 2>&1
	fi
	[ $? -eq $EXITCODE_TIMEOUT ] && log_error "failed to kill backend DB"

	log_debug "end: kill_gfmd"
}

#
# Start gfsd.
#
start_gfsd()
{
	log_debug "start_gfsd"

	TIMEOUT=`get_param timeout || echo 'no'`

	if [ -x /bin/systemctl ]; then
		log_debug "start_gfsd: execute gfservice-timeout $1" \
			"systemctl start `basename $GFSD_RC`"
		gfservice-timeout $1 systemctl start \
			`basename $GFSD_RC` > /dev/null 2>&1
	else
		log_debug "start_gfsd: execute gfservice-timeout $1" \
			"$GFSD_RC start"
		gfservice-timeout $1 $GFSD_RC start > /dev/null 2>&1
	fi
	[ $? -eq $EXITCODE_TIMEOUT ] && log_error "failed to start backend DB"

	log_debug "end: start_gfsd"
}

#
# Stop gfsd.
#
stop_gfsd()
{
	log_debug "stop_gfsd"

	TIMEOUT=`get_param timeout || echo 'no'`

	if [ -x /bin/systemctl ]; then
		log_debug "stop_gfsd: execute gfservice-timeout $1" \
			"systemctl stop `basename $GFSD_RC`"
		gfservice-timeout $1 systemctl stop \
			`basename $GFSD_RC` > /dev/null 2>&1
	else
		log_debug "stop_gfsd: execute gfservice-timeout $1" \
			"$GFSD_RC stop"
		gfservice-timeout $1 $GFSD_RC stop > /dev/null 2>&1
	fi
	[ $? -eq $EXITCODE_TIMEOUT ] && log_error "failed to stop backend DB"

	log_debug "end: stop_gfsd"
}

######################################################################

#
# Sub-command: get-config-gfarm-param
# Output result of 'config-gfarm -T'.
#
subcmd_get_config_gfarm_param()
{
	log_debug "subcmd_get_config_gfarm_param"

	PARAM=`get_param param`
	if [ "X$PARAM" = X ]; then
		eval config-gfarm -T $CONFIG_GFARM_OPTIONS
	else
		VALUE=`eval config-gfarm -T $CONFIG_GFARM_OPTIONS \
			| sed -ne "/^$PARAM=/s/^[^=]*=//p"`
		echo $VALUE
		log_debug "subcmd_get_config_gfarm_param: param=$PARAM," \
			"value=$VALUE"
	fi
	log_debug "end subcmd_get_config_gfarm_param"
}

#
# Sub-command: get-config-gfsd-param
# Output result of 'config-gfsd -T'.
#
subcmd_get_config_gfsd_param()
{
	log_debug "subcmd_get_config_gfsd_param"

	PARAM=`get_param param`
	if [ "X$PARAM" = X ]; then
		eval config-gfsd -T $CONFIG_GFSD_OPTIONS
	else
		log_debug "subcmd_get_config_gfsd_param: param=$PARAM"
		config-gfsd -T $CONFIG_GFSD_OPTIONS \
			| sed -ne "/^$PARAM=/s/^[^=]*=//p"
		log_debug "subcmd_get_config_gfsd_param: param=$PARAM," \
			"value="`config-gfsd -T $CONFIG_GFSD_OPTIONS \
			| sed -ne "/^$PARAM=/s/^[^=]*=//p"`
	fi

	log_debug "end subcmd_get_config_gfsd_param"
}

#
# Sub-command: backend-db-status
# Examine if backend-db is running.
#
subcmd_backend_db_status()
{
	log_debug "subcmd_backend_db_status"

	if get_pgsql_status; then
		echo "backend-db is running"
		RESULT=0
	else
		echo "backend-db is not running"
		RESULT=1
	fi
		
	log_debug "end subcmd_backend_db_status: returns $RESULT"
	return $RESULT
}

#
# Sub-command: gfmd-status
# Examine if gfmd is running.
#
subcmd_gfmd_status()
{
	log_debug "subcmd_gfmd_status"

	if get_gfmd_status; then
		echo "gfmd is running"
		RESULT=0
	else
		echo "gfmd is not running"
		RESULT=1
	fi
		
	log_debug "end subcmd_gfmd_status: returns $RESULT"
	return $RESULT
}

#
# Sub-command: gfsd-status
# Examine if gfmd is running.
#
subcmd_gfsd_status()
{
	log_debug "subcmd_gfsd_status"

	if get_gfsd_status; then
		echo "gfsd is running"
		RESULT=0
	else
		echo "gfsd is not running"
		RESULT=1
	fi

	log_debug "end subcmd_gfsd_status: returns $RESULT"
	return $RESULT
}

#
# Sub-command: start-backend_db
# Start PostgreSQL.
#
subcmd_start_backend_db()
{
	log_debug "subcmd_start_backend_db"

	TIMEOUT=`get_param timeout || echo 'no'`
	start_backend_db $TIMEOUT
	log_debug "end subcmd_start_backend_db"
}

#
# Sub-command: start-gfmd
# Start gfmd.
#
subcmd_start_gfmd()
{
	log_debug "subcmd_start_gfmd"

	TIMEOUT=`get_param timeout || echo 'no'`
	start_gfmd $TIMEOUT
	log_debug "subcmd_start_gfmd"
}

#
# Sub-command: start-gfmd-master
# Start gfmd as a master.
#
subcmd_start_gfmd_master()
{
	log_debug "subcmd_start_gfmd_master"

	TIMEOUT=`get_param timeout || echo 'no'`
	unset_conf $GFMD_CONF metadb_server_force_slave
	log_debug "subcmd_start_gfmd_master:" \
		"execute gfservice-timeout $TIMEOUT $GFMD_RC start"
	start_gfmd $TIMEOUT
	log_debug "end subcmd_start_gfmd_master"
}

#
# Sub-command: start-gfmd-slave
# Start gfmd as a slave.
#
subcmd_start_gfmd_slave()
{
	log_debug "subcmd_start_gfmd_slave"

	TIMEOUT=`get_param timeout || echo 'no'`
	slavestart_gfmd $TIMEOUT
	log_debug "end subcmd_start_gfmd_slave"
}

#
# Sub-command: start-gfsd
# Start gfsd.
#
subcmd_start_gfsd()
{
	log_debug "subcmd_start_gfsd"

	TIMEOUT=`get_param timeout || echo 'no'`
	start_gfsd $TIMEOUT
	log_debug "end subcmd_start_gfsd"
}

#
# Sub-command: stop-backend-db
# Stop PostgreSQL.
#
subcmd_stop_backend_db()
{
	log_debug "subcmd_stop_backend_db"

	TIMEOUT=`get_param timeout || echo 'no'`
	stop_backend_db $TIMEOUT
	log_debug "end subcmd_stop_backend_db"
}

#
# Sub-command: stop-gfmd
# Stop gfmd.
#
subcmd_stop_gfmd()
{
	log_debug "subcmd_stop_gfmd"

	TIMEOUT=`get_param timeout || echo 'no'`
	stop_gfmd $TIMEOUT
	log_debug "end subcmd_stop_gfmd"
}

#
# Sub-command: Kill-gfmd
# Kill gfmd.
#
subcmd_kill_gfmd()
{
	log_debug "subcmd_kill_gfmd"

	TIMEOUT=`get_param timeout || echo 'no'`
	kill_gfmd $TIMEOUT
	log_debug "end subcmd_kill_gfmd"
}

#
# Sub-command: stop-gfsd
# Stop gfsd.
#
subcmd_stop_gfsd()
{
	log_debug "subcmd_stop_gfsd"

	TIMEOUT=`get_param timeout || echo 'no'`
	stop_gfsd $TIMEOUT
	log_debug "end subcmd_stop_gfsd"
}

#
# Sub-command: config-gfarm
# Configure gfarm (gfmd + gfarm-pgsql).
#
subcmd_config_gfarm()
{
	log_debug "subcmd_config_gfarm"

	log_debug "subcmd_config_gfarm:" \
		"execute config-gfarm $CONFIG_GFARM_OPTIONS"
	eval config-gfarm $CONFIG_GFARM_OPTIONS
	[ $? -ne 0 ] && log_error "config-gfarm failed"

	case $AUTH_TYPE in
	gsi|gsi_auth) set_conf $GFMD_CONF 'auth enable sharedsecret' '*';;
	esac

	TIMEOUT=`get_param timeout || echo 'no'`
	stop_gfmd $TIMEOUT
	start_gfmd $TIMEOUT

	log_debug "end subcmd_config_gfarm"
}

#
# Sub-command: config-gfarm-master
# Configure gfarm (gfmd + gfarm-pgsql) with replication support.
#
subcmd_config_gfarm_master()
{
	log_debug "subcmd_config_gfarm_master"

	log_debug "subcmd_config_gfarm_master:" \
		"execute config-gfarm -r $CONFIG_GFARM_OPTIONS"
	eval config-gfarm -r $CONFIG_GFARM_OPTIONS
	[ $? -ne 0 ] && log_error "config-gfarm failed"

	unset_conf $GFMD_CONF metadb_server_force_slave
	case $AUTH_TYPE in
	gsi|gsi_auth) set_conf $GFMD_CONF 'auth enable sharedsecret' '*';;
	esac

	set_conf $GFARM_CONF metadb_server_list \
		"${BACKEND_HOSTNAME}:${GFMD_PORT}"

	TIMEOUT=`get_param timeout || echo 'no'`
	stop_gfmd $TIMEOUT
	start_gfmd $TIMEOUT

	log_debug "end subcmd_config_gfarm_master"
}

#
# Sub-command: config-gfsd
# Configure gfsd.
#
subcmd_config_gfsd()
{
	log_debug "subcmd_config_gfsd"

	log_debug "subcmd_config_gfsd:" \
		"execute config-gfsd $CONFIG_GFSD_OPTIONS"
	config-gfsd $CONFIG_GFSD_OPTIONS
	[ $? -ne 0 ] && log_error "config-gfsd failed"

	log_debug "end subcmd_config_gfsd"
}

#
# Sub-command: unconfig-gfarm
# Unconfigure gfarm (gfmd + gfarm-pgsql).
#
subcmd_unconfig_gfarm()
{
	log_debug "subcmd_unconfig_gfarm"

	TIMEOUT=`get_param timeout || echo 'no'`
	[ -f $GFMD_RC ] && stop_gfmd $TIMEOUT > /dev/null 2>&1
	[ -f $BACKEND_RC ] && stop_backend_db $TIMEOUT > /dev/null 2>&1
	rm -f $GFMD_PID_FILE
	rm -f $GFARM_CONF
	rm -f $GFMD_CONF
	rm -f $GFMD_RC
	rm -f $BACKEND_RC
	rm -f -r $METADATA_DIR
	rm -f -r $JOURNAL_DIR
	[ "X$GFSD_CONF" != X ] && rm -f $GFSD_CONF
	[ "X$USERMAP_FILE" != X ] && rm -f $USERMAP_FILE

	log_debug "end subcmd_unconfig_gfarm"
}

#
# Sub-command: unconfig-gfsd
# Unconfigure gfsd.
#
subcmd_unconfig_gfsd()
{
	log_debug "subcmd_unconfig_gfsd"

	TIMEOUT=`get_param timeout || echo 'no'`
	[ -f $GFSD_RC ] && stop_gfsd $TIMEOUT > /dev/null 2>&1
	rm -f $GFSD_PID_FILE
	rm -f $GFARM_CONF
	rm -f $GFSD_RC
	rm -f -r $SPOOL_DIR
	[ "X$GFSD_CONF" != X ] && rm -f $GFSD_CONF
	[ "X$USERMAP_FILE" != X ] && rm -f $USERMAP_FILE

	log_debug "end subcmd_unconfig_gfsd"
}

#
# Sub-command: unconfig-client
# Unconfigure client host.
#
subcmd_unconfig_client()
{
	log_debug "subcmd_unconfig_client"

	rm -f $GFARM_CONF
	rm -f $SHARED_KEY_FILE

	log_debug "end subcmd_unconfig_client"
}

#
# Sub-command: promote (alias: promote-gfmd)
# Promote the slave gfmd to master.
#
subcmd_promote()
{
	log_debug "subcmd_promote"

	unset_conf $GFMD_CONF metadb_server_force_slave
	PID=`head -1 $GFMD_PID_FILE`
	[ $? -ne 0 -o "X$PID" = X ] \
		&& log_error "failed to get PID of gfmd from the PID file"
	kill -USR1 $PID

	log_debug "end subcmd_promote"
}

#
# Sub-command: mount
# Mount a Gfarm2 file system.
#
subcmd_mount()
{
	log_debug "subcmd_mount"

	MOUNT_GFARM2FS=`get_param mount-gfarm2fs`
	[ "X$MOUNT_GFARM2FS" = X ] && MOUNT_GFARM2FS="mount.gfarm2fs"
	DIRECTORY=`get_param directory` || {
		log_error "missing mandatory argument 'directory'"
	}
	log_debug "subcmd_mount: directory=$DIRECTORY"
	OPTIONS=`get_param options || echo ''`
	log_debug "subcmd_mount: options=$OPTIONS"
	log_debug "subcmd_mount:" \
		"execute $MOUNT_GFARM2FS $GFARM_CONF $DIRECTORY $OPTIONS"
	$MOUNT_GFARM2FS $GFARM_CONF $DIRECTORY $OPTIONS
	[ $? -ne 0 ] && log_error "failed to mount Gfarm2 filesystem"

	log_debug "end subcmd_mount"
}

#
# Sub-command: unmount (alias: umount)
# Unmount a Gfarm2 file system.
#
subcmd_unmount()
{
	log_debug "subcmd_unmount"

	UMOUNT_GFARM2FS=`get_param umount-gfarm2fs`
	[ "X$UMOUNT_GFARM2FS" = X ] && UMOUNT_GFARM2FS="umount.gfarm2fs"
	DIRECTORY=`get_param directory` || {
		log_error "missing mandatory argument 'directory'"
	}
	log_debug "subcmd_unmount: directory=$DIRECTORY"
	log_debug "subcmd_mount: execute $UMOUNT_GFARM2FS $DIRECTORY"
	$UMOUNT_GFARM2FS $DIRECTORY
	[ $? -ne 0 ] && log_error "failed to unmount Gfarm2 filesystem"

	log_debug "end subcmd_unmount"
}

#
# Sub-command: set-gfmd-conf
# Set a configuration parameter of 'gfmd.conf'.
#
subcmd_set_gfmd_conf()
{
	log_debug "subcmd_set_gfmd_conf"

	DIRECTIVE=`get_param directive` || {
		log_error "missing mandatory argument 'directive'"
	}
	log_debug "subcmd_set_gfmd_conf: directive=$DIRECTIVE"
	VALUE=`get_param value` || {
		log_error "missing mandatory argument 'value'"
	}
	log_debug "subcmd_set_gfmd_conf: value=$VALUE"
	set_conf $GFMD_CONF "$DIRECTIVE" "$VALUE"

	log_debug "end subcmd_set_gfmd_conf"
}

#
# Sub-command: set-gfarm-conf
# Set a configuration parameter of 'gfarm2.conf'.
#
subcmd_set_gfarm_conf()
{
	log_debug "subcmd_set_gfarm_conf"

	DIRECTIVE=`get_param directive` || {
		log_error "missing mandatory argument 'directive'"
	}
	VALUE=`get_param value` || {
		log_error "missing mandatory argument 'value'"
	}
	log_debug "subcmd_set_gfarm_conf: directive=$DIRECTIVE, value=$VALUE"
	set_conf $GFARM_CONF "$DIRECTIVE" "$VALUE"

	log_debug "end subcmd_set_gfarm_conf"
}

#
# Sub-command: set-gfsd-conf
# Set a configuration parameter of 'gfsd.conf'.
#
subcmd_set_gfsd_conf()
{
	log_debug "subcmd_set_gfsd_conf"

	DIRECTIVE=`get_param directive` || {
		log_error "missing mandatory argument 'directive'"
	}
	VALUE=`get_param value` || {
		log_error "missing mandatory argument 'value'"
	}
	log_debug "subcmd_set_gfsd_conf: directive=$DIRECTIVE, value=$VALUE"
	[ "X$GFSD_CONF" = X ] && log_error "not private mode"
	set_conf $GFSD_CONF "$DIRECTIVE" "$VALUE"

	log_debug "end subcmd_set_gfsd_conf"
}

#
# Sub-command: unset-gfmd-conf
# Unset a configuration parameter of 'gfmd.conf'.
#
subcmd_unset_gfmd_conf()
{
	log_debug "subcmd_unset_gfmd_conf"

	DIRECTIVE=`get_param directive` || {
		log_error "missing mandatory argument 'directive'"
	}
	log_debug "subcmd_unset_gfmd_conf: directive=$DIRECTIVE"
	unset_conf $GFMD_CONF "$DIRECTIVE"

	log_debug "end subcmd_unset_gfmd_conf"
}

#
# Sub-command: unset-gfarm-conf
# unset a configuration parameter of 'gfarm2.conf'.
#
subcmd_unset_gfarm_conf()
{
	log_debug "subcmd_unset_gfarm_conf"

	DIRECTIVE=`get_param directive` || {
		log_error "missing mandatory argument 'directive'"
	}
	log_debug "subcmd_unset_gfarm_conf: directive=$DIRECTIVE"

	unset_conf $GFARM_CONF "$DIRECTIVE"

	log_debug "end subcmd_unset_gfarm_conf"
}

#
# Sub-command: unset-gfsd-conf
# unset a configuration parameter of 'gfsd.conf'.
#
subcmd_unset_gfsd_conf()
{
	log_debug "subcmd_unset_gfsd_conf"

	DIRECTIVE=`get_param directive` || {
		log_error "missing mandatory argument 'directive'"
	}
	log_debug "subcmd_unset_gfsd_conf: directive=$DIRECTIVE"
	[ "X$GFSD_CONF" = X ] && log_error "not private mode"
	unset_conf $GFSD_CONF "$DIRECTIVE"

	log_debug "end subcmd_unset_gfsd_conf"
}

#
# Sub-command: backup-gfmd-conf
# Export 'gfmd.conf' to standard out.
#
subcmd_backup_gfmd_conf()
{
	log_debug "subcmd_backup_gfmd_conf"

	cat $GFMD_CONF
	[ $? -ne 0 ] && log_error "failed to backup $GFMD_CONF"

	log_debug "end subcmd_backup_gfmd_conf"
}

#
# Sub-command: backup-gfarm-conf
# Export 'gfarm2.conf' to standard out.
#
subcmd_backup_gfarm_conf()
{
	log_debug "subcmd_backup_gfarm_conf"

	cat $GFARM_CONF
	[ $? -ne 0 ] && log_error "failed to backup $GFARM_CONF"

	log_debug "end subcmd_backup_gfarm_conf"
}

#
# Sub-command: backup-gfsd-conf
# Export 'gfsd.conf' to standard out.
#
subcmd_backup_gfsd_conf()
{
	log_debug "subcmd_backup_gfsd_conf"

	[ "X$GFSD_CONF" = X ] && log_error "not private mode"
	cat $GFSD_CONF
	[ $? -ne 0 ] && log_error "failed to backup $GFSD_CONF"

	log_debug "end subcmd_backup_gfsd_conf"
}

#
# Sub-command: backup-usermap
# Export 'usermap' to standard out.
#
subcmd_backup_usermap()
{
	log_debug "subcmd_backup_usermap_file"

	[ "X$USERMAP_FILE" = X ] && log_error "not private mode"
	cat $USERMAP_FILE
	[ $? -ne 0 ] && log_error "failed to backup $USERMAP_FILE"

	log_debug "end subcmd_backup_usermap_file"
}

#
# Sub-command: backup-shared-key
# Export '.gfarm_shared_key' to standard out.
#
subcmd_backup_shared_key()
{
	log_debug "subcmd_backup_shared_key"

	cat $SHARED_KEY_FILE
	[ $? -ne 0 ] && log_error "failed to backup $SHARED_KEY_FILE"

	log_debug "end subcmd_backup_shared_key"
}

#
# Sub-command: backup-backend-db
# Dump PostgreSQL database to standard out.
#
subcmd_backup_backend_db()
{
	log_debug "subcmd_backup_backend_db"

	if [ X$CONFIG_PREFIX = X ]; then
		gfdump.postgresql -d -f - -P $BACKEND_PREFIX
	else
		gfdump.postgresql -d -f - -P $BACKEND_PREFIX \
			--prefix $CONFIG_PREFIX
	fi

	[ $? -ne 0 ] && log_error "failed to dump database"

	log_debug "end subcmd_backup_backend_db"
}

#
# Sub-command: restore-gfmd-conf
# Import 'gfmd.conf' from standard in.
#
subcmd_restore_gfmd_conf()
{
	log_debug "subcmd_restore_gfmd_conf"

	restore_file $GFMD_CONF 077

	log_debug "end subcmd_restore_gfmd_conf"
}

#
# Sub-command: restore-gfarm-conf
# Import 'gfarm2.conf' from standard in.
#
subcmd_restore_gfarm_conf()
{
	log_debug "subcmd_restore_gfarm_conf"

	restore_file $GFARM_CONF 022

	log_debug "end subcmd_restore_gfarm_conf"
}

#
# Sub-command: restore-gfsd-conf
# Import 'gfsd.conf' from standard in.
#
subcmd_restore_gfsd_conf()
{
	log_debug "subcmd_restore_gfsd_conf"

	[ "X$GFSD_CONF" = X ] && log_error "not private mode"
	restore_file $GFSD_CONF 022

	log_debug "end subcmd_restore_gfsd_conf"
}

#
# Sub-command: restore-usermap
# Import 'usermap' from standard in.
#
subcmd_restore_usermap()
{
	log_debug "subcmd_restore_usermap"

	[ "X$USERMAP_FILE" = X ] && log_error "not private mode"
	restore_file $USERMAP_FILE 022

	log_debug "end subcmd_restore_usermap"
}

#
# Sub-command: restore-shared-key
# Import '.gfarm_shared_key' from standard in.
#
subcmd_restore_shared_key()
{
	log_debug "subcmd_restore_shared_key"

	restore_file $SHARED_KEY_FILE 077

	log_debug "end subcmd_restore_shared_key"
}

#
# Sub-command: restore-backend-db
# Import PostgreSQL database from standard in.
#
subcmd_restore_backend_db()
{
	log_debug "subcmd_restore_backend_db"

	if [ X$CONFIG_PREFIX = X ]; then
		gfdump.postgresql -r -n -f - -P $BACKEND_PREFIX
	else
		gfdump.postgresql -r -n -f - -P $BACKEND_PREFIX \
			--prefix $CONFIG_PREFIX
	fi
	[ $? -ne 0 ] && log_error "failed to restore database"

	log_debug "end subcmd_restore_backend_db"
}

#
# Sub-command: gfcmd
# Exec gf* command.
#
subcmd_gfcmd()
{
	log_debug "subcmd_gfcmd"

	CMD=`get_param cmd`
	expr "X$CMD" : '^Xgf[a-z0-9._-]*$' > /dev/null 2>&1 || {
		log_error "invalid command name: '$CMD'"
	}
	ARGS=`get_param args`
	log_debug "subcmd_gfcmd: execute @bindir@/$CMD $ARGS"
	env GFARM_CONFIG_FILE=$GFARM_CONF "@bindir@/$CMD" $ARGS
	[ $? -ne 0 ] && log_error "command $CMD failed"

	log_debug "end subcmd_gfcmd"
}

#
# Sub-command: grid-proxy-init
# Exec 'grid-proxy-init' command.
#
subcmd_grid_proxy_init()
{
	log_debug "subcmd_grid_proxy_init"

	if [ "X$GLOBUS_LOCATION" = X ]; then
		GRID_PROXY_INIT=grid-proxy-init
	else
		GRID_PROXY_INIT="$GLOBUS_LOCATION/grid-proxy-init"
	fi

	ARGS=`get_param args`
	log_debug "subcmd_gfcmd: execute $GRID_PROXY_INIT $ARGS"
	$GRID_PROXY_INIT $ARGS
	[ $? -ne 0 ] && log_error "command $GRID_PROXY_INIT failed"

	log_debug "end subcmd_grid_proxy_init"
}

######################################################################

#
# Parse command line arguments.
#
OPT=
while true; do
	if [ "X$OPT" = X ]; then
		[ $# -eq 0 ] && break
		case "$1" in
		--)	shift
			break
			;;
		-)	break
			;;
		-*)	OPT="$1"
			shift
			;;
		*)	break
			;;
		esac
	fi
	while [ "X$OPT" != X ]; do
		case "$OPT" in
		-d)	DEBUG=true
			OPT=
			;;
		-d*)	DEBUG=true
			OPT=`echo "X$OPT" | sed -e 's/^X-./-/'`
			;;
		*)	BAD_OPT=`echo "X$OPT" | sed -e 's/^X-\(.\).*$/\1/'`
			echo "$0: invalid option -- '$BAD_OPT'" 1>&2
			exit 1
			;;
		esac
	done
done

if [ $# -lt 2 ]; then
	echo "$0: too few argument" 1>&2
	exit 1
fi
SUBCMD="$2"
log_debug "main: set SUBCMD=$SUBCMD"
HOSTID="$1"
log_debug "main: set HOSTID=$HOSTID"
shift 2

ARGC=0
for I in "$@"; do
	eval "ARGV$ARGC=\$I"
	log_debug "main: set ARGV$ARGC=$I"
	ARGC=`expr $ARGC + 1`
done

set_params

#
# Perform the sub-command $SUBCMD.
#
case "$SUBCMD" in
get-config-gfarm-param)
	subcmd_get_config_gfarm_param
	;;
get-config-gfsd-param)
	subcmd_get_config_gfsd_param
	;;
backend-db-status)
	subcmd_backend_db_status || exit 1
	;;
gfmd-status)
	subcmd_gfmd_status || exit 1
	;;
gfsd-status)
	subcmd_gfsd_status || exit 1
	;;
start-backend-db)
	subcmd_start_backend_db
	;;
start-gfmd)
	subcmd_start_gfmd
	;;
start-gfmd-master)
	subcmd_start_gfmd_master
	;;
start-gfmd-slave)
	subcmd_start_gfmd_slave
	;;
start-gfsd)
	subcmd_start_gfsd
	;;
stop-backend-db)
	subcmd_stop_backend_db
	;;
stop-gfmd)
	subcmd_stop_gfmd
	;;
stop-gfsd)
	subcmd_stop_gfsd
	;;
kill-gfmd)
	subcmd_kill_gfmd
	;;
config-gfarm)
	subcmd_config_gfarm
	;;
config-gfarm-master)
	subcmd_config_gfarm_master
	;;
config-gfsd)
	subcmd_config_gfsd
	;;
unconfig-gfarm)
	subcmd_unconfig_gfarm
	;;
unconfig-gfsd)
	subcmd_unconfig_gfsd
	;;
unconfig-client)
	subcmd_unconfig_client
	;;
promote|promote-gfmd)
	subcmd_promote
	;;
mount)	subcmd_mount
	;;
unmount|umount)
	subcmd_unmount
	;;
set-gfmd-conf)
	subcmd_set_gfmd_conf
	;;
set-gfarm-conf)
	subcmd_set_gfarm_conf
	;;
set-gfsd-conf)
	subcmd_set_gfsd_conf
	;;
unset-gfmd-conf)
	subcmd_unset_gfmd_conf
	;;
unset-gfarm-conf)
	subcmd_unset_gfarm_conf
	;;
unset-gfsd-conf)
	subcmd_unset_gfsd_conf
	;;
backup-gfmd-conf)
	subcmd_backup_gfmd_conf
	;;
backup-gfarm-conf)
	subcmd_backup_gfarm_conf
	;;
backup-shared-key)
	subcmd_backup_shared_key
	;;
backup-backend-db)
	subcmd_backup_backend_db
	;;
backup-gfsd-conf)
	subcmd_backup_gfsd_conf
	;;
backup-usermap)
	subcmd_backup_usermap
	;;
restore-gfmd-conf)
	subcmd_restore_gfmd_conf
	;;
restore-gfarm-conf)
	subcmd_restore_gfarm_conf
	;;
restore-shared-key)
	subcmd_restore_shared_key
	;;
restore-backend-db)
	subcmd_restore_backend_db
	;;
restore-gfsd-conf)
	subcmd_restore_gfsd_conf
	;;
restore-usermap)
	subcmd_restore_usermap
	;;
gfcmd)
	subcmd_gfcmd "$@"
	;;
grid-proxy-init)
	subcmd_grid_proxy_init "$@"
	;;
*)
	SUBCMD="`echo $SUBCMD | sed -e 's|::|/|g'`"
	SUBCMD_FUNC="`basename $SUBCMD | sed -e 's|-|_|g'`"
	if [ -f $GFSERVICE_PLUGIN_DIR/$SUBCMD ]; then
		log_debug "loading plugin: $SUBCMD"
		. $GFSERVICE_PLUGIN_DIR/$SUBCMD

		DEFPEND_FILES="`${SUBCMD_FUNC}_agent_depends \
			| sed -e 's|::|/|g'`"
		for I in $DEFPEND_FILES; do
			log_debug "loading plugin: $I"
			. $GFSERVICE_PLUGIN_DIR/$I
		done

		subcmd_${SUBCMD_FUNC}_agent "$@"
	else
		echo "$0: invalid sub-command: $SUBCMD" 1>&2
		exit 1
	fi
	;;
esac

exit 0
