#!/bin/bash
#
# cs_precheck_for_hana
#
# (c) 2011-2017 SUSE Linux GmbH, Germany.
# (c) 2018-2019 SUSE LLC
# Author: L.Pinne.
# GNU General Public License v2. No warranty.
# http://www.gnu.org/licenses/gpl.html
#
# Version: 2019-11-28 19:25
#
# shellcheck disable=SC1090,SC2128
#

EXE="$0"

for CFG in "/etc/ClusterTools2/cs_precheck_for_hana" "/etc/ClusterTools2/cs_show_supportconfig"; do
	test -s $CFG && source $CFG
done

test -z "${TEMP}" &&\
	TEMP="/dev/shm/cltl.$RANDOM"

# TODO use common library with cs_sum_base_config and cs_show_supportconfig

test -z "${HANA_SAP_BOOTARG}" &&\
	HANA_SAP_BOOTARG="
intel_idle.max_cstate=0
processor.max_cstate=1
transparent_hugepage=never
numa_balancing=disabled
"
test -z "${HANA_SUSE_BOOTARG}" &&\
	HANA_SUSE_BOOTARG="
elevator=noop
cgroup_disable=memory
"
test -z "${HANA_SAP_SYSCTL}" &&\
	HANA_SAP_SYSCTL="
vm.pagecache_limit_mb
vm.pagecache_limit_ignore_dirty
vm.overcommit_memory
vm.swappiness
vm.max_map_count
vm.memory_failure_early_kill
fs.aio-max-nr
fs.file-max
kernel.sem
kernel.shmall
kernel.shmmax
net.core.somaxconn
net.ipv4.ip_local_port_range
net.ipv4.tcp_slow_start_after_idle
net.ipv4.tcp_slow_start_after_idle
net.ipv4.tcp_max_syn_backlog
net.ipv4.tcp_tw_reuse
net.ipv4.tcp_tw_recycle
net.ipv4.tcp_timestamps
net.ipv4.tcp_syn_retries
net.ipv4.tcp_wmem
net.ipv4.tcp_rmem
"
test -z "${HANA_SUSE_SYSCTL}" &&\
	HANA_SUSE_SYSCTL="
vm.dirty_bytes
vm.dirty_background_bytes
"
# TODO HANA_VERS_MIN as well?
# TODO HANA_SAP_PKG_YES as well?
test -z "${HANA_SAP_SVC_YES}" &&\
	HANA_SAP_SVC_YES="
syslog-ng.service
ntpd.service
sapinit.service
"
test -z "${HANA_SUSE_SVC_YES}" &&\
HANA_SUSE_SVC_YES="
mcelog.service
btrfsmaintenance-refresh.service
sshd.service
systemd-sysctl.service
tuned.service
sapconf.service
uuidd.socket
"
test -z "${HANA_SAP_SVC_OFF}" &&\
	HANA_SAP_SVC_OFF="
kdump.service
apparmor.service
"
test -z "${HANA_SUSE_SVC_OFF}" &&\
HANA_SUSE_SVC_OFF="
mysql.service
SuSEfirewall2.service
SuSEfirewall2_init.service
uuidd.service
"
test -z "${HANA_VERS_MIN}" &&\
	HANA_VERS_MIN="
kernel-default:3.12.51-60.20
kernel-xen:3.12.51-60.20
kernel-ppc:3.12.51-60.20
glibc:2.11.3-17.56.2
libgcc_s1:4.7.2_20130108-0.17.2
libstdc++6:4.7.2_20130108-0.17.2
xfsprogs:3.1.8-0.5.1
util-linux:2.25-22.1
uuidd:2.25-22.1
"
test -z "${HANA_SAP_PKG_YES}" &&\
	HANA_SAP_PKG_YES="
