#!/bin/bash
#
# ***********************************************************
# copyright 2002 Compaq Information Technologies Group, L.P.
# ***********************************************************
# 
# The following section is used for insserv (8) which is an
# installation / boot utility available under SuSE and United
# Linux based distributions.  This section has no affect on
# Linux distributions which do not implement the insserv (8)
# installation / boot utility.
#
### BEGIN INIT INFO
# Provides: cpqasm
# Required-Start:	$syslog
# Required-Stop:	$syslog
# Default-Start:	3 5
# Default-Stop:	0 1 2 6
# Description:	Starts / Stops ProLiant Advanced Server Management Driver
### END INIT INFO
#
# hp ProLiant Advanced Server Management Driver
#
# ********************************************************
# ** global variables                                   **
# ********************************************************
CPQASM_LOGFILE=/opt/compaq/cpqhealth/cpqhealth_boot.log 
CPQASM_LOGLEVEL=4

# ********************************************************
# ** log_msg                                            **
# ********************************************************
# ** This routine will log a message to the screen and  **
# ** to our error log.                                  **
# ********************************************************
function log_msg() {
	LOGLEVEL=$1
	shift
	echo "$*" >> $CPQASM_LOGFILE 
	[ $LOGLEVEL -le $CPQASM_LOGLEVEL ] && echo "$*"
}

function err_msg() {
	log_msg 1 $*
}


