#!/bin/sh -
#
# chkconfig:   345 99 01
# description: Starts and stops the OpenNMS network management \
#              poller and backend processes
# processname: opennms
# pidfile:     /data/ranger/opennms/target/opennms-1.8.0/logs/daemon/opennms.pid
#
### BEGIN INIT INFO
# Provides:          opennms
# Required-Start:    $local_fs $network
# Should-Start:      $time $named ypbind postgresql
# Required-Stop:     $local_fs $network
# Should-Stop:       $time $named ypbind
# Default-Start:     3 5
# Default-Stop:      0 1 2 6
# Short-Description: OpenNMS daemon for network monitoring
# Description:       OpenNMS daemon for network monitoring
### END INIT INFO
#
#  $Id$
#
#  For info on the "chkconfig:" section, see:
#     http://www.sensi.org/~alec/unix/redhat/sysvinit.html
#
#  For info on the "BEGIN INIT INFO" section, see:
#     http://www.suse.de/~mmj/Package-Conventions/
#
# Modifications:
#
# 2005 Oct 01: Removed `date` from a few echo commands and redirected
#              a few error messages to stderr. -- DJ Gregor
#

#### ------------> DO NOT CHANGE VARIABLES IN THIS FILE <------------- ####
#### Create $OPENNMS_HOME/etc/opennms.conf and put overrides in there. ####
#### ------------> DO NOT CHANGE VARIABLES IN THIS FILE <------------- ####

# Home directory for OpenNMS.
OPENNMS_HOME="/data/ranger/opennms/target/opennms-1.8.0"

# PID file for OpenNMS.
OPENNMS_PIDFILE="/data/ranger/opennms/target/opennms-1.8.0/logs/daemon/opennms.pid"

# Log directory for OpenNMS
LOG_DIRECTORY="/data/ranger/opennms/target/opennms-1.8.0/logs/daemon"

# Directory where init functions are likely stored (we also check a few other
# directories, just in case)
INITDIR="/data/ranger/opennms/target/opennms-1.8.0/bin"

# Where to redirect "start" output.
REDIRECT="$LOG_DIRECTORY/output.log"

# Number of times to do "opennms status" after starting OpenNMS to see
# if it comes up completely.  Set to "0" to disable.  Between each
# attempt we sleep for STATUS_WAIT seconds.  
START_TIMEOUT=10

# Number of seconds to wait between each "opennms status" check when
# START_TIMEOUT > 0.
STATUS_WAIT=5

# Value of the -Xmx<size>m option passed to Java.
JAVA_HEAP_SIZE=256

# Additional options that should be passed to Java when starting OpenNMS.
ADDITIONAL_MANAGER_OPTIONS=""

# Classpath additions.  These go on the front of our classpath.
ADDITIONAL_CLASSPATH=""

# Use incremental garbage collection.
USE_INCGC=""

# Use the Java Hotspot server VM.
HOTSPOT=""

# Enable verbose garbage collection debugging.
VERBOSE_GC=""

# Additional options to pass to runjava.
RUNJAVA_OPTIONS=""

# URL that this script uses to communicate with a running OpenNMS daemon.
INVOKE_URL="http://127.0.0.1:8181/invoke?objectname=OpenNMS:Name=Manager"

# The user that OpenNMS needs to run as.
RUNAS="root"

# Maximum file Descriptors + 1to be setted by ulimit -n
MAXIMUM_FILE_DESCRIPTORS=10240

# maximum size of stack segment (in kbytes) to be setted by ulimit -s
MAXIMUM_SIZE_STACK_SEGMENT=8192

#### ------------> DO NOT CHANGE VARIABLES IN THIS FILE <------------- ####
#### Create $OPENNMS_HOME/etc/opennms.conf and put overrides in there. ####
#### ------------> DO NOT CHANGE VARIABLES IN THIS FILE <------------- ####


# Load opennms.conf, if it exists, to override above configuration options.
if [ -f $OPENNMS_HOME/etc/opennms.conf ]; then
	. $OPENNMS_HOME/etc/opennms.conf
fi

