#!/bin/sh
# Start/stop ceph daemons
# chkconfig: 2345 60 80

### BEGIN INIT INFO
# Provides:          ceph
# Default-Start:     2 3 5
# Default-Stop:      0 1 6
# Required-Start:    $remote_fs $named $network $time
# Required-Stop:     $remote_fs $named $network $time
# Short-Description: Start Ceph distributed file system daemons at boot time
# Description:       Enable Ceph distributed file system services.
### END INIT INFO

# if we start up as ./mkcephfs, assume everything else is in the
# current directory too.
if [ `dirname $0` = "." ] && [ $PWD != "/etc/init.d" ]; then
    BINDIR=.
    LIBDIR=.
    ETCDIR=.
else
    BINDIR=/usr/bin
    LIBDIR=/usr/lib/ceph
    ETCDIR=/etc/ceph
fi

usage_exit() {
    echo "usage: $0 [options] {start|stop|restart} [mon|osd|mds]..."
    printf "\t-c ceph.conf\n"
    printf "\t--valgrind\trun via valgrind\n"
    printf "\t--hostname [hostname]\toverride hostname lookup\n"
    exit
}

. $LIBDIR/ceph_common.sh

EXIT_STATUS=0

signal_daemon() {
    name=$1
    daemon=$2
    pidfile=$3
    signal=$4
    action=$5
    [ -z "$action" ] && action="Stopping"
    echo -n "$action Ceph $name on $host..."
    do_cmd "if [ -e $pidfile ]; then
        pid=`cat $pidfile`
        if [ -e /proc/\$pid ] && grep -q $daemon /proc/\$pid/cmdline ; then
	    cmd=\"kill $signal \$pid\"
	    echo -n \$cmd...
	    \$cmd
        fi
    fi"
    echo done
}

