#!/bin/sh
# $Copyright$
# Copyright (C) Fujitsu Technology Solutions 2015
# All rights reserved
#
# $Copyright$
# Copyright (C) Fujitsu Technology Solutions 2009-2015
# All rights reserved
#
# $Copyright$
# Copyright (C) Fujitsu Siemens Computers GmbH 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
# All rights reserved
#############################################################################
#
# eecd_mods:	ServerView Agent Linux eecd modules.
#               The modules will be first compiled if necessary.
#
# chkconfig: 2345 20 20
# processname: eecd_mods_src
# description: Inserts and removes the eecd modules
#
### BEGIN INIT INFO
# Provides: eecd_mods
# Required-Start: $local_fs
# Required-Stop:
# Default-Start: 2 3 5
# Default-Stop: 0 1 6
# Description: Inserts and removes the eecd modules
### 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

# Use LSB function library for convenience.

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

# Source ServerView configuration file and function library

. /etc/srvmagt/config
. /etc/srvmagt/functions
exportConfVars  

export INTF_NUM=0 # number for IPMI device node

# Do nothing in a VM or ESX 4 where the native IPMI module is already loaded.
machType=$(isVM) && exit 0
vmware -v 2>/dev/null | fgrep "ESX 4" >/dev/null && exit 0  # SV_NICKNAME not yet available


module_loaded()
# module_loaded - check the status of ipmi module 
# $1    ipmi module 
# Returns 0 or 1 if module IS or IS NOT loaded
{
	if /sbin/lsmod | grep $1 >/dev/null 2>&1 ; then
		return 0
	elif [ -d "/sys/module/$1" ]; then
		return 0
	elif [ "$1" == "ipmi_msghandler" ]; then
		if [ -d "/sys/module/ipmi_si" ]; then
			return 0
		fi
	fi
	return 1
}

[ "$1" = stop ] &&  {
	# Unload all ServerView modules, but DO NOT unload native IPMI unless on XenServer

    if isXenServer; then
		/sbin/modprobe -q -r ipmi_si > /dev/null 2>&1
		/sbin/modprobe -q -r ipmi_devintf > /dev/null 2>&1
		/sbin/modprobe -q -r ipmi_msghandler > /dev/null 2>&1
		/sbin/modprobe -q -r ipmi__watchdog > /dev/null 2>&1
		
		if [ ! -x /sbin/udevd ]; then
			rm -f /dev/ipmi${INTF_NUM} 2> /dev/null
		fi

	fi
	
	error=0
	module=smbus
	lsmod | grep "$module " > /dev/null 2>&1
	if [ $? -ne 0 ]; then
		mylog_success_msg "Stopping ServerView modules: $module not loaded"
	else
		# Since the module is loaded, failure to unload indicates it is in use.
		rmmod $module 2>/dev/null >/dev/null
		if [ $? -eq 0 ]; then
			mylog_success_msg "Stopping ServerView modules: $module"
			rm -f /dev/pci/$module
		else
			mylog_failure_msg "Stopping ServerView modules: $module still in use"
			error=1
		fi
	fi

	[ $error -eq 0 ] && [ -d /dev/pci ] && rmdir /dev/pci

	# If necessary, reestablish EDAC kernel modules
	[ -d "/etc/modprobe.d/" ] && {
		edac_enable
		rc=$?
		case $rc in
		0)	mylog_success_msg "Stopping ServerView modules: Reenable EDAC";;
		1)	mylog_failure_msg "Stopping ServerView modules: Reenable EDAC";;
		esac
	}

	exit $error
}

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

# SV_MODULES is the complete set of SV kernel modules to build/load,
# a subset from {ipmi, smbus}.
# The SV IPMI module is in the set, if the native IPMI module is not configured.

SV_MODULES=""
pq=$(isPRIMEQUEST) || SV_MODULES="smbus"

THIS_RELEASE=$(uname -r)	# e.g. "2.6.5-7.97-default"
MOD_SUFFIX="o"
[[ ${THIS_RELEASE%%-*} > "2.6" ]] && MOD_SUFFIX="ko"

umask 0066

logger -t $MYNAME "$*: $(uname -a)"
mode="$1"