# ********************************************************
# ** kernel_src_avail                                   **
# ********************************************************
# ** This routine will check to see if various kernel   **
# ** header files are available.  These are required to **
# ** rebuild this module.                               **
# ********************************************************
function kernel_src_avail() {
	THIS_KERNEL=`uname -r`
	log_msg 4 " "
	log_msg 4 "Looking for sources to build ${THIS_KERNEL}"
	ls -ld /lib/modules/${THIS_KERNEL}/build > /dev/null
	[ $? -ne 0 ] &&  {
		err_msg " "
		err_msg "FAILURE:  Not able to rebuild on this kernel!"
		err_msg "/lib/modules/${THIS_KERNEL}/build does not exist"
		err_msg "This is an indication that the sources for this kernel (${THIS_KERNEL}) are not loaded."
		err_msg "Please load the appropriate sources to rebuild module".
		exit 1
	}

#
# We need to make sure that "version.h" exists.  This is a problem on SLES7
#
	ls /lib/modules/${THIS_KERNEL}/build/include/linux/version.h > /dev/null
	[ $? -ne 0 ] && {
		ls /boot/vmlinuz.version.h > /dev/null
	        [ $? -ne 0 ] && {
		        ls /boot/vmlinuz-${THIS_KERNEL}.version.h > /dev/null
		        [ $? -eq 0 ] && {
			cp /boot/vmlinuz-${THIS_KERNEL}.version.h /lib/modules/${THIS_KERNEL}/build/include/linux/version.h
			} || {
			        err_msg " "
			        err_msg "/lib/modules/${THIS_KERNEL}/build/include/linux/version.h does not exist"
			        err_msg "Please load the appropriate sources to rebuild module".
			        exit 1
		        }
		} || {
			cp /boot/vmlinuz.version.h /lib/modules/${THIS_KERNEL}/build/include/linux/version.h
		}
		err_msg " "
		err_msg "Missing  /lib/modules/${THIS_KERNEL}/build/include/linux/version.h"
		err_msg "Making a backup of /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h to"
		err_msg "                   /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h.ORIGINAL"
		mv /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h.ORIGINAL >> $CPQASM_LOGFILE 2>&1
		err_msg " "
	}

#
# We need to make sure that "autoconf.h" exists.  This is a problem on SLES7
#
	ls /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h > /dev/null
   	[ $? -ne 0 ] && {
		ls /boot/vmlinuz.autoconf.h > /dev/null
		[ $? -ne 0 ] && {
			ls /boot/vmlinuz-${THIS_KERNEL}.autoconf.h > /dev/null
			[ $? -eq 0 ] && {
				cp /boot/vmlinuz-${THIS_KERNEL}.autoconf.h /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h
			} || {
				err_msg " "
				err_msg "FAILURE:  Not able to rebuild on this kernel!"
				err_msg "/lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h does not exist"
				err_msg "Please load the appropriate sources to rebuild module".
				exit 1
	     		}
		} || {
	     	cp /boot/vmlinuz.autoconf.h /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h
		}

	}

#
# We now need to make sure that the version.h file matches the kernel
# we are trying to build.
#
	fgrep ${THIS_KERNEL} /lib/modules/${THIS_KERNEL}/build/include/linux/version.h > /dev/null
	[ $? -ne 0 ] && {
		log_msg 2 " "
		log_msg 2 "/lib/modules/${THIS_KERNEL}/build/include/linux/version.h does not match"
		log_msg 2 "the version of this kernel (${THIS_KERNEL})."
		log_msg 2 " "
		log_msg 2 "This is an indication that a patch has been loaded but not the sources"
		log_msg 2 "to match the running kernel.  This driver requires the sources to all"
		log_msg 2 "kernel patches to be loaded in order to relink to the kernel symbols"

# 
#	We will now try to see if this is a SLES 7 system that might have
#  been patched.
#
		ls /boot/vmlinuz.version.h > /dev/null
		[ $? -eq 0 ] && {
			fgrep ${THIS_KERNEL} /boot/vmlinuz.version.h > /dev/null

			[ $? -eq 0 ] && {
				log_msg 2 " "
				log_msg 2 "This appears to be a patched kernel and the correct files are located in the \"/boot\" directory"
				log_msg 2 " "
				log_msg 2 "Making a backup of /lib/modules/${THIS_KERNEL}/build/include/linux/version.h to"
				log_msg 2 "                   /lib/modules/${THIS_KERNEL}/build/include/linux/version.h.ORIGINAL"
				mv /lib/modules/${THIS_KERNEL}/build/include/linux/version.h /lib/modules/${THIS_KERNEL}/build/include/linux/version.h.ORIGINAL
				log_msg 2 " "
				log_msg 2 "Making a backup of /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h to"
				log_msg 2 "                   /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h.ORIGINAL"
				mv /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h.ORIGINAL
				log_msg 2 " "
				log_msg 2 "Copying /boot/vmlinuz.version.h to /lib/modules/${THIS_KERNEL}/build/include/linux/version.h"
				cp /boot/vmlinuz.version.h /lib/modules/${THIS_KERNEL}/build/include/linux/version.h

				log_msg 2 "Copying /boot/vmlinuz.autoconf.h to /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h"
				cp /boot/vmlinuz.autoconf.h /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h

			} || {
				err_log " "
				err_log "FAILURE:  Not able to rebuild on this kernel!"
				err_log "There does not appear to be kernel sources which match the current booting Linux kernel"
				err_log "There must be a directory named \"/lib/modules/${THIS_KERNEL}\" and there must be a"
				err_log "valid directory linked to \"/lib/modules/${THIS_KERNEL}/build\"."
				err_log "Please load the appropriate Linux sources to rebuild module".
				exit 1
			}

		} || {
		ls /boot/vmlinuz-${THIS_KERNEL}.version.h > /dev/null
		[ $? -eq 0 ] && {
			fgrep ${THIS_KERNEL} /boot/vmlinuz-${THIS_KERNEL}.version.h > /dev/null

			[ $? -eq 0 ] && {
				log_msg 2 " "
				log_msg 2 "This appears to be a patched kernel and the correct files are located in the \"/boot\" directory"
				log_msg 2 " "
				log_msg 2 "Making a backup of /lib/modules/${THIS_KERNEL}/build/include/linux/version.h to"
				log_msg 2 "                   /lib/modules/${THIS_KERNEL}/build/include/linux/version.h.ORIGINAL"
				mv /lib/modules/${THIS_KERNEL}/build/include/linux/version.h /lib/modules/${THIS_KERNEL}/build/include/linux/version.h.ORIGINAL
				log_msg 2 " "
				log_msg 2 "Making a backup of /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h to"
				log_msg 2 "                   /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h.ORIGINAL"
				mv /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h.ORIGINAL
				log_msg 2 " "
				log_msg 2 "Copying /boot/vmlinuz-${THIS_KERNEL}.version.h to /lib/modules/${THIS_KERNEL}/build/include/linux/version.h"
				cp /boot/vmlinuz-${THIS_KERNEL}.version.h /lib/modules/${THIS_KERNEL}/build/include/linux/version.h

				log_msg 2 "Copying /boot/vmlinuz-${THIS_KERNEL}.autoconf.h to /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h"
				cp /boot/vmlinuz-${THIS_KERNEL}.autoconf.h /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h

			} || {
				err_log " "
				err_log "FAILURE:  Not able to rebuild on this kernel!"
				err_log "There does not appear to be kernel sources which match the current booting Linux kernel"
				err_log "There must be a directory named \"/lib/modules/${THIS_KERNEL}\" and there must be a"
				err_log "valid directory linked to \"/lib/modules/${THIS_KERNEL}/build\"."
				err_log "Please load the appropriate Linux sources to rebuild module".
				exit 1
			}
	     	} || {
			exit 1
	     	}

		}

	}

	log_msg 4 " "
	log_msg 4 "Sources for Linux kernel ${THIS_KERNEL} have been located"
	log_msg 4 " "
}