bc
iptraf
ntp
sudo
syslog-ng
tcsh
libssh2-1
libstdc++6
libgcc_s1
libpng12-0
libcairo2
libgtk-2_0-0
libjpeg62
libyui-ncurses7
libltdl7
libuuid1
libssh2-1
libnuma1
libicu52_1
expect
autoyast2-installation
cairo
findutils-locate
graphviz
iptraf
krb5-32bit
krb5-client
nfs-client
tuned
numactl
uuidd
xfsprogs
python-curses
python-pycurl
unixODBC
"
test -z "${HANA_SAP_PKG_NOT}" &&\
        HANA_SAP_PKG_NOT="
apparmor
apache2-mod_apparmor
apparmor-parser
apparmor-profiles
apparmor-utils
pam_apparmor
perl-apparmor
yast2-apparmor
ulimit
"
test -z "${HANA_SUSE_PTRN}" &&\
	HANA_SUSE_PTRN="
Minimal
Basis-Devel
base
x11
sap-hana
sap_server
ha_sles
"
test -z "${HANA_SUSE_PKG_YES}" &&\
	HANA_SUSE_PKG_YES="
perl-TermReadLine-Gnu
rear1172a
sysstat
supportutils
sapconf
xfsdump
fio-util
fio-common
fio-sysvinit
libvsl
iomemory-vsl
fio-firmware-ioaccelerator
fio-firmware-highiops
SAPHanaSR
SAPHanaSR-doc
HANA-Firewall
librdmacm1
libibverbs1
"

CFGVAR="
HANA_SAP_BOOTARG
HANA_SAP_SYSCTL
HANA_SAP_SVC_YES
HANA_SAP_SVC_OFF
HANA_SAP_PKG_YES
HANA_SAP_PKG_NOT
HANA_VERS_MIN
HANA_SUSE_BOOTARG
HANA_SUSE_SYSCTL
HANA_SUSE_PTRN
HANA_SUSE_PKG_YES
HANA_SUSE_SVC_YES
HANA_SUSE_SVC_OFF
HANA_SUSE_RUNLVL
"


function help() {
	echo "usage:	$(basename "$EXE")"
	echo "	$(basename "$EXE") [OPTION]"
	echo
	echo " --help		show help"
	echo " --version	show version"
	echo " --writecfg	show some internal variables"
	echo " --base 	show base config"
	echo " --apps 	show HANA apps config"
	echo
	test $UID -gt 0 && echo "please call as root"
}


function echo_msgsep(){
	echo
	echo "============================================================ ${1:0
:14} ==="
}


function writecfg(){
	# TODO --writecfg <variable_name> show single variable
	#echo "INFO: ### $FUNCNAME $1 start ###" >/dev/stderr
	echo -e "# $CFG \n# For SLES12.\n#"
	for c in $CFGVAR; do
		echo "${c}=\""
		# shellcheck disable=SC2086
		echo ${!c} | tr " " "\n"
		echo "\""
		echo "#"
	done
	#echo "INFO: ### $FUNCNAME $1 end ###" >/dev/stderr
}


function prck_hardware(){

	echo "INFO: start $EXE $FUNCNAME"
	echo_msgsep "$FUNCNAME"

	echo -n "cpu "
	/usr/bin/grep "model.name" /proc/cpuinfo | sort -u
	echo -n "cpu MHz:	"
	/usr/bin/awk '$2=="MHz" {print $4}' /proc/cpuinfo | sort -u | tr "\n" " "
	# TODO number of sockets, NUMA
	echo

	/usr/bin/grep -e "MemTotal:" -e "SwapTotal:" -e "VmallocTotal:" /proc/meminfo

	echo
	echo "INFO: normal_end $EXE $FUNCNAME"
}


