#!/bin/sh
# $Copyright$
# Copyright (C) Fujitsu Technology Solutions 2009, 2010, 2011, 2012, 2013, 2014, 2015
# All rights reserved
#
# $Copyright$
# Copyright (C) Fujitsu Siemens Computers GmbH 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
# All rights reserved
#############################################################################
#
# srvmagt:	ServerView Agent Linux SNMP subagent Daemons connect to the
#           snmpd daemon and provide information about the system
#
# chkconfig: 2345 59 02
# processname: scagt
# processname: sc2agt
# processname: thragt
# processname: busagt
# processname: hdagt
# processname: unixagt
# processname: etheragt
# processname: securagt
# processname: statusagt
# processname: invagt
# processname: vvagt
# processname: hpsimagt
# processname: vmeagt
# processname: svupdateagt
# processname: osagt
# description: Starts and stops the ServerView Agent Linux SNMP subagent Daemons
#
### BEGIN INIT INFO
# Provides: srvmagt
# Required-Start: $local_fs $network $syslog snmp eecd
# Required-Stop:
# Default-Start: 2 3 5
# Default-Stop: 0 1 6
# Description: Starts and stops the ServerView Agent Linux SNMP subagent Daemons
### END INIT INFO
#

#
# Exit status codes (see LSB 3 spec, ch. 20) are :
# 0     OK
# 1     generic or unspecified error
# 2     invalid or excess argument(s)
# 3     unimplemented feature (e.g. "reload")
# 4     user had insufficient privileges
# 5     program is not installed
# 6     program is not configured
# 7     program is not running
# 8+    reserved (see LSB Core Spec 3.1, ch. 20)

# Set up a decent path.

PATH="/sbin:/usr/sbin:/bin:/usr/bin"
export PATH

# Messages when exchanging the native snmpd with the ServerView instance

SVSnmpMsg="SNMP Daemon snmpd restarted. Changed from %s snmpd version %s to %s snmpd version %s"
SVSnmpd="ServerView"
NativeSnmpd="native"

# Use LSB function library for convenience.

[ -f /lib/lsb/init-functions ] && . /lib/lsb/init-functions

# Source ServerView function library

. /etc/srvmagt/functions

mode="$1"

# skip first param
shift

. /etc/srvmagt/config
# get the names of the agents (without their "agt" suffix) from the config file (Default: all)
AllAgent="sc sc2 bus hd unix ether bios secur status inv thr vv hpsim svupdate os vme"
agentlist=${AgentsToBeStarted:=$AllAgent}