show_help () {
	cat <<END

Usage: $0 [-n] [-t] [-p] [-o] [-c timeout] [-v] [-Q] <command> [<service>]
 
  command options: start|stop|restart|status|check|pause|resume|kill

  service options: all|<a service id from the etc/service-configuration.xml>
      defaults to all

  The following options are available:

      -n  "No execute" mode.  Don't call Java to do anything.
      -t  Test mode.  Enable JPDA on port 8001.
      -p  Enable TIJMP profiling
      -o  Enable OProfile profiling
      -c  Controller HTTP connection timeout in seconds.
      -v  Verbose mode.  When used with the "status" command, gives the
          results for all OpenNMS services.  When used with "start", enables
          some verbose debugging, such as details on garbage collection.
      -Q  Quick mode.  Don't wait for OpenNMS to startup.  Useful if you
          want to watch the logs while OpenNMS starts up without wanting to
          open another terminal window.

END
	return
}

getPid(){
	test -f $OPENNMS_PIDFILE && cat $OPENNMS_PIDFILE
}

getTempFile(){
	mktemp=`which mktemp 2>/dev/null`

	test -z "$TMPDIR" && TMPDIR=/tmp

	__TEMPFILE=""
	test -n "$mktemp" && {
		__TEMPFILE=`mktemp $TMPDIR/opennmsXXXXXX`
	}
	test -z "$mktemp" && {
		__TEMPFILE="$TMPDIR/xmllint.$RANDOM.$RANDOM.$RANDOM.$$"
	}

	rm "$__TEMPFILE"
	(umask 077 && touch "$__TEMPFILE")
	echo "$__TEMPFILE"
}
		
checkXmlFiles(){
	XMLLINT=`which xmllint 2>/dev/null || :`

	if [ -n "$XMLLINT" ] && [ -x "$XMLLINT" ]; then
		TEMPFILE=`getTempFile`
		find "$OPENNMS_HOME/etc" -type f -name \*.xml | while read "FILE"; do
			"$XMLLINT" "$FILE" >/dev/null 2>&1
			if [ $? != 0 ]; then
				echo "ERROR: XML validation failed: $FILE"
				echo "	   run '$XMLLINT $FILE' for details"
			fi
		done >"$TEMPFILE"
		cat "$TEMPFILE"
		FAILCOUNT=`cat "$TEMPFILE" | grep -c 'XML validation failed'`
		rm "$TEMPFILE"
		if [ $FAILCOUNT -gt 0 ]; then
			echo "Validation failed on $FAILCOUNT XML files.  Exiting."
			exit 1
		fi
	fi
		 
	return 0
}