function prck_kernel(){

	echo "INFO: start $EXE $FUNCNAME"
	echo_msgsep "$FUNCNAME"

	# TODO show recommeded version from HANA_VERS_MIN
	echo -n "Kernel: "; /bin/uname -s -r -v -m -p -i -o
	echo

	FIL="/proc/cmdline"
	for f in $FIL; do
		for a in ${HANA_SAP_BOOTARG} ${HANA_SUSE_BOOTARG}; do
			FOUND=$(grep "$a" "$f")
			test -z "${FOUND}" && FOUND="NA"
			echo "${f}: ${a} :	${FOUND}"
		done
	done
	echo

	FOUND=$(/bin/dmesg | /usr/bin/grep -e governor -e cpupower -e cpuidle |\
			tr -s "\n" " ")
	test -z "${FOUND}" && FOUND="NA"
	echo "CPU frequency scaling:      ${FOUND}"
	echo
	OPT="/sys/devices/system/cpu/cpu*/cpufreq/scaling_governor /sys/kernel/mm/transparent_hugepage/enabled /sys/.*/scheduler"
	f="/etc/init.d/boot.local"
	for a in $OPT ; do
		FOUND=$(grep "$a" $f 2>/dev/null)
		test -z "${FOUND}" && FOUND="NA"
		echo "${f}: ${a} :      ${FOUND}"
	done
	echo
	f="/sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages"
	FOUND=$(cat $f 2>/dev/null)
	test -z "${FOUND}" && FOUND="NA"
	echo "$f (=0):	${FOUND}"
	f="/sys/devices/system/cpu/cpuidle/current_driver"
	FOUND=$(cat $f 2>/dev/null)
	test -z "${FOUND}" && FOUND="NA"
	echo "$f (acpi_idle):  ${FOUND}"
	echo

	# TODO loop
	echo -n "Elevator: deadline: "
	find /sys/devices/ -name "scheduler" -exec grep "\[deadline\]" {} \; | wc -l
	echo -n "Elevator: noop: "
	find /sys/devices/ -name "scheduler" -exec grep "\[noop\]" {} \; | wc -l
	echo -n "Elevator: cfq (=0): "
	find /sys/devices/ -name "scheduler" -exec grep "\[cfq\]" {} \; | wc -l
	echo
	echo -n "Elevator: mq-deadline: "
	find /sys/devices/ -name "scheduler" -exec grep "\[mq-deadline\]" {} \; | wc -l
	echo -n "Elevator: none: "
	find /sys/devices/ -name "scheduler" -exec grep "\[none\]" {} \; | wc -l
	echo -n "Elevator: kyber: "
	find /sys/devices/ -name "scheduler" -exec grep "\[kyber\]" {} \; | wc -l
	echo -n "Elevator: bfq: "
	find /sys/devices/ -name "scheduler" -exec grep "\[bfq\]" {} \; | wc -l
	echo

	FOUND=$(lsmod | grep -e dog -e wdt | cut -d" " -f1 | tr "\n" " ")
	test -z "${FOUND}" && FOUND="NA"
	echo "Watchdog loaded:  ${FOUND}"

	echo
	echo "INFO: normal_end $EXE $FUNCNAME"
}


function prck_network(){

	echo "INFO: start $EXE $FUNCNAME"
	echo_msgsep "$FUNCNAME"

	# TODO fix output
	a="bond"
	FOUND=$(ip -o a s | grep $a)
	test -z "${FOUND}" && FOUND="NA"
	### echo "network ${a} :      ${FOUND}"
	# TODO look for 10gbit/s
	# TODO look for MTU=9000
	# TODO look for irq balancing
	# TODO look for offload options

	echo
	echo "INFO: normal_end $EXE $FUNCNAME"
}