[ $# -ge 1 ] && agentlist="$*"

Unknown="unknown"
SELinux="$Unknown"
[ -f /etc/selinux/config ] && {
	type -f getenforce >/dev/null 2>&1
	if [ $? -eq 0 ]; then
		SELinux=$(getenforce)
	else
		SELinux=$(grep '^[[:space:]]*SELINUX=' /etc/selinux/config) || SELinux="$Unknown"
		SELinux=${SELinux##*=}
		SELinux=${SELinux%% *}
	fi
}

[ "$mode" = stop ] &&  {
	# Stop each running subagent daemon. This SHOULD use LSB killproc.

	# Turn off periodical supervision of srvmagt daemons
	rm -f /etc/srvmagt/srvmagtCronOn
	logger -t $MYNAME "Periodical supervision turned off."

	# remove udev rules and lib file, if existing
	if [ -e /etc/udev/rules.d/srvmagt.rules ]; then
		/bin/rm -f /etc/udev/rules.d/srvmagt.rules
		/bin/rm -f /lib/udev/srvmagt_udev_hotplug.sh
		if [ -e /sbin/udevadm ]; then
			/sbin/udevadm control --reload-rules  >/dev/null 2>&1
		fi
	fi	

	running=0
	errors=0
	for agt in $AllAgent; do
		inList=0
		echo $agentlist | grep -qw $agt && inList=1
		pid=$(mypidof "/usr/sbin/${agt}agt") || {
			[ $inList -eq 1 ]  && 
					mylog_success_msg "Shutting down ServerView ${agt}agt (stopped)"
			continue
		}
		let running++

		[ $# -ge 1 -a $inList -eq 0 ] && continue
		# this is a hack for the time being
		if [ "${agt}" = "vme" ]; then
			killproc "vmeagt"
		else
			killproc "/usr/sbin/${agt}agt"
		fi
		success=$?

		# ia64 (SLES), LSB killproc exposes problems in the GA release
		# if it is invoked with full pathname of the process.

		[ "$(uname -m)" = "ia64" ] && pid=$(mypidof "/usr/sbin/${agt}agt") && {
			killproc "${agt}agt"
			success=$?
		}

		if [ $success -eq 0 ]; then
			mylog_success_msg "Shutting down ServerView ${agt}agt"
		else
			mylog_failure_msg "Shutting down ServerView ${agt}agt"
			let errors++
		fi
	done

	[ ${SELinux:1:7} = "isabled" -o "$SELinux" = "$Unknown" ] || {
		# Removing SELinux policy module vme.pp for RHEL6
		module=`semodule -l 2>/dev/null| grep "vme" | wc -l`
		if [ $module -ne 0 ]; then
			semodule -r vme
			restorecon -F /etc/srvmagt/VME/bin/vmeagt
		fi
		}

	[ -e /var/lock/subsys/srvmagt ] &&  rm -f /var/lock/subsys/srvmagt

	[ $running -eq 0 ] && exit 0
	[ $errors -eq 0 ] && exit 0
	exit 1 
}

# perform SetSvEnv only if not yet done
[ -z "$SV_NICKNAME" ] && SetSvEnv

# This path is needed to catch additional OEM libs for vmeagt
#if [ "$SV_ARCH" != "x86_64" -o "${SV_NICKNAME:0:4}" = "SLES" -o "${SV_NICKNAME:0:4}" = "RHEL" -a "$SV_NICKNAME" != "RHEL7" ]; then
if [ "$SV_ARCH" = "x86_64" -a "$SV_NICKNAME" != "RHEL5" -a "$SV_NICKNAME" != "OVM32" ]; then
	LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/etc/srvmagt/VME/lib64
else
	LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/etc/srvmagt/VME/lib
fi


# Source my configuration file value and use them as default values
# unless there is already a value in the environment

UserGroup=${UserGroup:-bin}
NoAccountCheck=${NoAccountCheck:-0}
ShutdownDelay=${ShutdownDelay:-0}
UseServerViewSnmpd=${UseServerViewSnmpd:-0}

exportConfVars

# makeXpairsfromMSB - transform each 16-bit MSB numbers into 2 hexdigit pairs in LSB
#
# $@        each argument is a 16-bit MSB numbers (for example 0123)
# stdout	Present the arguments as space-separated hexdigit pairs,
#           two adjacent pairs present the MSB number in LSB (for example 23 01)

function makeXpairsfromMSB() {
	local s=""

	[ "$#" -gt 0 ] || return
	while [ $# -gt 0 ] ; do
		s="$s ${1:2:2} ${1:0:2}"
		shift
	done
	printf "${s#* }"	# remove the leading space
}

# TurnOnCron - turn on periodical supervision of srvmagt daemons
# 	The root's crontab file contains the script srvmagtCron inserted during
# 	the daemons start that periodical executes the checking script.
#	The file "srvmagtCronOn" in /etc/srvmagt is created at the 'turn on'.
# 	If the file does not exist, then srvmagtCron will terminate doing nothing.

TmpRoot=/var/tmp/root.$$

function TurnOnCron(){

	crontab -l -u root >$TmpRoot 2>/dev/null 
	fgrep "srvmagtCron"  $TmpRoot>/dev/null
	if [ $? -eq 0 ]; then   
		grep "0,5,10,15,20,25,30,35,40,45,50,55.*srvmagtCron.*" $TmpRoot>/dev/null && {
		#  old crontab entry found, modify it
			sed -i '/srvmagtCron.$/s/0,5,10,15,20,25,30,35,40,45,50,55/0,15,30,45/' $TmpRoot
			/usr/bin/crontab -u root $TmpRoot >/dev/null 2>&1
		}
	else
		echo "# srvmagtCron: restarts daemons that died" >> $TmpRoot
		echo "0,15,30,45 * * * * /bin/sh -c \"[ -x /etc/srvmagt/srvmagtCron ] && /etc/srvmagt/srvmagtCron\"" >> $TmpRoot
		/usr/bin/crontab -u root $TmpRoot >/dev/null 2>&1
	fi
	rm -f $TmpRoot

	echo "" > /etc/srvmagt/srvmagtCronOn
	logger -t $MYNAME "Periodical supervision turned on."
}


# For SLES9 SP3, it is necessary to have SNMPCONFPATH="/etc" in the
# environment of each subagent so that the SNMP configuration file
# handler finds "/etc/snmpd.conf" to fetch to community.
# This is not necessary for SLES10, RHEL4 and RHEL5.

[ -f /etc/snmpd.conf ] && export SNMPCONFPATH="/etc"

# Be restictive with access right while creating files
umask 0066

if [ "$mode" = "trace" ]
then
        flags="-d -l"
        export TraceFileLimit=0
        export SV_LOG_DEBUG_LEVEL=255
elif [ "$mode" = "start" ]
then
        flags=-d
        [ "$TraceFileLimit" = "0" ] && {
            flags=
            export SV_LOG_DEBUG_LEVEL=0
        }
fi

case "$mode" in
trace|start)

	# Save existing ServerView Agent Linux logfiles

	( cd /var/log/srvmagt
	logFiles=$(find . -name log.\*agt\*)
	[ -f vme_status.xml ] &&
		logFiles="${logFiles} vme_status.xml"
	[ -z "$logFiles" ] || tar -czf log.AgentLogs.tgz $logFiles)

	# Do not run wait cycles and checks, if all requested subagents are already running

	count=0
	for agt in $agentlist; do
		pid=$(mypidof "/usr/sbin/${agt}agt") && {
			mylog_success_msg "Starting ServerView ${agt}agt $flags (already running $pid)"
			continue
		}
		let count++
	done
	[ $count -eq 0 ] && exit 0

	# Without snmpd, SNMP operation is impossible for ALL subagent

	pid=$(mypidof "/usr/sbin/snmpd") || {
		mylog_failure_msg "Starting ServerView agents: service snmpd is not running!"
		exit 1
	}

	# Without the service eecd HW monitoring for SOME subagents is impossible.
	# Wait until eecd sockets are ready. Then give eecd another grace period
	# to complete init. All this to avoid SNMP timeouts that might stress snmpd.

	pid=$(mypidof "/usr/sbin/eecd") || {
		mylog_failure_msg "Starting ServerView agents: service eecd is not running!"
		exit 1
	}

	count=${WaitForEecdSockets:=300}    # If <100 adjust \b's below
	echo -e "Waiting for eecd sockets ...\c"
	while [ $count -gt 0 ]; do
		[ -S /dev/eecda -a -S /dev/eecds ] && break
		sleep 1
		count=$(($count - 1))
		if [ $count -ge 100 ]; then
			echo -e "\b\b\b$count\c"
		elif [ $count -ge 10 ]; then
			echo -e "\b\b\b $count\c"
		else
			echo -e "\b\b\b  $count\c"
		fi
	done

	[ $count -eq 0 ] && {
		echo " giving up after $WaitForEecdSockets seconds!"
		mylog_failure_msg "Starting ServerView agents: eecd sockets do not exist!"
		exit 1
	}
	echo -e "\b\b\bdone ($count)"

#	[ "$#" -eq 0 ] && wait4eecd     # Only if ALL agents are started (during reboot)

	# Enable the configured UserGroup to issue eecdcp commands (besides root)

	chgrp $UserGroup /dev/eecd[as] && chmod g+w /dev/eecd[as] && {
	logger -t $MYNAME "Starting ServerView agents: eecd sockets enabled for group $UserGroup"
	}

	# Set the ShutdownDelay value into the config space

	eecdcp -c oc=e002 oe=1700 $(makeXpairsfromMSB $(printf "%04x" $ShutdownDelay)) >/dev/null

	[ $SV_NICKNAME = "RHEL6" -o $SV_NICKNAME = "RHEL7" ] && {
		[ ${SELinux:1:7} = "isabled" -o "$SELinux" = "$Unknown" ] || {
			# Adding SELinux policy module vme.pp for RHEL6
			module=`semodule -l 2>/dev/null | grep "vme" | wc -l`
			if [ $module -eq 0 ]; then
				restorecon -F /etc/srvmagt/VME/bin/vmeagt
				semodule -i   /etc/srvmagt/VME/bin/vme.pp
				restorecon -F /etc/srvmagt/VME/bin/vmeagt
				module=`semodule -l 2>/dev/null | grep "vme" | wc -l`
				if [ $module -eq 0 ]; then
					mylog_failure_msg "failed to add selinux module vme.pp"
				fi
			fi
		}
	}

	if [ "$SV_ARCH" = "x86_64" ]; then
		# Disable glibc internal allocator checks.
		# This is very ugly hack, but this allows daemons to start
		export MALLOC_CHECK_=0
	fi
	# Now start the requested not yet running subagents
	# Return OK and set subsystem ready if ALL subagents started.

	errors=0
	for agt in $agentlist; do
	pid=$(mypidof "/usr/sbin/${agt}agt") && continue

	[ "$agt" = "vv" ] && testVersionViewFile
	[ "$agt" = "secur" ] && writeAuthConf
	[ "$agt" = "sc2" ] && MibSetEnabled && MibSetAgentShutEnabled
	[ "$agt" = "vv" ] && export SV_USE_SNMPLIB=1
	[ "$agt" = "vme" ] && flags="-d -p /etc/srvmagt/VME" && export LD_LIBRARY_PATH

	# Start the daemon. This SHOULD use the LSB start_daemon routine.

	[ "$SV_DAEMON_COREFILE_LIMIT" = "" -o "$SV_DAEMON_COREFILE_LIMIT" = 0 ] ||
	ulimit -c $SV_DAEMON_COREFILE_LIMIT

	rm -f /var/log/log.${agt}agt /var/log/log.${agt}agt_[ab]
	rm -f /var/log/srvmagt/log.${agt}agt /var/log/srvmagt/log.${agt}agt_[ab]

	/usr/sbin/${agt}agt $flags >/var/log/srvmagt/log.${agt}agt 2>&1 </dev/null

	# Show formatted completion status

	if [ $? -eq 0 ]; then
	    mylog_success_msg "Starting ServerView ${agt}agt $flags"
	else
	    mylog_failure_msg "Starting ServerView ${agt}agt $flags"
	    let errors++
	fi
	done

	if [ $errors -eq 0 ]; then
		[ -d /var/lock/subsys ] &&  touch /var/lock/subsys/srvmagt
		# Turn on periodical supervision of srvmagt daemons
		TurnOnCron

		# ON ESX4, if the appliance svappliance exists, write name, working directory
		# and timeout of shutdown routine into config space 
		[ $SV_NICKNAME = "ESX4" ] &&
		vmware-cmd -l|fgrep -i svappliance >/dev/null && {
			eecdcp -c oc=e002 oe=1710 \"ChkStatusOnShutdown\" >/dev/null
			eecdcp -c oc=e002 oe=1711 \"/etc/srvmagt\" >/dev/null
			eecdcp -c oc=e002 oe=1712 B4 >/dev/null
		}

		# create udev rules and lib file, if necessary
		if [ -e /sbin/udevd ]; then
			# install udev rules and lib file only on PRIMEQUEST system
			/etc/srvmagt/dmidecodeSV | fgrep PRIMEQUEST >/dev/null 2>&1 
			if [ $? -eq 0 ]; then
				/bin/cp -p -f /etc/srvmagt/srvmagt_udev_hotplug.sh /lib/udev/srvmagt_udev_hotplug.sh
				/bin/cp -p -f /etc/srvmagt/srvmagt.rules	   /etc/udev/rules.d/srvmagt.rules
				if [ -e /sbin/udevadm ]; then
					/sbin/udevadm control --reload-rules  >/dev/null 2>&1
				fi
			fi
		fi

		exit 0
	else
		[ -e /var/lock/subsys/srvmagt ] &&  rm -f /var/lock/subsys/srvmagt
		exit 1
	fi ;;

archive)
	# Run snmpwalk on all oids in StartOIds.ini
	# Output stored under directory : /var/log/srvmagt/ARCHIVE
	/etc/srvmagt/archive
	exit $? ;;

force-reload)
	# Reload configuration, if the service supports this,
	# otherwise start the service if it is not running

	$0 start
	exit $? ;;

restart)

	$0 stop  $*
	$0 start $*
	exit $? ;;