case "$mode" in
start|trace)
	# Remove /etc/srvmagt/srvmagtCronOn if it exists to avoid that eecd is started twice after system crash
	# SA 233464492
	[ -f /etc/srvmagt/srvmagtCronOn ] &&
		rm /etc/srvmagt/srvmagtCronOn

	# Changes to kernel modules might crash a running eecd

	[ -x /usr/sbin/eecd ] && pid=$(mypidof "/usr/sbin/eecd") && {
		mylog_failure_msg "Starting ServerView modules: stop service eecd first!"
		exit 1
	}

	# Remove the EDAC kernel modules if it exists
	[ -d "/etc/modprobe.d/" ] && { 
		edac_disable
		rc=$?
		case $rc in
		0)	mylog_success_msg "Starting ServerView modules: disable EDAC";;
		1)	mylog_failure_msg "Starting ServerView modules: disable EDAC";;
		esac
	}

	# 1. Load the native IPMI module
	# The native IPMI module might or might not have an init script.

	logger -t $MYNAME "Starting native IPMI modules..."
	
	if [ $SV_NICKNAME == "SLES12" ]; then
		cat >/etc/modprobe.d/ipmi_devintf.conf <<EOF
alias acpi*:IPI0001:* ipmi_devintf 
alias acpi*:IPI0001:* ipmi_si 
# alias acpi:IPI000*:* ipmi_msghandler
EOF
		systemctl start ipmi.service
		rc=$?
		case $rc in
		0)	logger -t $MYNAME "Native IPMI modules are loaded.";;
		1)	logger -t $MYNAME "Starting ServerView modules: native IPMI modules were not loaded (rc=$rc).";;
		esac
	
	else
	
		if [ -f  /usr/lib/systemd/system/ipmi.service ]; then
			systemctl start ipmi.service
			rc=$?
			case $rc in
			0)	logger -t $MYNAME "Native IPMI modules are loaded.";;
			1)	logger -t $MYNAME "Starting ServerView modules: native IPMI modules were not loaded (rc=$rc).";;
			esac

		elif [ -x "/etc/init.d/ipmi" ]; then
			# OpenIPMI init script exists
			/etc/init.d/ipmi status >/dev/null 2>&1 || /etc/init.d/ipmi start >/dev/null 2>&1
			rc=$?		# last failure status MUST be from "ipmi start"
			if /etc/init.d/ipmi status >/dev/null 2>&1; then
				logger -t $MYNAME "Native IPMI modules are loaded."
			else
				logger -t $MYNAME "Starting ServerView modules: native IPMI modules were not loaded (rc=$rc)."
			fi
		else
			# No OpenIPMI init script, the IPMI modules must be loaded "manually".

			/sbin/modprobe ipmi_msghandler > /dev/null 2>&1

			if ( ! module_loaded ipmi_msghandler ) ; then
				logger -t $MYNAME "Module 'ipmi_msghandler' cannot be loaded. All IPMI driver modules unloaded."
				# exit 1  # Log only, but don't abort anymore on non-IPMI systems.
			else
				/sbin/modprobe ipmi_devintf > /dev/null 2>&1

				if ( ! module_loaded ipmi_devintf ) ; then
					logger -t $MYNAME "Module 'ipmi_devintf' cannot be loaded. All IPMI driver modules unloaded."
					/sbin/modprobe -r ipmi_msghandler > /dev/null 2>&1
					# exit 1  # Log only, but don't abort anymore on non-IPMI systems.
				else
					/sbin/modprobe ipmi_si > /dev/null 2>&1

					if ( ! module_loaded ipmi_devintf ) ; then
						logger -t $MYNAME "Module 'ipmi_si' cannot be loaded. All IPMI driver modules unloaded."
						/sbin/modprobe -r ipmi_devintf > /dev/null 2>&1
						/sbin/modprobe -r ipmi_msghandler > /dev/null 2>&1
						# exit 1  # Log only, but don't abort anymore on non-IPMI systems.
					else
						# Now ipmi modules are loaded
						if [ ! -x /sbin/udevd ]; then
							DEVMAJOR=`cat /proc/devices | awk '/ipmidev/{print $1}'`
							rm -f /dev/ipmi${INTF_NUM}
							/bin/mknod -m 0600 /dev/ipmi${INTF_NUM} c ${DEVMAJOR} 0 
						fi

						# udev can take several seconds to create /dev/ipmi0,
						# but it happens asynchronously, so delay here
							locdelay=20
						while [ ! -e /dev/ipmi${INTF_NUM} -a ${locdelay} -gt 0 ]; do
							locdelay=$((locdelay - 1))
							sleep 1
						done

						if [ ! -e /dev/ipmi${INTF_NUM} ]; then
							logger -t $MYNAME "Node '/dev/ipmi0' has not been created. All IPMI driver modules unloaded."
							/sbin/modprobe -r ipmi_si > /dev/null 2>&1
							/sbin/modprobe -r ipmi_devintf > /dev/null 2>&1
							/sbin/modprobe -r ipmi_msghandler > /dev/null 2>&1
							# exit 1 Log only, but don't abort anymore on non-IPMI systems.
						else
							# Start the IPMI Watchdog.
							/sbin/modprobe ipmi__watchdog > /dev/null 2>&1
							if /sbin/lsmod | grep ipmi__watchdog >/dev/null 2>&1 ; then
								logger -t $MYNAME "Module 'ipmi_watchdog' cannot be loaded."
							fi
						fi
					fi
				fi
			fi
		fi
	fi

	[ "${SV_NICKNAME:0:2}" = "XS" -o "${SV_NICKNAME:0:1}" = "O" -o "${SV_NICKNAME:0:3}" = "TLX" ] && {
		mylog_success_msg "Starting ServerView modules: Note that $SV_NICKNAME Server does not offer smbus."
		exit 0
	}

	# 2. Validate SV modules and recompile if necessary unless PLDP or DUP are present.
	# Note: The release of the RUNNING kernel is within the searched folder name!