function prck_sysconf(){

	echo "INFO: start $EXE $FUNCNAME"
	echo_msgsep "$FUNCNAME"

	# TODO ppc64: /etc/lilo.conf instead of /boot/grub/menu.lst
	FIL="/boot/grub/menu.lst /etc/sysconfig/bootloader /boot/grub2/grub.cfg"
	for f in $FIL; do
		for a in ${HANA_SAP_BOOTARG} ${HANA_SUSE_BOOTARG}; do
			FOUND=$(grep "$a" "$f" 2>/dev/null)
			test -z "${FOUND}" && FOUND="NA"
			echo "${f}: ${a} :	${FOUND}"
		done
	done
	echo

	OPT="/sys/devices/system/cpu/cpu*/cpufreq/scaling_governor /sys/kernel/mm/transparent_hugepage/enabled /sys/.*/scheduler"
	f="/etc/init.d/boot.local"
	for a in $OPT ; do
		FOUND=$(grep "$a" $f 2>/dev/null)
		test -z "${FOUND}" && FOUND="NA"
		echo "${f}: ${a} :      ${FOUND}"
	done
	echo

	f=/etc/sysctl.conf
	for a in ${HANA_SAP_SYSCTL} ${HANA_SUSE_SYSCTL}; do
		FOUND=$(grep "$a" $f)
		test -z "${FOUND}" && FOUND="NA"
		echo "${f}: ${a} :	${FOUND}"
	done
	echo

	# TODO variable
	for f in bootloader kernel kdump; do
		g="/etc/sysconfig/$f"
		test -r $g || echo "${g}: NA"; continue
		echo "${g}:"
		grep -v "^#" $g | tr -s "\n" | grep -v "\"\"$"
		echo 
	done	
	echo

	CMD=/usr/bin/zcat
	INITRD=$(readlink /boot/initrd 2>/dev/null)
	if [ "$(file /boot/"$INITRD" | sed 's%.*:%%')" == " XZ compressed data" ]; then
		CMD=/usr/bin/xzcat
	fi
	FOUND=$($CMD /boot/"$INITRD" | cpio -itv 2>/dev/null |\
		colrm 43 54 | grep -e "dog.*.ko" -e "wdt.*.ko" |\
		awk '{print $6}' | tr "\n" " ")
	test -z "${FOUND}" && FOUND="NA"
	echo "Watchdog in initrd:      ${FOUND}"

	FOUND=$($CMD /boot/"$INITRD" | cpio -itv 2>/dev/null |\
		colrm 43 54 | grep -e "/etc/multipath.*"  -e lvm.conf |\
		awk '{print $6}' | tr "\n" " ")
	test -z "${FOUND}" && FOUND="NA"
	echo "MPIO, LVM in initrd:      ${FOUND}"

	echo
	echo "INFO: normal_end $EXE $FUNCNAME"
}


# TODO function prck_timeres(){
# TODO /etc/ntp.conf
# TODO /etc/sysconfig/ntp: NTPD_FORCE_SYNC_ON_STARTUP=yes NTPD_OPTIONS=-g
# TODO ntpq -p
# TODO chkconfig ntp
#}


function prck_runlvl(){

	echo "INFO: start $EXE $FUNCNAME"
	echo_msgsep "$FUNCNAME"

	# TODO sles12 HANA_SUSE_RUNLVL
	test -r /etc/inittab && FOUND=$(awk -F: '$1=="id" && $3=="initdefault" {print $2}' /etc/inittab) || FOUND=$(systemctl get-default)
	test -z "${FOUND}" && FOUND="NA"
	echo "default runlevel (3):	${FOUND}"
	echo

	# TODO sles12
	# TODO sapinit?
	for a in ${HANA_SAP_SVC_YES} ${HANA_SUSE_SVC_YES}; do
		FOUND=$(chkconfig -A | grep "$a" | awk '{print $2}')
		test -z "${FOUND}" && FOUND="NA"
		echo "chkconfig ${a} ON:	${FOUND}"
	done
	for a in ${HANA_SAP_SVC_OFF} ${HANA_SUSE_SVC_OFF}; do
		FOUND=$(chkconfig -A | grep "$a" | awk '{print $2}')
		test -z "${FOUND}" && FOUND="NA"
		echo "chkconfig ${a} OFF:	${FOUND}"
	done

	echo
	echo "INFO: normal_end $EXE $FUNCNAME"
}