daemon_is_running() {
    name=$1
    daemon=$2
    daemon_id=$3
    pidfile=$4
    do_cmd "[ -e $pidfile ] || exit 1   # no pid, presumably not running
	pid=\`cat $pidfile\`
	[ -e /proc/\$pid ] && grep -q $daemon /proc/\$pid/cmdline && grep -qwe -i.$daemon_id /proc/\$pid/cmdline && exit 0 # running
        exit 1  # pid is something else" "" "okfail"
}

stop_daemon() {
    name=$1
    daemon=$2
    pidfile=$3
    signal=$4
    action=$5
    [ -z "$action" ] && action="Stopping"
    echo -n "$action Ceph $name on $host..."
    do_cmd "while [ 1 ]; do 
	[ -e $pidfile ] || break
	pid=\`cat $pidfile\`
	while [ -e /proc/\$pid ] && grep -q $daemon /proc/\$pid/cmdline ; do
	    cmd=\"kill $signal \$pid\"
	    echo -n \$cmd...
	    \$cmd
	    sleep 1
	    continue
	done
	break
    done"
    echo done
}

## command line options
options=

version=0
dovalgrind=
docrun=
allhosts=0
debug=0
monaddr=
dobtrfs=1
dobtrfsumount=0
verbose=0

while echo $1 | grep -q '^-'; do     # FIXME: why not '^-'?
case $1 in
    -v | --verbose)
	    verbose=1
	    ;;
    --valgrind)
	    dovalgrind=1
	    ;;
    --novalgrind)
	    dovalgrind=0
	    ;;
    --allhosts | -a)
	    allhosts=1;
	    ;;
    --restart)
	    docrun=1
	    ;;
    --norestart)
	    docrun=0
	    ;;
    -m )
	    [ -z "$2" ] && usage_exit
	    options="$options $1"
	    shift
	    MON_ADDR=$1
	    ;;
    --btrfs)
	    dobtrfs=1
	    ;;
    --nobtrfs)
	    dobtrfs=0
	    ;;
    --btrfsumount)
	    dobtrfsumount=1
	    ;;
    --conf | -c)
	    [ -z "$2" ] && usage_exit
	    options="$options $1"
	    shift
	    conf=$1
	    ;;
    --hostname )
	    [ -z "$2" ] && usage_exit
	    options="$options $1"
	    shift
	    hostname=$1
            ;;
    *)
	    echo unrecognized option \'$1\'
	    usage_exit
	    ;;
esac
options="$options $1"
shift
done

verify_conf

command=$1
[ -n "$*" ] && shift

get_name_list "$@"

for name in $what; do
    type=`echo $name | cut -c 1-3`   # e.g. 'mon', if $item is 'mon1'
    id=`echo $name | cut -c 4- | sed 's/^\\.//'`
    num=$id
    name="$type.$id"

    get_conf auto_start "" "auto start"
    if [ -z "$@" ] || [ "$@" = "mds" ]; then
	if [ "$auto_start" = "no" ] || [ "$auto_start" = "false" ] || [ "$auto_start" = "0" ]; then
	    continue
	fi
    fi

    check_host || continue

    get_conf pid_file "/var/run/ceph/$type.$id.pid" "pid file"
    [ -n "$pid_file" ] && do_cmd "mkdir -p "`dirname $pid_file`

    get_conf log_dir "" "log dir"
    get_conf log_sym_dir "" "log sym dir"
    [ -n "$log_dir" ] && do_cmd "mkdir -p $log_dir"
    [ -n "$log_sym_dir" ] && do_cmd "mkdir -p $log_sym_dir"

    # start, and already running?  (do this check early to avoid unnecessary work!)
    if [ "$command" = "start" ]; then
	if daemon_is_running $name ceph-$type $id $pid_file; then
	    echo "Starting Ceph $name on $host...already running"
	    continue
	fi
    fi

    # binary?
    binary="$BINDIR/ceph-$type"
    if [ "$command" = "start" ]; then
	get_conf copy_executable_to "" "copy executable to"
	if [ -n "$copy_executable_to" ]; then
	    scp $binary "$host:$copy_executable_to"
	    binary="$copy_executable_to"
	fi
    fi

    cmd="$binary -i $id"

    # conf file
    if [ "$host" = "$hostname" ]; then
	cur_conf=$conf
    else
	if echo $pushed_to | grep -v -q " $host "; then
	    scp -q $conf $host:/tmp/ceph.conf.$$
	    pushed_to="$pushed_to $host "
	fi
	cur_conf="/tmp/ceph.conf.$$"
    fi
    cmd="$cmd -c $cur_conf"

    if echo $name | grep -q ^osd; then
	get_conf osd_data "" "osd data"
	get_conf btrfs_path "$osd_data" "btrfs path"  # mount point defaults so osd data
	get_conf btrfs_devs "" "btrfs devs"
	first_dev=`echo $btrfs_devs | cut '-d ' -f 1`
    fi

    # do lockfile, if RH
    get_conf lockfile "/var/lock/subsys/ceph" "lock file"
    lockdir=`dirname $lockfile`
    if [ ! -d "$lockdir" ]; then
	lockfile=""
    fi

    case "$command" in
	start)
            # Increase max_open_files, if the configuration calls for it.
            get_conf max_open_files "0" "max open files"
            if [ $max_open_files != "0" ]; then
                # Note: Don't try to do math with these numbers, because POSIX shells
                # can't do 64-bit math (natively). Just treat them as strings.
                cur=`ulimit -n`
                if [ "x$max_open_files" != "x$cur" ]; then
                    ulimit -n $max_open_files
                fi
            fi

            # build final command
	    wrap=""
	    runmode=""
	    runarg=""
	    
	    [ -z "$crun" ] && get_conf_bool crun "0" "restart on core dump"
	    [ "$crun" -eq 1 ] && wrap="$BINDIR/ceph-run"
	    
	    [ -z "$dovalgrind" ] && get_conf_bool valgrind "" "valgrind"
	    [ -n "$valgrind" ] && wrap="$wrap valgrind $valgrind"
	    
	    [ -n "$wrap" ] && runmode="-f &" && runarg="-f"

	    cmd="$wrap $cmd $runmode"
	    
	    if [ $dobtrfs -eq 1 ] && [ -n "$btrfs_devs" ]; then
		get_conf pre_mount "true" "pre mount command"
		get_conf btrfs_opt "noatime" "btrfs options"
		[ -n "$btrfs_opt" ] && btrfs_opt="-o $btrfs_opt"
		[ -n "$pre_mount" ] && do_cmd "$pre_mount"
		echo Mounting Btrfs on $host:$btrfs_path
		do_root_cmd "modprobe btrfs ; btrfsctl -a ; egrep -q '^[^ ]+ $btrfs_path' /proc/mounts || mount -t btrfs $btrfs_opt $first_dev $btrfs_path"
	    fi
	    echo Starting Ceph $name on $host...
	    get_conf pre_start_eval "" "pre start eval"
	    [ -n "$pre_start_eval" ] && $pre_start_eval
	    get_conf pre_start "" "pre start command"
	    get_conf post_start "" "post start command"
	    [ -n "$pre_start" ] && do_cmd "$pre_start"
	    do_cmd "$cmd" $runarg
	    [ -n "$post_start" ] && do_cmd "$post_start"
	    [ -n "$lockfile" ] && [ "$?" -eq 0 ] && touch $lockfile
	    ;;
	
	stop)
	    get_conf pre_stop "" "pre stop command"
	    get_conf post_stop "" "post stop command"
	    [ -n "$pre_stop" ] && do_cmd "$pre_stop"
	    stop_daemon $name ceph-$type $pid_file
	    [ -n "$post_stop" ] && do_cmd "$post_stop"
	    [ -n "$lockfile" ] && [ "$?" -eq 0 ] && rm -f $lockfile
	    if [ $dobtrfsumount -eq 1 ] && [ -n "$btrfs_devs" ]; then
		echo Unmounting Btrfs on $host:$btrfs_path
		do_root_cmd "umount $btrfs_path || true"
	    fi
	    ;;

	status)
	    if daemon_is_running $name ceph-$type $id $pid_file; then
                echo "$name: running..."
            elif [ -e "$pid_file" ]; then
                # daemon is dead, but pid file still exists
                echo "$name: dead."
                EXIT_STATUS=1
            else
                # daemon is dead, and pid file is gone
                echo "$name: not running."
                EXIT_STATUS=3
            fi
	    ;;

	ssh)
	    $ssh
	    ;;

	forcestop)
	    get_conf pre_forcestop "" "pre forcestop command"
	    get_conf post_forcestop "" "post forcestop command"
	    [ -n "$pre_forcestop" ] && do_cmd "$pre_forcestop"
	    stop_daemon $name ceph-$type $pid_file -9
	    [ -n "$post_forcestop" ] && do_cmd "$post_forcestop"
	    [ -n "$lockfile" ] && [ "$?" -eq 0 ] && rm -f $lockfile
	    ;;
	    
	killall)
	    echo "killall ceph-$type on $host"
	    do_cmd "pkill ^ceph-$type || true"
	    [ -n "$lockfile" ] && [ "$?" -eq 0 ] && rm -f $lockfile
	    ;;
	
	force-reload | reload)
	    signal_daemon $name ceph-$type $pid_file -1 "Reloading"
	    ;;

	restart)
	    $0 $options stop $name
	    $0 $options start $name
	    ;;

	cleanlogs)
	    echo removing logs
	    if [ -n "$log_sym_dir" ]; then
		do_cmd "for f in $log_sym_dir/$type.$id.*; do rm -f \`readlink \$f\` ; rm -f \$f ; done ; rm -f $log_dir/$type.$id.*"
	    fi
	    [ -n "$log_dir" ] && do_cmd "rm -f $log_dir/$type.$id.*"
	    ;;

	cleanalllogs)
	    echo removing all logs
	    [ -n "$log_sym_dir" ] && do_cmd "rm -f $log_sym_dir/* || true"
	    [ -n "$log_dir" ] && do_cmd "rm -f $log_dir/* || true"
	    ;;

	*)
	    usage_exit
	    ;;
    esac
done

exit $EXIT_STATUS