#
# For United Linux SP3 we need to do the following to configure the kernel
# source so we can rebuild and load if necessary:
# cd /usr/src/linux; make distclean; make cloneconfig; make dep;
#
ul_sp3fix () {
	if [ -f /etc/UnitedLinux-release ]
	then
		if [ ! -d /usr/src/linux/include/linux/modules ]
		then
			#
			#As recommended by SuSE. Doing these steps will
			#create the linux/modules directory and populate
			#the *.ver files with the correct checksums for 
			#the symbols depending on the kernel that is running.
			#
			CWD=`pwd`
			echo -e "\n"
			echo "********** Please note *************"
			echo "Your kernel source needs to be configured. This will be done"
			echo "automatically by executing the following steps: cd /usr/src/linux;"
			echo "make distclean; make cloneconfig; make dep"
			echo "This may take about 3 minutes or more to complete"
			sleep 10
   			cd /usr/src/linux
   			make distclean
   			make cloneconfig
   			make dep

			cd ${CWD}
		fi
	fi
}

start_driver () {
	DRIVER_NAME=$1
	DRIVER_MKTG_NAME=$2

	CPQDRIVER=`/sbin/lsmod |fgrep $DRIVER_NAME`
	if [ ${#CPQDRIVER} -eq 0 ]
	then
		if [ ! -d /opt/compaq/cpqhealth/$DRIVER_NAME/${THIS_KERNEL} ]
		then
			REBUILD_MODULE=TRUE
			log_msg 3 " "
			log_msg 3 "The $DRIVER_MKTG_NAME is not available"
			log_msg 3 "for this Linux kernel:  ${THIS_KERNEL}"

		else
			/sbin/insmod -p /opt/compaq/cpqhealth/$DRIVER_NAME/${THIS_KERNEL}/$DRIVER_NAME.o \
				>>$CPQASM_LOGFILE 2>&1
			if [ $? -eq 0 ]
			then
				MODINFO="`modinfo -d /opt/compaq/cpqhealth/$DRIVER_NAME/${THIS_KERNEL}/$DRIVER_NAME.o`"
				if [ "$MODINFO" != "<none>" ]
				then
					echo "$MODINFO" | tr -d '"' | md5sum --check --status 2> /dev/null > /dev/null
					if [ $? -ne 0 ]
					then
						log_msg 3 " "
						log_msg 3 "Linux Kernel Checksum Conflict - Attempting rebuild to resolve."
						REBUILD_MODULE=TRUE
					fi
				fi
			else	
				log_msg 3 " "
				log_msg 3 "Linux Kernel Symbol Conflict - Attempting rebuild to resolve."
				REBUILD_MODULE=TRUE
			fi

		fi

		if [ "${REBUILD_MODULE}" == "TRUE" ]
		then
			kernel_src_avail
			cd /opt/compaq/cpqhealth/$DRIVER_NAME
			/sbin/rmmod $DRIVER_NAME> /dev/null 2>&1
			make -s -f $DRIVER_NAME.mk rebuild >> $CPQASM_LOGFILE

			if [ $? -ne 0 ]
			then
				err_msg " "
				err_msg "WARNING!  Not able to rebuild the $DRIVER_MKTG_NAME on this kernel!"
				err_msg "          See  $CPQASM_LOGFILE "
				err_msg "          for error details."
				err_msg " "
				err_msg "          The ProLiant ASM driver has failed to load!"
				exit 1
			fi

			sh retry_$DRIVER_NAME.sh

			if [ $? -ne 0 ]
			then
				err_msg " "
				err_msg "WARNING!  The cpqhealth RPM has failed to install!"
				exit 1
			fi

		else
			log_msg 5 "Loading the $DRIVER_MKTG_NAME . . ."
			/sbin/insmod /opt/compaq/cpqhealth/$DRIVER_NAME/${THIS_KERNEL}/$DRIVER_NAME.o \
				>>$CPQASM_LOGFILE 2>&1
			sleep 3
		fi

	else
		log_msg 4 "The $DRIVER_MKTG_NAME is already loaded."
	fi
}

stop_driver () {
	DRIVER_NAME=$1
	DRIVER_MKTG_NAME=$2
	CPQDRIVER=`/sbin/lsmod | fgrep $DRIVER_NAME`
	RETVAL=0
	if [ ${#CPQDRIVER} -ne 0 ]; then
		log_msg 5 "Unloading the $DRIVER_MKTG_NAME . . ."
		/sbin/rmmod $DRIVER_NAME 2>&1 >> $CPQASM_LOGFILE
		RETVAL=$?
		sleep 1
	else
		log_msg 4 "The $DRIVER_MKTG_NAME is already stopped."
	fi

# There is a timing problem between installation and removal
# of the hpasm package.  The issue appears to be with the 
# agents as there is a delayed "open" somewhere.
	if [ $RETVAL -ne 0 ]; then
		log_msg 5 "Waiting for $DRIVER_MKTG_NAME to complete initialization"
		sleep 5
		log_msg 5 "Unloading the $DRIVER_MKTG_NAME . . ."
		/sbin/rmmod $DRIVER_NAME 2>&1 >> $CPQASM_LOGFILE
		RETVAL=$?
	fi

	return $RETVAL 
}

start_daemon () {
	DAEMON_NAME=$1
	DAEMON_MKTG_NAME=$2
	DAEMON_LOCATION=$3

	if [ -z "`pidof $DAEMON_NAME`" ]; then
		log_msg 5 "Starting the $DAEMON_MKTG_NAME . . ."
		/opt/compaq/cpqhealth/$DAEMON_LOCATION/$DAEMON_NAME &
		sleep 1
	else
		log_msg 4 "The $DAEMON_MKTG_NAME is already running."
	fi
}

stop_daemon () {
	DAEMON_NAME=$1
	DAEMON_MKTG_NAME=$2
	DAEMON_LOCATION=$3

	if [ -z "`pidof $DAEMON_NAME`" ]; then
		log_msg 4 "The $DAEMON_MKTG_NAME is already stopped."
	else
		log_msg 5 "Stopping the $DAEMON_MKTG_NAME . . ."
		/opt/compaq/cpqhealth/$DAEMON_LOCATION/$DAEMON_NAME -t 
		sleep 5
		if [ ! -z "`pidof $DAEMON_NAME`" ]; then
			sleep 5
		fi
	fi
}

case "$2" in
	verbose)
		CPQASM_LOGLEVEL=5
		;;
	chatty)
		CPQASM_LOGLEVEL=4
		;;
	normal)
		CPQASM_LOGLEVEL=3
		;;
	terse)
		CPQASM_LOGLEVEL=2
		;;
	quiet)
		CPQASM_LOGLEVEL=1
		;;
	silent)
		CPQASM_LOGLEVEL=0
		;;