checkRpmFiles(){
	CHECKDIRS="$OPENNMS_HOME/etc"

	for dir in /var/tomcat*/webapps /usr/lib/tomcat*/webapps $OPENNMS_HOME/jetty-webapps/*; do
		if [ -d "$dir/WEB-INF" ]; then
			CHECKDIRS="$CHECKDIRS $dir/WEB-INF"
		fi
	done

	for EXTENSION in rpmnew rpmsave dpkg-dist; do
		if [ `find $CHECKDIRS -name \*.$EXTENSION | wc -l` -gt 0 ]; then
			cat <<END

WARNING!  You have files that end in .$EXTENSION in your
OPENNMS_HOME ($OPENNMS_HOME) directory.

The format of the original files may have changed since
you modified them before installing a new version.
Please double-check that your configuration files are
up-to-date and delete any leftover .$EXTENSION files or
OpenNMS will not start.

END
			return 6	# From LSB: 6 - program is not configured
		fi
	done

	return 0
}

doStart(){
	checkXmlFiles || return $?
	checkRpmFiles || return $?

	doStatus
	status=$?
	case $status in
		0)
			echo "OpenNMS is already running." >&2
			return 0
			;;

		160)
			echo "OpenNMS is partially running." >&2
			echo "If you have just attempted starting OpenNMS, please try again in a few" >&2
			echo "moments, otherwise, at least one service probably had issues starting." >&2
			echo "Check your logs in $LOG_DIRECTORY for errors." >&2
			return 1
			;;

		3)
			true  # don't do anything, it isn't running, which is good 
				  # because we are going to start it. :-)
			;;

		*)
			echo "Unknown value return from doStatus: $status" >&2
			return 1
	esac


	$JAVA_CMD -Dopennms.home=$OPENNMS_HOME -jar $BOOTSTRAP check
	if [ $? -ne 0 ]; then
		echo "OpenNMS runs better if you start up the database first." >&2
		return 1
	fi

	##########################################################################
	# Run opennms with the "-t" option to enable the Java Platform Debugging
	# Architecture. This will open a server socket on port 8001 that can be
	# connected to by a remote java debugger. A good choice is JSwat which can 
	# be found at http://www.bluemarsh.com
	###########################################################################
	if [ $TEST -gt 0 ]; then
		echo "- enabling JPDA debugging on port 8001"
		JPDA="-Xdebug -Xnoagent -Djava.compiler=none -Xrunjdwp:transport=dt_socket,server=y,address=8001,suspend=n"
	fi

	# See: http://www.khelekore.org/jmp/tijmp/
	if [ $TPROFILE -gt 0 ]; then
		echo "- enabling TIJMP Profiling"
		JPDA="-Dtijmp.jar=/usr/share/java/tijmp-0.6.jar -agentlib:tijmp ${JPDA}"
	fi

	# See: http://oprofile.sourceforge.net/doc/setup-jit.html
	if [ $OPROFILE -gt 0 ]; then
		echo "- enabling OProfile support"
		JPDA="-agentpath:/usr/lib/oprofile/libjvmti_oprofile.so ${JPDA}"
	fi

	if [ "$SERVICE" = "" ]; then
		APP_VM_PARMS="$JPDA $MANAGER_OPTIONS"
		APP_PARMS_BEFORE="start"

	else
		APP_VM_PARMS="$CONTROLLER_OPTIONS"
		APP_PARMS_BEFORE="start $SERVICE"
	fi

	if [ -z "$NOEXECUTE" ]; then
		echo "------------------------------------------------------------------------------" >> "$REDIRECT"
		date >> "$REDIRECT"
		echo "begin ulimit settings:" >> "$REDIRECT"
		ulimit -a >> "$REDIRECT"
		echo "end ulimit settings" >> "$REDIRECT"
		CMD="$JAVA_CMD -Djava.endorsed.dirs=$OPENNMS_HOME/lib/endorsed $APP_VM_PARMS -jar $BOOTSTRAP $APP_PARMS_CONTROLLER $APP_PARMS_BEFORE "$@" $APP_PARMS_AFTER"
		echo "Executing command: $CMD" >> "$REDIRECT"
		$CMD >>"$REDIRECT" 2>&1 &
		OPENNMS_PID=$!
		echo $OPENNMS_PID > "$OPENNMS_PIDFILE"
		# disown # XXX specific to bash
	fi

	if [ $START_TIMEOUT -eq 0 ]; then
		# don't wait for OpenNMS to startup
		$opennms_echo "(not waiting for startup) \c"
		return 0
	fi

	# wait for OpenNMS to startup
	STATUS_ATTEMPTS=0
	while [ $STATUS_ATTEMPTS -lt $START_TIMEOUT ]; do
		if doStatus; then
			return 0
		fi
		if /bin/ps -p $OPENNMS_PID | grep "^ *$OPENNMS_PID " > /dev/null; then
			true		# Java process is still running... don't do anything
		else
			echo "Started OpenNMS, but it stopped running: for details see $REDIRECT" >&2
			return 1
		fi
		sleep $STATUS_WAIT
		STATUS_ATTEMPTS=`expr $STATUS_ATTEMPTS + 1`
	done

	echo "Started OpenNMS, but it has not finished starting up" >&2
	return 1
}

doPause(){
	if doStatus; then
		APP_VM_PARMS="$CONTROLLER_OPTIONS"
		APP_PARMS_BEFORE="-u $INVOKE_URL pause $SERVICE"
		if [ -z "$NOEXECUTE" ]; then
			$JAVA_CMD $APP_VM_PARMS -jar $BOOTSTRAP $APP_PARMS_CONTROLLER $APP_PARMS_BEFORE "$@" $APP_PARMS_AFTER
		fi
	else
		echo "OpenNMS is not running."
	fi
}

doResume(){
	if doStatus; then
		APP_VM_PARMS="$CONTROLLER_OPTIONS"
		APP_PARMS_BEFORE="-u $INVOKE_URL resume $SERVICE"
		if [ -z "$NOEXECUTE" ]; then
			$JAVA_CMD $APP_VM_PARMS -jar $BOOTSTRAP $APP_PARMS_CONTROLLER $APP_PARMS_BEFORE "$@" $APP_PARMS_AFTER
		fi
	else
		echo "OpenNMS is not running."
	fi
}

doCheck() {
	if doStatus; then
		# do nothing.. it's running
		exit 0
	fi

	echo "OpenNMS is not running... Restarting" >&2
	$OPENNMS_HOME/bin/opennms start

	exit 1
}

doStop() {
	doStatus
	if [ $? -eq 3 ]; then
		echo "Trying to stop OpenNMS but it's already stopped." >&2
		return 7   # LSB says: 7 - program is not running
	fi

	pid=`getPid`
	if [ -n "$pid" ]; then
		echo "=== OpenNMS Complimentary Thread Dump ===" >> $REDIRECT
		kill -3 "$pid" >> $REDIRECT 2>&1
	fi

	STOP_ATTEMPTS=0
	while [ $STOP_ATTEMPTS -lt 5 ]; do
		doStatus
		if [ $? -eq 3 ]; then
			echo "" > "$OPENNMS_PIDFILE"
			return 0
		fi

		if [ -z "$NOEXECUTE" ]; then
			APP_VM_PARMS="$CONTROLLER_OPTIONS"
			APP_PARMS_BEFORE="-u $INVOKE_URL stop $SERVICE"
			$JAVA_CMD $APP_VM_PARMS -jar $BOOTSTRAP $APP_PARMS_CONTROLLER $APP_PARMS_BEFORE "$@" $APP_PARMS_AFTER
		fi

		sleep 5

		STOP_ATTEMPTS=`expr $STOP_ATTEMPTS + 1`
	done

	return 1
}

doKill(){
	if doStatus; then
		APP_VM_PARMS="$CONTROLLER_OPTIONS"
		APP_PARMS_BEFORE="-u $INVOKE_URL exit"
		$JAVA_CMD $APP_VM_PARMS -jar $BOOTSTRAP $APP_PARMS_CONTROLLER $APP_PARMS_BEFORE "$@" $APP_PARMS_AFTER
	fi

	pid=`getPid`
	if [ x"$pid" != x"" ]; then
		if /bin/ps -p "$pid" | grep "^$RUNAS" > /dev/null; then
			kill -9 $pid > /dev/null 2>&1
		fi
	fi

	echo "" > "$OPENNMS_PIDFILE"
}

doStatus(){
	if [ $VERBOSE -gt 0 ]; then
		STATUS_VERBOSE="-v"
	else
		STATUS_VERBOSE=""
	fi

	if [ -z "$NOEXECUTE" ]; then
		APP_VM_PARMS="$CONTROLLER_OPTIONS"
		APP_PARMS_BEFORE="-u $INVOKE_URL $STATUS_VERBOSE status"
		$JAVA_CMD $APP_VM_PARMS -jar $BOOTSTRAP $APP_PARMS_CONTROLLER $APP_PARMS_BEFORE "$@" $APP_PARMS_AFTER
	fi
}

FUNCTIONS_LOADED=0

if [ -f /etc/SuSE-release ]; then
	. /etc/rc.status
	rc_reset
else
	# Source function library.
	for dir in "$INITDIR" /etc /etc/rc.d; do
		if [ -f "$dir/init.d/functions" -a $FUNCTIONS_LOADED -eq 0 ]; then
			. "$dir/init.d/functions"
			FUNCTIONS_LOADED=1
		fi
	done
fi

if [ `echo "\000\c" | wc -c` -eq 1 ]; then
	opennms_echo="echo"
elif [ `echo -e "\000\c" | wc -c` -eq 1 ]; then
	opennms_echo="echo -e"
elif [ `/bin/echo "\000\c" | wc -c` -eq 1 ]; then
	opennms_echo="/bin/echo"
elif [ `/bin/echo -e "\000\c" | wc -c` -eq 1 ]; then
	opennms_echo="/bin/echo -e"
else
	echo "ERROR: could not get 'echo' to emit just a null character" >&2
	exit 1
fi

ulimit -s $MAXIMUM_SIZE_STACK_SEGMENT > /dev/null 2>&1
ulimit -n $MAXIMUM_FILE_DESCRIPTORS > /dev/null 2>&1
if [ x"`uname`" = x"Darwin" ]; then
	for flag in "-d" "-f" "-l" "-m" "-n" "-s" "-u" "-v"; do
		ulimit $flag unlimited >/dev/null 2>&1
	done
fi

umask 002

# XXX is this needed?  maybe we should "cd $OPENNMS_HOME/logs" so hotspot
# XXX error files go somewhere reasonable
cd "$OPENNMS_HOME" || { echo "could not \"cd $OPENNMS_HOME\"" >&2; exit 1; }

# define needed for grep to find opennms easily
JAVA_CMD="$OPENNMS_HOME/bin/runjava -r $RUNJAVA_OPTIONS --"

#
#if [ x"$ADDITIONAL_CLASSPATH" != x"" ]; then
#	APP_CLASSPATH="$ADDITIONAL_CLASSPATH:$OPENNMS_HOME/etc"
#else
#	APP_CLASSPATH="$OPENNMS_HOME/etc"
#fi
#for jar in $OPENNMS_HOME/lib/*.jar; do
#	APP_CLASSPATH="$APP_CLASSPATH:$jar"
#done
#

BOOTSTRAP="$OPENNMS_HOME/lib/opennms_bootstrap.jar"

#MANAGER_OPTIONS="-DOPENNMSLAUNCH"
MANAGER_OPTIONS=""
MANAGER_OPTIONS="$MANAGER_OPTIONS -Dopennms.home=$OPENNMS_HOME"
MANAGER_OPTIONS="$MANAGER_OPTIONS -Dcom.sun.management.jmxremote.port=18980"
MANAGER_OPTIONS="$MANAGER_OPTIONS -Dcom.sun.management.jmxremote.ssl=false"
MANAGER_OPTIONS="$MANAGER_OPTIONS -Dcom.sun.management.jmxremote.authenticate=false"
#MANAGER_OPTIONS="$MANAGER_OPTIONS -Djcifs.properties=$OPENNMS_HOME/etc/jcifs.properties"
MANAGER_OPTIONS="$MANAGER_OPTIONS -Xmx${JAVA_HEAP_SIZE}m"

if [ -n "$USE_INCGC" -a "$USE_INCGC" = true ] ; then
	MANAGER_OPTIONS="$MANAGER_OPTIONS -Xincgc"
fi


if echo "$ADDITIONAL_MANAGER_OPTIONS" | grep MaxPermSize > /dev/null ; then
	true # do nothing
else
	ADDITIONAL_MANAGER_OPTIONS="$ADDITIONAL_MANAGER_OPTIONS -XX:MaxPermSize=128m"
fi

if [ x"$ADDITIONAL_MANAGER_OPTIONS" != x"" ]; then
	MANAGER_OPTIONS="$MANAGER_OPTIONS $ADDITIONAL_MANAGER_OPTIONS"
fi


if [ -n "$HOTSPOT" -a "$HOTSPOT" = true ] ; then
	JAVA_CMD="$JAVA_CMD -server"
fi

CONTROLLER_OPTIONS="-Dopennms.home=$OPENNMS_HOME"
#CONTROLLER_OPTIONS="$CONTROLLER_OPTIONS -Dlog4j.configuration=log4j.properties"

if [ x"$ADDITIONAL_CONTROLLER_OPTIONS" != x"" ]; then
	CONTROLLER_OPTIONS="$CONTROLLER_OPTIONS $ADDITIONAL_CONTROLLER_OPTIONS"
fi

TEST=0
TPROFILE=0
OPROFILE=0
NOEXECUTE=""
VERBOSE=0

NAME="opennms"

while getopts c:ntvpoQ c; do
	case $c in
		c)
			APP_PARMS_CONTROLLER="$APP_PARMS_CONTROLLER -t $OPTARG"
			;;
		n)
			NOEXECUTE="foo"
			;;
		Q)
				START_TIMEOUT=0
			;;
		t)
			TEST=1
			;;
		p)
			TPROFILE=1
			;;
		o)
			OPROFILE=1
			;;
		v)
			VERBOSE=1
			VERBOSE_GC=1
			;;

		"?")
			show_help
			exit 1
			;;
	esac
done
shift `expr $OPTIND - 1`

if [ $# -eq 0 ]; then
	show_help
	exit 1
else
	COMMAND="$1"; shift
fi

if [ $# -gt 0 ]; then
	SERVICE="$1"; shift
else
	SERVICE=""
fi

if [ $# -gt 0 ]; then
	show_help
	exit 1
fi

if [ x"$SERVICE" = x"all" ]; then
	SERVICE=""
fi

if [ x"$VERBOSE_GC" != x"" ]; then
	MANAGER_OPTIONS="$MANAGER_OPTIONS -verbose:gc"
fi

if [ ! -f $OPENNMS_HOME/etc/configured ]; then
	cat <<END >&2
$0: OpenNMS not configured.
$OPENNMS_HOME/etc/configured does not exist.

You need to run the installer to set up the database.  In most
cases, it is enough to run:

  $OPENNMS_HOME/bin/install -dis

For details, see the install guide at:

http://www.opennms.org/index.php/QuickStart#Initialize_OpenNMS_and_the_Database

END
	exit 6	# From LSB: 6 - program is not configured
fi

myuser="`id | sed -e 's/uid=[0-9][0-9]*(//' -e 's/).*//'`"
if [ x"$myuser" = x"$RUNAS" ]; then
	true # all is well
else
	echo "Error: you must run this script as $RUNAS, not '$myuser'" >&2
	exit 4	# According to LSB: 4 - user had insufficient privileges
fi

case "$COMMAND" in
	start|spawn)
		$opennms_echo "Starting OpenNMS: \c"

		if [ -f /etc/SuSE-release ]; then
			doStart

			# Remember status and be verbose
			rc_status -v
		elif [ $FUNCTIONS_LOADED -ne 0 ]; then
			doStart
			ret=$?
			if [ $ret -eq 0 ]; then
				echo_success
				touch /var/lock/subsys/${NAME}
			else
				echo_failure
			fi
			echo ""
		else
			doStart
			ret=$?
			if [ $ret -eq 0 ]; then
				echo "ok"
			else
				echo "failed"
			fi
		fi
		;;

	stop)
		$opennms_echo "Stopping OpenNMS: \c"
		if [ -f /etc/SuSE-release ]; then
			doStop

			# Remember status and be verbose
			rc_status -v

			doKill
		elif [ $FUNCTIONS_LOADED -ne 0 ]; then
			doStop
			ret=$?
			if [ $ret -eq 0 ]; then
				echo_success
			else
				echo_failure
			fi
			rm -f /var/lock/subsys/${NAME}
			echo ""

			doKill
		else
			doStop
			ret=$?
			if [ $ret -eq 0 ]; then
				echo "stopped"
			else
				echo "failed"
			fi

			doKill
		fi
		;;

	restart)
		## Stop the service and regardless of whether it was
		## running or not, start it again.
		$OPENNMS_HOME/bin/opennms stop
		$OPENNMS_HOME/bin/opennms start
		ret=$?

		if [ -f /etc/SuSE-release ]; then
			rc_failed $ret
		fi
		;;

	status)
		if [ -f /etc/SuSE-release ]; then
			$opennms_echo "Checking for OpenNMS: \c"
			if [ $VERBOSE -gt 0 ]; then
				echo ""
			fi
			doStatus

			# Remember status and be verbose
			rc_status -v
		else
			doStatus
			ret=$?
			case $ret in
				0)
					echo "${NAME} is running"
					;;

				3)
					echo "${NAME} is stopped"
					;;

				160)
					echo "${NAME} is partially running"
					;;

				*)
					echo "Unknown return code from doStatus: $ret" >&2
			esac
		fi
		;;

	configtest)
		$opennms_echo "Validating XML files: \c"
		checkXmlFiles
		echo "PASSED"
		;;

	pause)
		doPause
		;;

	check)
		doCheck
		;;

	resume)
		doResume
		;;

	kill)
		doKill
		;;

	*)
		echo ""
		echo "ERROR: unknown command \"$COMMAND\""
		show_help
		exit 1
		;;
esac


if [ -f /etc/SuSE-release ]; then
	rc_exit
else
	exit $ret
fi