function prck_basesoft(){

	echo "INFO: start $EXE $FUNCNAME"
	echo_msgsep "$FUNCNAME"

	# TODO abort zypper, if server not reached
	INSTALLED_PTRN=$(zypper -n se -t pattern | awk '$1=="i" {print $3}')
	for a in ${HANA_SUSE_PTRN}; do
		FOUND=$(echo "$INSTALLED_PTRN" | tr " " "\n" | grep "$a")
		test -z "${FOUND}" && FOUND="NA"
		echo "pattern ${a}:       ${FOUND}"
	done
	echo

	RPMLIST=$(rpm -qa | sort)
	for a in ${HANA_SAP_PKG_YES} ${HANA_SUSE_PKG_YES}; do
		FOUND=$(echo "$RPMLIST" | tr " " "\n" | grep "$a" | tr "\n" " ")
		test -z "${FOUND}" && FOUND="NA"
		echo "${a} :      ${FOUND}"
	done
	# TODO also glibc HANA_VERS_MIN
	# TODO check HANA_SAP_PKG_NOT

	echo
	echo "INFO: normal_end $EXE $FUNCNAME"
}


function prck_apps() {

	echo "INFO: start $EXE $FUNCNAME"
	echo_msgsep "$FUNCNAME"

	# TODO check for SAP programs needed by SAPHanaSR
	#	1. sapcontrol/sapstartsrv 
	#		/usr/sap/$SID/$InstanceName/exe/sapstartsrv
	#		/usr/sap/$SID/$InstanceName/exe/sapcontrol
	#	2. landscapeHostConfiguration.py
	#	3. hdbnsutil
	#	4. systemReplicationStatus.py
	#	5. saphostctrl
	# TODO check for disk space for HANA
	#	50GB	/usr/sap/
	#	x RAM	/hana/log/ 
	#	x RAM	/hana/data/
	#	x RAM	/hana/shared/	NFS
	# TODO instance name, site name, virt. ho0stname for detailled checks
	# TODO see HWCCT output for other interesting points
	# TODO loop, "NA"
	# TODO for SAPHanaSR-ScaleOut
	#	/etc/sudoers
	#	/hana/shared/$SID/.../global.ini
	#	/hana/shared/.../SAPHanaSR.pyc
	# TODO grep sapsys /etc/groups, grep [a-z]??adm /etc/passwd		
	/bin/ls -al /hana/data/ | awk '{print $1,$2,$3,$4,$5,$9}'
	/bin/ls -al /hana/log/ | awk '{print $1,$2,$3,$4,$5,$9}'
	/bin/ls -al /hana/shared/ | awk '{print $1,$2,$3,$4,$5,$9}'
	/bin/ls -al /usr/sap/[A-Z]??/SYS/profile/ | awk '{print $1,$2,$3,$4,$5,$9}'
	/bin/ls -al /usr/sap/*/[0-9][0-9]/work/ | awk '{print $1,$2,$3,$4,$5,$9}'
	# TODO /usr/sap/sapservices
	echo
	echo "INFO: normal_end $EXE $FUNCNAME"
}


# main()
case $1 in
	-v|--version)
		echo -n "$(basename "$EXE") "
		head -11 "$EXE" | grep "^# Version: "
		exit
	;;
	-b|--base)
		echo "INFO: start $EXE"

		test $UID -gt 0 && echo "please call as root." && exit
		mkdir "$TEMP"
		cd "$TEMP" || exit 1
		prck_hardware
		prck_kernel
		prck_sysconf
		prck_runlvl
		prck_network
		prck_basesoft
		cd "$OLDPWD" || exit 1
		rm -rf "$TEMP"

		echo "INFO: normal_end $EXE"
		exit
	;;
	-a|--apps)
		echo "INFO: start $EXE"
		test $UID -gt 0 && echo "please call as root." && exit

		prck_apps

		echo "INFO: normal_end $EXE"
		exit
	;;
	-w|--writecfg)
		writecfg
		exit
	;;
	*)
		help
		exit		
	;;
esac
#