esac

MYDATE=`date`
THIS_KERNEL=`uname -r`
REBUILD_MODULE=FALSE

case "$1" in
	'start')
#
# First make sure we are not already running
#
		cp $CPQASM_LOGFILE $CPQASM_LOGFILE.old >/dev/null 2>&1
		> $CPQASM_LOGFILE

		log_msg 5 "Enabling Advanced Server Management at ${MYDATE} on Linux kernel:  ${THIS_KERNEL}" 
		
#
# The /lib/modules ../version.h is a dummy file in United Linux 1.0, SP3.
# So we need to perform some special steps.
#
		ul_sp3fix

		start_driver "cpqevt" "hp ProLiant Event Logging Driver"
		[ $? -ne 0 ] &&  exit 1

		start_driver "cpqasm" "hp ProLiant Advanced Server Management Driver"
		[ $? -ne 0 ] &&  exit 1

                if [ ! -z "`lspci -d 0xe11:0xb200`" ]; then
		   start_driver "cmhp" "hp ProLiant Memory Hot Plug Driver"
		   [ $? -ne 0 ] &&  exit 1
                fi


		sh /opt/compaq/cpqhealth/cpqasm/cpqasm_mknod.sh

		start_daemon "cevtd" "hp ProLiant Event Logging Daemon" "cpqevt"
		start_daemon "casmd" "hp ProLiant Advanced Server Management Daemon" "cpqasm"

		#if we made it this far, we are good to go
		log_msg 3 "Advanced Server Management drivers have been enabled."

		touch  /var/lock/subsys/cpqasm
		exit 0
		;;

	'stop')
		log_msg 5 "Disabling Advanced Server Management at ${MYDATE} on Linux kernel:  ${THIS_KERNEL}" 

		stop_daemon "casmd" "hp ProLiant Advanced Server Management Daemon" "cpqasm"
		stop_daemon "cevtd" "hp ProLiant Event Logging Daemon" "cpqevt"