status)
	# Status codes in this case are:
	# 0     all agents are running [OK]
	# 1     service is dead /var/run/<pid file> exists
	# 2     service is dead and /var/lock/<lock file> ecists
	# 3     one or more agents are not running
	# 4     service status is unknown
	# 5+    reserved (see LSB Core Spec 3.1, ch. 20)

	notRunning=0
	for agt in $AllAgent; do
	inList=0
	echo $agentlist | grep -qw $agt && inList=1
	[ $# -ge 1 -a $inList -eq 0 ] && continue
		pid=$(mypidof "/usr/sbin/${agt}agt")
		if [ $? -eq 0 ]; then
			if [ $inList -eq 1 ]; then
				statMsg=$(printf "Checking for ServerView %s: pid %s, %s" ${agt}agt $pid $(mapAgtState $agt))
			else
				statMsg=$(printf "ServerView %s not in list but %s, pid %s" ${agt}agt $(mapAgtState $agt) $pid)
			fi
		else
			[ $inList -eq 0 ]  &&  continue
			let notRunning++
			statMsg=$(printf "Checking for ServerView %s: stopped" ${agt}agt)
		fi
		echo $statMsg
		logger -t $MYNAME $statMsg
	done

	[ $notRunning -eq 0 ] && exit 0
	exit 3 ;;

try-restart|reload|*)
	echo "Usage: $0 {start|trace|stop|restart|archive|force-reload|status} [<agent> ...]"
	exit 1 ;;
esac

exit 1
# EOF