# OL!!!
	[ "${SV_NICKNAME:0:5}" = "SLES1" -o "${SV_NICKNAME:0:4}" = "RHEL" ]  && {
		# In (valid) presence of PLDP or DUP required modules should exist

		errors=0
		for module in $SV_MODULES; do
			flags=
			[ "$mode" = trace ] && flags="${module}Debug=3"

			logger -t $MYNAME "loading (modprobe) module $module $flags"
			/sbin/modprobe -q $module $flags 2>/dev/null
			insrc=$?

			[ $insrc -eq 0 ] && {
				# Recreate the module's special file

				rm -f /dev/pci/$module
				major=$(grep $module /proc/devices) && {
					major=${major%% *}
					[ -e /dev/pci ] || {
						mkdir /dev/pci
						chmod 755 /dev/pci
						chown root /dev/pci
						chgrp root /dev/pci
					}
					mknod -m 644 /dev/pci/$module c $major 0 2>&1 | logger -t $MYNAME
				}

				[ -c /dev/pci/$module ] && {
					logger -t $MYNAME "created $(ls -l /dev/pci/$module)"
					mylog_success_msg "Starting ServerView modules: $module $flags"
					continue
				}
			}
			
			logger -t $MYNAME "Starting ServerView modules: no KMP for $module. Own $module is used"
			let errors++
                                
		done
		[ $errors -eq 0 ] && exit 0
			
	}

	# Compile any missing and necessary SV modules.
	# PLDP and DUP module DON'T exist here 

	compileModules=0
	for module in $SV_MODULES; do
		path=/lib/modules/$THIS_RELEASE/srvmagt/$module.$MOD_SUFFIX

		[ -f $path ] && {
			logger -t $MYNAME "Starting ServerView modules: found $path"
			continue;
		}
		logger -t $MYNAME "Starting ServerView modules: make $path"
		let compileModules++
	done
		
	[ $compileModules -gt 0 ] && {
		/etc/srvmagt/StartupScripts/eecd_mods makemods || {
			mylog_failure_msg "Starting ServerView modules: cannot make modules"
			exit 1
		}
	}

	# 3. (Re)load each ServerView module in turn

	errors=0
	for module in $SV_MODULES; do
		res=$(lsmod | grep "$module ") && {
			mylog_success_msg "Starting ServerView modules: $module already loaded"
			continue
		}

		path=/lib/modules/$THIS_RELEASE/srvmagt/$module.$MOD_SUFFIX
		[ -f $path ] && {
			flags=
			[ "$mode" = trace ] && flags="${module}Debug=3"

			logger -t $MYNAME "loading (insmod) module $module $flags"
			insmod $path $flags >/tmp/eecd_mods.log 2>&1
			insrc=$?
			logger -t $MYNAME -f /tmp/eecd_mods.log

			[ $insrc -eq 0 ] && {
				# Recreate the module's special file

				rm -f /dev/pci/$module
				major=$(grep $module /proc/devices) && {
					major=${major%% *}
					[ -e /dev/pci ] || {
						mkdir /dev/pci
						chmod 755 /dev/pci
						chown root /dev/pci
						chgrp root /dev/pci
					}
					mknod -m 644 /dev/pci/$module c $major 0 2>&1 | logger -t $MYNAME
				}

				[ -c /dev/pci/$module ] && {
					logger -t $MYNAME "created $(ls -l /dev/pci/$module)"
					mylog_success_msg "Starting ServerView modules: $module $flags"
					continue
				}
			}

			# The module will not load. Missing HW is not an error, other causes are.
			# Since distinction is impossible, just log this event to /var/log/messages.

			logger -t $MYNAME "Starting ServerView modules: cannot load $module (missing HW?)"
			continue
		}

		mylog_failure_msg "Starting ServerView modules: $path does not exist"
		let errors++
	done

	[ $errors -eq 0 ] && exit 0
	exit 1 ;;

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)

	echo "ServerView modules packages:"
	rpm -q \
		--queryformat '\tinstalled %{INSTALLTIME:date} %{NAME}-%{VERSION}-%{RELEASE}\n' \
		srvmagt-mods_src

	pkgs=$(rpm -qa | egrep "primergy-ipmi|primergy-smbus|kmod-ipmi|kmod-smbus")
	for pkg in $pkgs; do
		rpm -q \
			--queryformat '\tinstalled %{INSTALLTIME:date} %{NAME}-%{VERSION}-%{RELEASE}\n' \
		$pkg
	done

	# Show SV modules status including native IPMI module

	echo ""
	lsmod | head -1
	if [ ${SV_NICKNAME:0:2} = "XS" ]; then
		res=$(lsmod | grep "ipmi_")
		
		if [ -n "$res" ]; then
			printf "$res"
			exit 0
		fi
		exit 3
	fi

	no_n_ipmi=0
	theLine=$(lsmod | grep "ipmi_")
	if [ $? -eq 0 ]; then
		echo "$theLine"
	else
		echo "Native IPMI module(s) not loaded"
		no_n_ipmi=1
	fi
	
	no_smbus=0
	theLine=$(lsmod | grep "smbus")
	if [ $? -eq 0 ]; then
		echo "$theLine"
	else
		echo "ServerView smbus module not loaded"
		
		# On ESX4, OL and OVM a missing smbus is OK.
		[ ${SV_NICKNAME} = "ESX4" -o ${SV_NICKNAME:0:2} = "OL" -o ${SV_NICKNAME:0:3} = "OVM" ] || no_smbus=1
	fi
	
	[ $no_n_ipmi -eq 0 -a $no_smbus -eq 0 ] || exit 3
	
	exit 0 ;;