#
# We need to kill the RIB /iLo Drivers if they are running
#
		RIB_DRIVER=`/sbin/lsmod | fgrep cpqrid`
		if [ ${#RIB_DRIVER} -ne 0 ]; then
			log_msg 2 "hpasm: Detect ProLiant Insight Management Driver installed.  Disabling driver"
			[ -x /etc/init.d/hprsm ] && /etc/init.d/hprsm stop
		fi

		RIB_DRIVER=`/sbin/lsmod | fgrep cpqci`
		if [ ${#RIB_DRIVER} -ne 0 ]; then
			log_msg 2 "hpasm: Detect ProLiant Integrated Lights Out Management Driver installed.  Disabling driver"
			[ -x /etc/init.d/hprsm ] && /etc/init.d/hprsm stop
		fi

                if [ ! -z "`lspci -d 0xe11:0xb200`" ]; then
		   stop_driver "cmhp" "hp ProLiant Memory Hot Plug Driver"
		   if [ $? -ne 0 ]; then
			start_daemon "cevtd" "hp ProLiant Event Logging Daemon" "cpqevt"
			start_daemon "casmd" "hp ProLiant Advanced Server Management Daemon" "cpqasm"
			log_msg 2 "WARNING!  Not able to stop the cmhp device driver!"
			log_msg 2 "          The CIM agents may not be terminated."
			exit 1
		   fi
                fi

		stop_driver "cpqasm" "hp ProLiant Advanced Server Management Driver"
		if [ $? -ne 0 ]; then
			start_daemon "cevtd" "hp ProLiant Event Logging Daemon" "cpqevt"
			start_daemon "casmd" "hp ProLiant Advanced Server Management Daemon" "cpqasm"
			log_msg 2 "WARNING!  Not able to stop the cpqasm device driver!"
			log_msg 2 "          The CIM agents may not be terminated."
			exit 1
		fi
		stop_driver "cpqevt" "hp ProLiant Event Logging Driver"
		if [ $? -ne 0 ]; then
			start_driver "cpqasm" "hp ProLiant Advanced Server Management Driver"
			start_daemon "cevtd" "hp ProLiant Event Logging Daemon" "cpqevt"
			start_daemon "casmd" "hp ProLiant Advanced Server Management Daemon" "cpqasm"
			log_msg 2 "WARNING!  Not able to stop the cpqevt device driver!"
			log_msg 2 "          The CIM agents may not be terminated."
			exit 1
		fi


		log_msg 3 "Advanced Server Management has been disabled successfully."

		rm -f  /var/lock/subsys/cpqasm
		exit 0
        	;;

	'status')
		echo -e "\n"
		echo "Here are the modules / daemons executing:"
		MYPID=`ps -x | grep casmd | awk '{ print $5 }'`
		declare -i PIDCNT
		PIDCNT=0
		for i in $MYPID
		do
			if [ "$i" != "grep" ]
			then
				PIDCNT=$PIDCNT+1
			fi
		done

		echo -e "\n"
		/sbin/lsmod | grep Module
		/sbin/lsmod | grep cpqasm
		echo -e "\n"

		ps -x | grep casmd
		ps -x | grep cevtd
		echo -e "\n"

		case $PIDCNT in
			0 )
				echo "STATUS:  The ProLiant Advanced Server Management is disabled!"
				echo -e "\n"
				exit 1
				;;

			1 )
				echo "WARNING:  The ProLiant Advanced Server Management is in a degraded state!"
				echo -e "\n"
				exit 1
				;;

			2 )
				echo "STATUS:  The ProLiant Advanced Server Management is enabled!"
				echo -e "\n"
				;;

			* )
				echo "WARNING:  The ProLiant Advanced Server Management is in an unknown state!"
				echo -e "\n"
				exit 1
				;;
		esac

		exit 0
        	;;

	*)
		echo "Usage: $0 [ start | stop | status ]"
		exit 1
		;;
esac

exit 0