makemods)
	# Only in the package's "src" incarnation
	# Compile ServerView modules for the RUNNING kernel
	# Make sure suitable kernel source is installed for module compilation

	[ $MYNAME = "eecd_mods_bin" ] && exit 1

	kdir=$(checkKernelSource $SV_NICKNAME $SV_ARCH)
	case $? in 
	0)
		 ;;
	1)
		mylog_failure_msg "Compiling found no $SV_NICKNAME kernel $THIS_RELEASE source"
		logger -t $MYNAME "$mode found no $SV_NICKNAME kernel $THIS_RELEASE source [${kdir%%:*}]"
		exit 1 ;;
	2)
		mylog_failure_msg "kernel source $SV_PKG_ARCH and processor architecture $SV_ARCH mismatch"		
		exit 1 ;;
	esac

	logger -t $MYNAME "$mode compiles with $SV_NICKNAME kernel $THIS_RELEASE source: ${kdir%%:*}"

	echo "Compiling ServerView modules for $SV_NICKNAME kernel $THIS_RELEASE..."
	logger -t $MYNAME "Compiling ServerView modules for $SV_NICKNAME kernel $THIS_RELEASE..."
	cd /etc/srvmagt/sources;make -s -C /etc/srvmagt/sources all >/tmp/eecd_mods.log 2>&1
	makerc=$?
	logger -t $MYNAME -f /tmp/eecd_mods.log
	if [ $makerc -eq 0 ]; then
		mylog_success_msg "Compiling ServerView modules"
		logger -t $MYNAME "$mode succeeded"
		exit 0
	else
		mylog_failure_msg "Compiling ServerView modules"
		echo "See /var/log/messages for details!"
		logger -t $MYNAME "$mode failed"
		exit 1
	fi ;;

makepackage)
	# Only in the package's "src" incarnation
	# Build the binaries package srvmagt-mods_bin

	[ $MYNAME = "eecd_mods_bin" ] && exit 1

	echo -n "Building ServerView modules RPM package srvmagt-mods_bin"
	pkg=$(/etc/srvmagt/sources/srvmagt_buildpackage)
	if [ $? -eq 0 ]; then
		mylog_success_msg ""
		echo -e "The RPM package $pkg is in /etc/srvmagt/rpms.\n"
		rpm -qip "/etc/srvmagt/rpms/$pkg"
		exit 0
	else
		mylog_failure_msg ""
		echo "See /var/log/messages for details!"
		exit 1
	fi ;;

showlog)
	# Display my log file

	grep $MYNAME /var/log/messages | more
	exit 0 ;;

try-restart|reload|*)
	echo "Usage: $0 {start|stop|trace|status|makemods|makepackage|showlog}"
	exit 1 ;;
esac

exit 1
# EOF
