Petr Šabata f5bf49
#!/bin/bash
Petr Šabata f5bf49
KEXEC=/sbin/kexec
Petr Šabata f5bf49
Petr Šabata f5bf49
KDUMP_KERNELVER=""
Petr Šabata f5bf49
KDUMP_KERNEL=""
Petr Šabata f5bf49
KDUMP_COMMANDLINE=""
Petr Šabata f5bf49
KEXEC_ARGS=""
DistroBaker 5cac7c
KDUMP_LOG_PATH="/var/log"
Petr Šabata f5bf49
MKDUMPRD="/sbin/mkdumprd -f"
Kairui Song 96a3fc
MKFADUMPRD="/sbin/mkfadumprd"
Petr Šabata f5bf49
DRACUT_MODULES_FILE="/usr/lib/dracut/modules.txt"
Petr Šabata f5bf49
SAVE_PATH=/var/crash
Petr Šabata f5bf49
SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa"
Petr Šabata f5bf49
INITRD_CHECKSUM_LOCATION="/boot/.fadump_initrd_checksum"
Petr Šabata f5bf49
DUMP_TARGET=""
Petr Šabata f5bf49
DEFAULT_INITRD=""
Petr Šabata f5bf49
DEFAULT_INITRD_BAK=""
Petr Šabata f5bf49
KDUMP_INITRD=""
Petr Šabata f5bf49
TARGET_INITRD=""
Petr Šabata f5bf49
FADUMP_REGISTER_SYS_NODE="/sys/kernel/fadump_registered"
Petr Šabata f5bf49
#kdump shall be the default dump mode
Petr Šabata f5bf49
DEFAULT_DUMP_MODE="kdump"
Petr Šabata f5bf49
image_time=0
Petr Šabata f5bf49
DistroBaker 5cac7c
standard_kexec_args="-d -p"
Petr Šabata f5bf49
Petr Šabata f5bf49
# Some default values in case /etc/sysconfig/kdump doesn't include
Petr Šabata f5bf49
KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug"
Petr Šabata f5bf49
Petr Šabata f5bf49
if [ -f /etc/sysconfig/kdump ]; then
Petr Šabata f5bf49
	. /etc/sysconfig/kdump
Petr Šabata f5bf49
fi
Petr Šabata f5bf49
DistroBaker 5cac7c
[[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut
DistroBaker 5cac7c
. $dracutbasedir/dracut-functions.sh
DistroBaker 5cac7c
. /lib/kdump/kdump-lib.sh
DistroBaker 624a64
. /lib/kdump/kdump-logger.sh
DistroBaker 5cac7c
DistroBaker 5cac7c
#initiate the kdump logger
DistroBaker 5cac7c
dlog_init
DistroBaker 5cac7c
if [ $? -ne 0 ]; then
DistroBaker 5cac7c
	echo "failed to initiate the kdump logger."
DistroBaker 5cac7c
	exit 1
DistroBaker 5cac7c
fi
DistroBaker 5cac7c
Petr Šabata f5bf49
single_instance_lock()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local rc timeout=5
Petr Šabata f5bf49
Petr Šabata f5bf49
	exec 9>/var/lock/kdump
Petr Šabata f5bf49
	if [ $? -ne 0 ]; then
DistroBaker 5cac7c
		derror "Create file lock failed"
Petr Šabata f5bf49
		exit 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	flock -n 9
Petr Šabata f5bf49
	rc=$?
Petr Šabata f5bf49
Petr Šabata f5bf49
	while [ $rc -ne 0 ]; do
DistroBaker 5cac7c
		dinfo "Another app is currently holding the kdump lock; waiting for it to exit..."
Petr Šabata f5bf49
		flock -w $timeout 9
Petr Šabata f5bf49
		rc=$?
Petr Šabata f5bf49
	done
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
determine_dump_mode()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	# Check if firmware-assisted dump is enabled
Petr Šabata f5bf49
	# if yes, set the dump mode as fadump
Petr Šabata f5bf49
	if is_fadump_capable; then
DistroBaker 5cac7c
		dinfo "Dump mode is fadump"
Petr Šabata f5bf49
		DEFAULT_DUMP_MODE="fadump"
Petr Šabata f5bf49
	fi
DistroBaker 5cac7c
	ddebug "DEFAULT_DUMP_MODE=$DEFAULT_DUMP_MODE"
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
save_core()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	coredir="/var/crash/`date +"%Y-%m-%d-%H:%M"`"
Petr Šabata f5bf49
Petr Šabata f5bf49
	mkdir -p $coredir
DistroBaker 5cac7c
	ddebug "cp --sparse=always /proc/vmcore $coredir/vmcore-incomplete"
Petr Šabata f5bf49
	cp --sparse=always /proc/vmcore $coredir/vmcore-incomplete
Petr Šabata f5bf49
	if [ $? == 0 ]; then
Petr Šabata f5bf49
		mv $coredir/vmcore-incomplete $coredir/vmcore
DistroBaker 5cac7c
		dinfo "saved a vmcore to $coredir"
Petr Šabata f5bf49
	else
DistroBaker 5cac7c
		derror "failed to save a vmcore to $coredir"
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	# pass the dmesg to Abrt tool if exists, in order
Petr Šabata f5bf49
	# to collect the kernel oops message.
Petr Šabata f5bf49
	# https://fedorahosted.org/abrt/
Petr Šabata f5bf49
	if [ -x /usr/bin/dumpoops ]; then
DistroBaker 5cac7c
		ddebug "makedumpfile --dump-dmesg $coredir/vmcore $coredir/dmesg"
Petr Šabata f5bf49
		makedumpfile --dump-dmesg $coredir/vmcore $coredir/dmesg >/dev/null 2>&1
DistroBaker 5cac7c
		ddebug "dumpoops -d $coredir/dmesg"
Petr Šabata f5bf49
		dumpoops -d $coredir/dmesg >/dev/null 2>&1
Petr Šabata f5bf49
		if [ $? == 0 ]; then
DistroBaker 5cac7c
			dinfo "kernel oops has been collected by abrt tool"
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
rebuild_fadump_initrd()
Petr Šabata f5bf49
{
Kairui Song 96a3fc
	if ! $MKFADUMPRD "$DEFAULT_INITRD_BAK" "$TARGET_INITRD" --kver "$KDUMP_KERNELVER"; then
Kairui Song 96a3fc
		derror "mkfadumprd: failed to make fadump initrd"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_earlykdump_is_enabled()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	grep -q -w "rd.earlykdump" /proc/cmdline
Petr Šabata f5bf49
	return $?
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
rebuild_kdump_initrd()
Petr Šabata f5bf49
{
DistroBaker 5cac7c
	ddebug "rebuild kdump initrd: $MKDUMPRD $TARGET_INITRD $KDUMP_KERNELVER"
Petr Šabata f5bf49
	$MKDUMPRD $TARGET_INITRD $KDUMP_KERNELVER
Petr Šabata f5bf49
	if [ $? != 0 ]; then
DistroBaker 5cac7c
		derror "mkdumprd: failed to make kdump initrd"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	if check_earlykdump_is_enabled; then
DistroBaker 5cac7c
		dwarn "Tips: If early kdump is enabled, also require rebuilding the system initramfs to make the changes take effect for early kdump."
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
rebuild_initrd()
Petr Šabata f5bf49
{
5f4c5f
	if [[ ! -w $(dirname $TARGET_INITRD) ]];then
5f4c5f
		derror "$(dirname $TARGET_INITRD) does not have write permission. Cannot rebuild $TARGET_INITRD"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	if [ $DEFAULT_DUMP_MODE == "fadump" ]; then
Petr Šabata f5bf49
		rebuild_fadump_initrd
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		rebuild_kdump_initrd
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	return $?
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
#$1: the files to be checked with IFS=' '
Petr Šabata f5bf49
check_exist()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	for file in $1; do
Petr Šabata f5bf49
		if [ ! -e "$file" ]; then
DistroBaker 5cac7c
			derror "Error: $file not found."
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	done
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
#$1: the files to be checked with IFS=' '
Petr Šabata f5bf49
check_executable()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	for file in $1; do
Petr Šabata f5bf49
		if [ ! -x "$file" ]; then
DistroBaker 5cac7c
			derror "Error: $file is not executable."
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	done
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
backup_default_initrd()
Petr Šabata f5bf49
{
DistroBaker 5cac7c
	ddebug "backup default initrd: $DEFAULT_INITRD"
DistroBaker 5cac7c
Petr Šabata f5bf49
	if [ ! -f "$DEFAULT_INITRD" ]; then
Petr Šabata f5bf49
		return
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	if [ ! -e $DEFAULT_INITRD_BAK ]; then
DistroBaker 5cac7c
		dinfo "Backing up $DEFAULT_INITRD before rebuild."
Petr Šabata f5bf49
		# save checksum to verify before restoring
Petr Šabata f5bf49
		sha1sum $DEFAULT_INITRD > $INITRD_CHECKSUM_LOCATION
Petr Šabata f5bf49
		cp $DEFAULT_INITRD $DEFAULT_INITRD_BAK
Petr Šabata f5bf49
		if [ $? -ne 0 ]; then
DistroBaker 5cac7c
			dwarn "WARNING: failed to backup $DEFAULT_INITRD."
Petr Šabata f5bf49
			rm -f $DEFAULT_INITRD_BAK
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
restore_default_initrd()
Petr Šabata f5bf49
{
DistroBaker 5cac7c
	ddebug "restore default initrd: $DEFAULT_INITRD"
DistroBaker 5cac7c
Petr Šabata f5bf49
	if [ ! -f "$DEFAULT_INITRD" ]; then
Petr Šabata f5bf49
		return
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	# If a backup initrd exists, we must be switching back from
Petr Šabata f5bf49
	# fadump to kdump. Restore the original default initrd.
Petr Šabata f5bf49
	if [ -f $DEFAULT_INITRD_BAK ] && [ -f $INITRD_CHECKSUM_LOCATION ]; then
Petr Šabata f5bf49
		# verify checksum before restoring
Petr Šabata f5bf49
		backup_checksum=`sha1sum $DEFAULT_INITRD_BAK | awk '{ print $1 }'`
Petr Šabata f5bf49
		default_checksum=`cat $INITRD_CHECKSUM_LOCATION | awk '{ print $1 }'`
Petr Šabata f5bf49
		if [ "$default_checksum" != "$backup_checksum" ]; then
DistroBaker 5cac7c
			dwarn "WARNING: checksum mismatch! Can't restore original initrd.."
Petr Šabata f5bf49
		else
Petr Šabata f5bf49
			rm -f $INITRD_CHECKSUM_LOCATION
Petr Šabata f5bf49
			mv $DEFAULT_INITRD_BAK $DEFAULT_INITRD
Petr Šabata f5bf49
			if [[ $? -eq 0 ]]; then
DistroBaker 5cac7c
				derror "Restoring original initrd as fadump mode is disabled."
Petr Šabata f5bf49
				sync
Petr Šabata f5bf49
			fi
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_config()
Petr Šabata f5bf49
{
DistroBaker 5cac7c
	local -A _opt_rec
ba2668
	while read -r config_opt config_val; do
Petr Šabata f5bf49
		case "$config_opt" in
DistroBaker 5cac7c
		dracut_args)
DistroBaker 5cac7c
			if [[ $config_val == *--mount* ]]; then
DistroBaker 5cac7c
				if [ $(echo $config_val | grep -o "\-\-mount" | wc -l) -ne 1 ]; then
DistroBaker 5cac7c
					derror "Multiple mount targets specified in one \"dracut_args\"."
DistroBaker 5cac7c
					return 1
DistroBaker 5cac7c
				fi
DistroBaker 5cac7c
				config_opt=_target
DistroBaker 5cac7c
			fi
Petr Šabata f5bf49
			;;
DistroBaker 5cac7c
		raw)
DistroBaker 5cac7c
			if [ -d "/proc/device-tree/ibm,opal/dump" ]; then
DistroBaker 5cac7c
				dwarn "WARNING: Won't capture opalcore when 'raw' dump target is used."
Petr Šabata f5bf49
			fi
DistroBaker 5cac7c
			config_opt=_target
DistroBaker 5cac7c
			;;
DistroBaker 5cac7c
		ext[234]|minix|btrfs|xfs|nfs|ssh)
DistroBaker 5cac7c
			config_opt=_target
DistroBaker 5cac7c
			;;
DistroBaker 5cac7c
		sshkey|path|core_collector|kdump_post|kdump_pre|extra_bins|extra_modules|failure_action|default|final_action|force_rebuild|force_no_rebuild|fence_kdump_args|fence_kdump_nodes)
Petr Šabata f5bf49
			;;
Petr Šabata f5bf49
		net|options|link_delay|disk_timeout|debug_mem_level|blacklist)
DistroBaker 5cac7c
			derror "Deprecated kdump config option: $config_opt. Refer to kdump.conf manpage for alternatives."
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
			;;
ba2668
		'')
ba2668
			continue
ba2668
			;;
Petr Šabata f5bf49
		*)
DistroBaker 5cac7c
			derror "Invalid kdump config option $config_opt"
DistroBaker 5cac7c
			return 1
Petr Šabata f5bf49
			;;
Petr Šabata f5bf49
		esac
DistroBaker 5cac7c
ba2668
		if [[ -z "$config_val" ]]; then
ba2668
			derror "Invalid kdump config value for option '$config_opt'"
ba2668
			return 1
ba2668
		fi
ba2668
DistroBaker 5cac7c
		if [ -n "${_opt_rec[$config_opt]}" ]; then
DistroBaker 5cac7c
			if [ $config_opt == _target ]; then
DistroBaker 5cac7c
				derror "More than one dump targets specified"
DistroBaker 5cac7c
			else
DistroBaker 5cac7c
				derror "Duplicated kdump config value of option $config_opt"
DistroBaker 5cac7c
			fi
DistroBaker 5cac7c
			return 1
DistroBaker 5cac7c
		fi
DistroBaker 5cac7c
		_opt_rec[$config_opt]="$config_val"
67b8dd
	done <<< "$(kdump_read_conf)"
Petr Šabata f5bf49
Petr Šabata f5bf49
	check_failure_action_config || return 1
Petr Šabata f5bf49
	check_final_action_config || return 1
Petr Šabata f5bf49
	check_fence_kdump_config || return 1
Petr Šabata f5bf49
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
# get_pcs_cluster_modified_files <image timestamp>
Petr Šabata f5bf49
# return list of modified file for fence_kdump modified in Pacemaker cluster
Petr Šabata f5bf49
get_pcs_cluster_modified_files()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local time_stamp
Petr Šabata f5bf49
	local modified_files
Petr Šabata f5bf49
Petr Šabata f5bf49
	is_generic_fence_kdump && return 1
Petr Šabata f5bf49
	is_pcs_fence_kdump || return 1
Petr Šabata f5bf49
Petr Šabata f5bf49
	time_stamp=`pcs cluster cib | xmllint --xpath 'string(/cib/@cib-last-written)' - | \
Petr Šabata f5bf49
		xargs -0 date +%s --date`
Petr Šabata f5bf49
Petr Šabata f5bf49
	if [ -n $time_stamp -a $time_stamp -gt $image_time ]; then
Petr Šabata f5bf49
		modified_files="cluster-cib"
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	if [ -f $FENCE_KDUMP_CONFIG_FILE ]; then
Petr Šabata f5bf49
		time_stamp=`stat -c "%Y" $FENCE_KDUMP_CONFIG_FILE`
Petr Šabata f5bf49
		if [ "$time_stamp" -gt "$image_time" ]; then
Petr Šabata f5bf49
			modified_files="$modified_files $FENCE_KDUMP_CONFIG_FILE"
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	echo $modified_files
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
setup_initrd()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	prepare_kdump_bootinfo
Petr Šabata f5bf49
	if [ $? -ne 0 ]; then
DistroBaker 5cac7c
		derror "failed to prepare for kdump bootinfo."
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	DEFAULT_INITRD_BAK="$KDUMP_BOOTDIR/.$(basename $DEFAULT_INITRD).default"
Petr Šabata f5bf49
	if [ $DEFAULT_DUMP_MODE == "fadump" ]; then
Petr Šabata f5bf49
		TARGET_INITRD="$DEFAULT_INITRD"
Petr Šabata f5bf49
Petr Šabata f5bf49
		# backup initrd for reference before replacing it
Petr Šabata f5bf49
		# with fadump aware initrd
Petr Šabata f5bf49
		backup_default_initrd
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		TARGET_INITRD="$KDUMP_INITRD"
Petr Šabata f5bf49
Petr Šabata f5bf49
		# check if a backup of default initrd exists. If yes,
Petr Šabata f5bf49
		# it signifies a switch from fadump mode. So, restore
Petr Šabata f5bf49
		# the backed up default initrd.
Petr Šabata f5bf49
		restore_default_initrd
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_files_modified()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local modified_files=""
Petr Šabata f5bf49
Petr Šabata f5bf49
	#also rebuild when Pacemaker cluster conf is changed and fence kdump is enabled.
Petr Šabata f5bf49
	modified_files=$(get_pcs_cluster_modified_files)
Petr Šabata f5bf49
6afe4e
	EXTRA_BINS=$(kdump_get_conf_val kdump_post)
6afe4e
	CHECK_FILES=$(kdump_get_conf_val kdump_pre)
Petr Šabata f5bf49
	HOOKS="/etc/kdump/post.d/ /etc/kdump/pre.d/"
Petr Šabata f5bf49
	if [ -d /etc/kdump/post.d ]; then
Petr Šabata f5bf49
		for file in /etc/kdump/post.d/*; do
Petr Šabata f5bf49
			if [ -x "$file" ]; then
Petr Šabata f5bf49
				POST_FILES="$POST_FILES $file"
Petr Šabata f5bf49
			fi
Petr Šabata f5bf49
		done
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
	if [ -d /etc/kdump/pre.d ]; then
Petr Šabata f5bf49
		for file in /etc/kdump/pre.d/*; do
Petr Šabata f5bf49
			if [ -x "$file" ]; then
Petr Šabata f5bf49
				PRE_FILES="$PRE_FILES $file"
Petr Šabata f5bf49
			fi
Petr Šabata f5bf49
		done
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
	HOOKS="$HOOKS $POST_FILES $PRE_FILES"
6afe4e
	CORE_COLLECTOR=$(kdump_get_conf_val core_collector | awk '{print $1}')
Petr Šabata f5bf49
	CORE_COLLECTOR=`type -P $CORE_COLLECTOR`
Petr Šabata f5bf49
	# POST_FILES and PRE_FILES are already checked against executable, need not to check again.
Petr Šabata f5bf49
	EXTRA_BINS="$EXTRA_BINS $CHECK_FILES"
6afe4e
	CHECK_FILES=$(kdump_get_conf_val extra_bins)
Petr Šabata f5bf49
	EXTRA_BINS="$EXTRA_BINS $CHECK_FILES"
Petr Šabata f5bf49
	files="$KDUMP_CONFIG_FILE $KDUMP_KERNEL $EXTRA_BINS $CORE_COLLECTOR"
Petr Šabata f5bf49
	[[ -e /etc/fstab ]] && files="$files /etc/fstab"
Petr Šabata f5bf49
Petr Šabata f5bf49
	# Check for any updated extra module
6afe4e
	EXTRA_MODULES="$(kdump_get_conf_val extra_modules)"
Petr Šabata f5bf49
	if [ -n "$EXTRA_MODULES" ]; then
Petr Šabata f5bf49
		if [ -e /lib/modules/$KDUMP_KERNELVER/modules.dep ]; then
Petr Šabata f5bf49
			files="$files /lib/modules/$KDUMP_KERNELVER/modules.dep"
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
		for _module in $EXTRA_MODULES; do
Petr Šabata f5bf49
			_module_file="$(modinfo --set-version "$KDUMP_KERNELVER" --filename "$_module" 2>/dev/null)"
Petr Šabata f5bf49
			if [[ $? -eq 0 ]]; then
Petr Šabata f5bf49
				files="$files $_module_file"
Petr Šabata f5bf49
				for _dep_modules in $(modinfo -F depends $_module | tr ',' ' '); do
Petr Šabata f5bf49
				    files="$files $(modinfo --set-version "$KDUMP_KERNELVER" --filename $_dep_modules 2>/dev/null)"
Petr Šabata f5bf49
				done
Petr Šabata f5bf49
			else
Petr Šabata f5bf49
				# If it's not a module nor builtin, give an error
Petr Šabata f5bf49
				if ! ( modprobe --set-version "$KDUMP_KERNELVER" --dry-run "$_module" &>/dev/null ); then
DistroBaker 5cac7c
					dwarn "Module $_module not found"
Petr Šabata f5bf49
				fi
Petr Šabata f5bf49
			fi
Petr Šabata f5bf49
		done
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	# HOOKS is mandatory and need to check the modification time
Petr Šabata f5bf49
	files="$files $HOOKS"
Petr Šabata f5bf49
	check_exist "$files" && check_executable "$EXTRA_BINS"
Petr Šabata f5bf49
	[ $? -ne 0 ] && return 2
Petr Šabata f5bf49
Petr Šabata f5bf49
	for file in $files; do
Petr Šabata f5bf49
		if [ -e "$file" ]; then
Petr Šabata f5bf49
			time_stamp=`stat -c "%Y" $file`
Petr Šabata f5bf49
			if [ "$time_stamp" -gt "$image_time" ]; then
Petr Šabata f5bf49
				modified_files="$modified_files $file"
Petr Šabata f5bf49
			fi
Petr Šabata f5bf49
			if [ -L "$file" ]; then
Petr Šabata f5bf49
				file=$(readlink -m $file)
Petr Šabata f5bf49
				time_stamp=`stat -c "%Y" $file`
Petr Šabata f5bf49
				if [ "$time_stamp" -gt "$image_time" ]; then
Petr Šabata f5bf49
					modified_files="$modified_files $file"
Petr Šabata f5bf49
				fi
Petr Šabata f5bf49
			fi
Petr Šabata f5bf49
		else
DistroBaker 5cac7c
			dwarn "$file doesn't exist"
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	done
Petr Šabata f5bf49
Petr Šabata f5bf49
	if [ -n "$modified_files" ]; then
DistroBaker 5cac7c
		dinfo "Detected change(s) in the following file(s): $modified_files"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
DistroBaker a10140
check_drivers_modified()
Petr Šabata f5bf49
{
DistroBaker a10140
	local _target _new_drivers _old_drivers _module_name _module_filename
Petr Šabata f5bf49
DistroBaker a10140
	# If it's dump target is on block device, detect the block driver
DistroBaker a10140
	_target=$(get_block_dump_target)
Petr Šabata f5bf49
	if [[ -n "$_target" ]]; then
DistroBaker a10140
		_record_block_drivers() {
DistroBaker a10140
			local _drivers
DistroBaker a10140
			_drivers=$(udevadm info -a "/dev/block/$1" | sed -n 's/\s*DRIVERS=="\(\S\+\)"/\1/p')
DistroBaker a10140
			for _driver in $_drivers; do
DistroBaker a10140
				if ! [[ " $_new_drivers " == *" $_driver "* ]]; then
DistroBaker a10140
					_new_drivers="$_new_drivers $_driver"
DistroBaker a10140
				fi
DistroBaker a10140
			done
Petr Šabata f5bf49
DistroBaker a10140
			ddebug "MAJ:MIN=$1 drivers='$_drivers'"
DistroBaker a10140
		}
DistroBaker a10140
		check_block_and_slaves_all _record_block_drivers "$(get_maj_min "$_target")"
DistroBaker a10140
	fi
DistroBaker 5cac7c
DistroBaker a10140
	# Include watchdog drivers if watchdog module is not omitted
DistroBaker a10140
	is_dracut_mod_omitted watchdog || _new_drivers+=" $(get_watchdog_drvs)"
DistroBaker a10140
	[ -z "$_new_drivers" ] && return 0
Kairui Song 8e51eb
Kairui Song 8e51eb
	if is_fadump_capable; then
Kairui Song 8e51eb
		_old_drivers="$(lsinitrd "$TARGET_INITRD" -f /usr/lib/dracut/fadump-kernel-modules.txt | tr '\n' ' ')"
Kairui Song 8e51eb
	else
Kairui Song 8e51eb
		_old_drivers="$(lsinitrd "$TARGET_INITRD" -f /usr/lib/dracut/hostonly-kernel-modules.txt | tr '\n' ' ')"
Kairui Song 8e51eb
	fi
Petr Šabata f5bf49
DistroBaker a10140
	ddebug "Modules required for kdump: '$_new_drivers'"
DistroBaker a10140
	ddebug "Modules included in old initramfs: '$_old_drivers'"
DistroBaker a10140
	for _driver in $_new_drivers; do
Petr Šabata f5bf49
		# Skip deprecated/invalid driver name or built-in module
Petr Šabata f5bf49
		_module_name=$(modinfo --set-version "$KDUMP_KERNELVER" -F name $_driver 2>/dev/null)
Petr Šabata f5bf49
		_module_filename=$(modinfo --set-version "$KDUMP_KERNELVER" -n $_driver 2>/dev/null)
Petr Šabata f5bf49
		if [ $? -ne 0 ] || [ -z "$_module_name" ] || [[ "$_module_filename" = *"(builtin)"* ]]; then
Petr Šabata f5bf49
			continue
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
		if ! [[ " $_old_drivers " == *" $_module_name "* ]]; then
DistroBaker 5cac7c
			dinfo "Detected change in block device driver, new loaded module: $_module_name"
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	done
DistroBaker a10140
}
Petr Šabata f5bf49
DistroBaker a10140
check_fs_modified()
DistroBaker a10140
{
DistroBaker a10140
	local _old_dev _old_mntpoint _old_fstype
DistroBaker a10140
	local _new_dev _new_mntpoint _new_fstype
DistroBaker a10140
	local _target _dracut_args
DistroBaker a10140
DistroBaker a10140
	# No need to check in case of mount target specified via "dracut_args".
DistroBaker a10140
	if is_mount_in_dracut_args; then
DistroBaker a10140
		return 0
DistroBaker a10140
	fi
DistroBaker a10140
DistroBaker a10140
	# No need to check in case of raw target.
DistroBaker a10140
	# Currently we do not check also if ssh/nfs target is specified
DistroBaker a10140
	if is_ssh_dump_target || is_nfs_dump_target || is_raw_dump_target; then
DistroBaker a10140
		return 0
DistroBaker a10140
	fi
DistroBaker a10140
DistroBaker a10140
	_target=$(get_block_dump_target)
DistroBaker a10140
	_new_fstype=$(get_fs_type_from_target $_target)
DistroBaker a10140
	if [[ -z "$_target" ]] || [[ -z "$_new_fstype" ]];then
DistroBaker a10140
		derror "Dump target is invalid"
DistroBaker a10140
		return 2
DistroBaker a10140
	fi
DistroBaker a10140
DistroBaker a10140
	ddebug "_target=$_target _new_fstype=$_new_fstype"
DistroBaker a10140
	_new_dev=$(kdump_get_persistent_dev $_target)
DistroBaker a10140
	if [ -z "$_new_dev" ]; then
DistroBaker a10140
		perror "Get persistent device name failed"
DistroBaker a10140
		return 2
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	_new_mntpoint="$(get_kdump_mntpoint_from_target $_target)"
Petr Šabata f5bf49
	_dracut_args=$(lsinitrd $TARGET_INITRD -f usr/lib/dracut/build-parameter.txt)
Petr Šabata f5bf49
	if [[ -z "$_dracut_args" ]];then
DistroBaker 5cac7c
		dwarn "Warning: No dracut arguments found in initrd"
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	# if --mount argument present then match old and new target, mount
Petr Šabata f5bf49
	# point and file system. If any of them mismatches then rebuild
Petr Šabata f5bf49
	echo $_dracut_args | grep "\-\-mount" &> /dev/null
Petr Šabata f5bf49
	if [[ $? -eq 0 ]];then
Petr Šabata f5bf49
		set -- $(echo $_dracut_args | awk -F "--mount '" '{print $2}' | cut -d' ' -f1,2,3)
Petr Šabata f5bf49
		_old_dev=$1
Petr Šabata f5bf49
		_old_mntpoint=$2
Petr Šabata f5bf49
		_old_fstype=$3
Petr Šabata f5bf49
		[[ $_new_dev = $_old_dev && $_new_mntpoint = $_old_mntpoint && $_new_fstype = $_old_fstype ]] && return 0
Petr Šabata f5bf49
	# otherwise rebuild if target device is not a root device
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		[[ "$_target" = "$(get_root_fs_device)" ]] && return 0
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "Detected change in File System"
Petr Šabata f5bf49
	return 1
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
# returns 0 if system is not modified
Petr Šabata f5bf49
# returns 1 if system is modified
Petr Šabata f5bf49
# returns 2 if system modification is invalid
Petr Šabata f5bf49
check_system_modified()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local ret
Petr Šabata f5bf49
Petr Šabata f5bf49
	[[ -f $TARGET_INITRD ]] || return 1
Petr Šabata f5bf49
Petr Šabata f5bf49
	check_files_modified
Petr Šabata f5bf49
	ret=$?
Petr Šabata f5bf49
	if [ $ret -ne 0 ]; then
Petr Šabata f5bf49
		return $ret
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker a10140
	check_fs_modified
Petr Šabata f5bf49
	ret=$?
Petr Šabata f5bf49
	if [ $ret -ne 0 ]; then
Petr Šabata f5bf49
		return $ret
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker a10140
	check_drivers_modified
DistroBaker a10140
	ret=$?
DistroBaker a10140
	if [ $ret -ne 0 ]; then
DistroBaker a10140
		return $ret
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_rebuild()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local capture_capable_initrd="1"
6afe4e
	local force_rebuild force_no_rebuild
Petr Šabata f5bf49
	local ret system_modified="0"
Petr Šabata f5bf49
Petr Šabata f5bf49
	setup_initrd
Petr Šabata f5bf49
Petr Šabata f5bf49
	if [ $? -ne 0 ]; then
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
6afe4e
	force_no_rebuild=$(kdump_get_conf_val force_no_rebuild)
6afe4e
	force_no_rebuild=${force_no_rebuild:-0}
6afe4e
	if [ "$force_no_rebuild" != "0" ] && [ "$force_no_rebuild" != "1" ];then
6afe4e
		derror "Error: force_no_rebuild value is invalid"
6afe4e
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
6afe4e
	force_rebuild=$(kdump_get_conf_val force_rebuild)
6afe4e
	force_rebuild=${force_rebuild:-0}
6afe4e
	if [ "$force_rebuild" != "0" ] && [ "$force_rebuild" != "1" ];then
6afe4e
		derror "Error: force_rebuild value is invalid"
6afe4e
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	if [[ "$force_no_rebuild" == "1" && "$force_rebuild" == "1" ]]; then
DistroBaker 5cac7c
		derror "Error: force_rebuild and force_no_rebuild are enabled simultaneously in kdump.conf"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	# Will not rebuild kdump initrd
Petr Šabata f5bf49
	if [ "$force_no_rebuild" == "1" ]; then
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	#check to see if dependent files has been modified
Petr Šabata f5bf49
	#since last build of the image file
Petr Šabata f5bf49
	if [ -f $TARGET_INITRD ]; then
Petr Šabata f5bf49
		image_time=`stat -c "%Y" $TARGET_INITRD 2>/dev/null`
Petr Šabata f5bf49
Petr Šabata f5bf49
		#in case of fadump mode, check whether the default/target
Petr Šabata f5bf49
		#initrd is already built with dump capture capability
Petr Šabata f5bf49
		if [ "$DEFAULT_DUMP_MODE" == "fadump" ]; then
Kairui Song 96a3fc
			capture_capable_initrd=$(lsinitrd -f $DRACUT_MODULES_FILE $TARGET_INITRD | grep -e ^kdumpbase$ -e ^zz-fadumpinit$ | wc -l)
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	check_system_modified
Petr Šabata f5bf49
	ret=$?
Petr Šabata f5bf49
	if [ $ret -eq 2 ]; then
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	elif [ $ret -eq 1 ];then
Petr Šabata f5bf49
		system_modified="1"
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	if [ $image_time -eq 0 ]; then
DistroBaker 5cac7c
		dinfo "No kdump initial ramdisk found."
Petr Šabata f5bf49
	elif [ "$capture_capable_initrd" == "0" ]; then
DistroBaker 5cac7c
		dinfo "Rebuild $TARGET_INITRD with dump capture support"
Petr Šabata f5bf49
	elif [ "$force_rebuild" != "0" ]; then
DistroBaker 5cac7c
		dinfo "Force rebuild $TARGET_INITRD"
Petr Šabata f5bf49
	elif [ "$system_modified" != "0" ]; then
Petr Šabata f5bf49
		:
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "Rebuilding $TARGET_INITRD"
Petr Šabata f5bf49
	rebuild_initrd
Petr Šabata f5bf49
	return $?
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
# Load the kdump kernel specified in /etc/sysconfig/kdump
Petr Šabata f5bf49
# If none is specified, try to load a kdump kernel with the same version
Petr Šabata f5bf49
# as the currently running kernel.
Petr Šabata f5bf49
load_kdump()
Petr Šabata f5bf49
{
DistroBaker 5cac7c
	local ret
DistroBaker 5cac7c
Petr Šabata f5bf49
	KEXEC_ARGS=$(prepare_kexec_args "${KEXEC_ARGS}")
Petr Šabata f5bf49
	KDUMP_COMMANDLINE=$(prepare_cmdline "${KDUMP_COMMANDLINE}" "${KDUMP_COMMANDLINE_REMOVE}" "${KDUMP_COMMANDLINE_APPEND}")
Petr Šabata f5bf49
Petr Šabata f5bf49
	# For secureboot enabled machines, use new kexec file based syscall.
Petr Šabata f5bf49
	# Old syscall will always fail as it does not have capability to
Petr Šabata f5bf49
	# to kernel signature verification.
Petr Šabata f5bf49
	if is_secure_boot_enforced; then
DistroBaker 5cac7c
		dinfo "Secure Boot is enabled. Using kexec file based syscall."
Petr Šabata f5bf49
		KEXEC_ARGS="$KEXEC_ARGS -s"
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	ddebug "$KEXEC $KEXEC_ARGS $standard_kexec_args --command-line=$KDUMP_COMMANDLINE --initrd=$TARGET_INITRD $KDUMP_KERNEL"
DistroBaker 5cac7c
DistroBaker 17a515
	# The '12' represents an intermediate temporary file descriptor
DistroBaker 17a515
	# to store the standard error file descriptor '2', and later
DistroBaker 17a515
	# restore the error file descriptor with the file descriptor '12'
DistroBaker 17a515
	# and release it.
DistroBaker 5cac7c
	exec 12>&2
DistroBaker 5cac7c
	exec 2>> $KDUMP_LOG_PATH/kdump.log
DistroBaker 5cac7c
	PS4='+ $(date "+%Y-%m-%d %H:%M:%S") ${BASH_SOURCE}@${LINENO}: '
DistroBaker 5cac7c
	set -x
DistroBaker 5cac7c
Petr Šabata f5bf49
	$KEXEC $KEXEC_ARGS $standard_kexec_args \
Petr Šabata f5bf49
		--command-line="$KDUMP_COMMANDLINE" \
Petr Šabata f5bf49
		--initrd=$TARGET_INITRD $KDUMP_KERNEL
DistroBaker 5cac7c
DistroBaker 5cac7c
	ret=$?
DistroBaker 5cac7c
	set +x
DistroBaker 5cac7c
	exec 2>&12 12>&-
DistroBaker 5cac7c
DistroBaker 5cac7c
	if [ $ret == 0 ]; then
DistroBaker 5cac7c
		dinfo "kexec: loaded kdump kernel"
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	else
DistroBaker 5cac7c
		derror "kexec: failed to load kdump kernel"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_ssh_config()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	while read config_opt config_val; do
Petr Šabata f5bf49
		case "$config_opt" in
Petr Šabata f5bf49
		sshkey)
Petr Šabata f5bf49
			# remove inline comments after the end of a directive.
Petr Šabata f5bf49
			if [ -f "$config_val" ]; then
Petr Šabata f5bf49
				# canonicalize the path
Petr Šabata f5bf49
				SSH_KEY_LOCATION=$(/usr/bin/readlink -m $config_val)
Petr Šabata f5bf49
			else
DistroBaker 5cac7c
				dwarn "WARNING: '$config_val' doesn't exist, using default value '$SSH_KEY_LOCATION'"
Petr Šabata f5bf49
			fi
Petr Šabata f5bf49
			;;
Petr Šabata f5bf49
		path)
Petr Šabata f5bf49
			SAVE_PATH=$config_val
Petr Šabata f5bf49
			;;
Petr Šabata f5bf49
		ssh)
Petr Šabata f5bf49
			DUMP_TARGET=$config_val
Petr Šabata f5bf49
			;;
Petr Šabata f5bf49
		*)
Petr Šabata f5bf49
			;;
Petr Šabata f5bf49
		esac
67b8dd
	done <<< "$(kdump_read_conf)"
Petr Šabata f5bf49
Petr Šabata f5bf49
	#make sure they've configured kdump.conf for ssh dumps
Petr Šabata f5bf49
	local SSH_TARGET=`echo -n $DUMP_TARGET | sed -n '/.*@/p'`
Petr Šabata f5bf49
	if [ -z "$SSH_TARGET" ]; then
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
# ipv6 host address may takes a long time to be ready.
Petr Šabata f5bf49
# Instead of checking against ipv6 address, we just check the network reachable
Petr Šabata f5bf49
# by the return val of 'ssh'
Petr Šabata f5bf49
check_and_wait_network_ready()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local start_time=$(date +%s)
Petr Šabata f5bf49
	local warn_once=1
Petr Šabata f5bf49
	local cur
Petr Šabata f5bf49
	local diff
Petr Šabata f5bf49
	local retval
Petr Šabata f5bf49
	local errmsg
Petr Šabata f5bf49
Petr Šabata f5bf49
	while true; do
Petr Šabata f5bf49
		errmsg=$(ssh -i $SSH_KEY_LOCATION -o BatchMode=yes $DUMP_TARGET mkdir -p $SAVE_PATH 2>&1)
Petr Šabata f5bf49
		retval=$?
Petr Šabata f5bf49
Petr Šabata f5bf49
		# ssh exits with the exit status of the remote command or with 255 if an error occurred
Petr Šabata f5bf49
		if [ $retval -eq 0 ]; then
Petr Šabata f5bf49
			return 0
Petr Šabata f5bf49
		elif [ $retval -ne 255 ]; then
DistroBaker 5cac7c
			derror "Could not create $DUMP_TARGET:$SAVE_PATH, you should check the privilege on server side"
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
Petr Šabata f5bf49
		# if server removes the authorized_keys or, no /root/.ssh/kdump_id_rsa
DistroBaker 5cac7c
		ddebug "$errmsg"
DistroBaker 5cac7c
		echo $errmsg | grep -q "Permission denied\|No such file or directory\|Host key verification failed" &> /dev/null
Petr Šabata f5bf49
		if [ $? -eq 0 ]; then
DistroBaker 5cac7c
			derror "Could not create $DUMP_TARGET:$SAVE_PATH, you probably need to run \"kdumpctl propagate\""
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
Petr Šabata f5bf49
		if [ $warn_once -eq 1 ]; then
DistroBaker 5cac7c
			dwarn "Network dump target is not usable, waiting for it to be ready..."
Petr Šabata f5bf49
			warn_once=0
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
Petr Šabata f5bf49
		cur=$(date +%s)
Petr Šabata f5bf49
		let "diff = $cur - $start_time"
Petr Šabata f5bf49
		# 60s time out
Petr Šabata f5bf49
		if [ $diff -gt 180 ]; then
Petr Šabata f5bf49
			break;
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
		sleep 1
Petr Šabata f5bf49
	done
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "Could not create $DUMP_TARGET:$SAVE_PATH, ipaddr is not ready yet. You should check network connection"
Petr Šabata f5bf49
	return 1
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_ssh_target()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	check_and_wait_network_ready
Petr Šabata f5bf49
	if [ $? -ne 0 ]; then
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
propagate_ssh_key()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	check_ssh_config
Petr Šabata f5bf49
	if [ $? -ne 0 ]; then
DistroBaker 5cac7c
		derror "No ssh config specified in $KDUMP_CONFIG_FILE.  Can't propagate"
Petr Šabata f5bf49
		exit 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	local KEYFILE=$SSH_KEY_LOCATION
Petr Šabata f5bf49
	local errmsg="Failed to propagate ssh key"
Petr Šabata f5bf49
Petr Šabata f5bf49
	#Check to see if we already created key, if not, create it.
Petr Šabata f5bf49
	if [ -f $KEYFILE ]; then
DistroBaker 5cac7c
		dinfo "Using existing keys..."
Petr Šabata f5bf49
	else
DistroBaker 5cac7c
		dinfo "Generating new ssh keys... "
Petr Šabata f5bf49
		/usr/bin/ssh-keygen -t rsa -f $KEYFILE -N "" 2>&1 > /dev/null
DistroBaker 5cac7c
		dinfo "done."
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	#now find the target ssh user and server to contact.
Petr Šabata f5bf49
	SSH_USER=`echo $DUMP_TARGET | cut -d\  -f2 | cut -d@ -f1`
Petr Šabata f5bf49
	SSH_SERVER=`echo $DUMP_TARGET | sed -e's/\(.*@\)\(.*$\)/\2/'`
Petr Šabata f5bf49
Petr Šabata f5bf49
	#now send the found key to the found server
Petr Šabata f5bf49
	ssh-copy-id -i $KEYFILE $SSH_USER@$SSH_SERVER
Petr Šabata f5bf49
	RET=$?
Petr Šabata f5bf49
	if [ $RET == 0 ]; then
DistroBaker 5cac7c
		dinfo "$KEYFILE has been added to ~$SSH_USER/.ssh/authorized_keys on $SSH_SERVER"
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	else
DistroBaker 5cac7c
		derror "$errmsg, $KEYFILE failed in transfer to $SSH_SERVER"
Petr Šabata f5bf49
		exit 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
show_reserved_mem()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
    local mem=$(cat /sys/kernel/kexec_crash_size)
Petr Šabata f5bf49
    local mem_mb=$(expr $mem / 1024 / 1024)
Petr Šabata f5bf49
DistroBaker 5cac7c
    dinfo "Reserved "$mem_mb"MB memory for crash kernel"
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_current_fadump_status()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	# Check if firmware-assisted dump has been registered.
Petr Šabata f5bf49
	rc=`cat $FADUMP_REGISTER_SYS_NODE`
Petr Šabata f5bf49
	[ $rc -eq 1 ] && return 0
Petr Šabata f5bf49
	return 1
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_current_status()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	if [ $DEFAULT_DUMP_MODE == "fadump" ]; then
Petr Šabata f5bf49
		check_current_fadump_status
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		check_current_kdump_status
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	return $?
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
save_raw()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local kdump_dir
Petr Šabata f5bf49
	local raw_target
Petr Šabata f5bf49
6afe4e
	raw_target=$(kdump_get_conf_val raw)
Petr Šabata f5bf49
	[ -z "$raw_target" ] && return 0
Petr Šabata f5bf49
	[ -b "$raw_target" ] || {
DistroBaker 5cac7c
		derror "raw partition $raw_target not found"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	}
Petr Šabata f5bf49
	check_fs=$(lsblk --nodeps -npo FSTYPE $raw_target)
Petr Šabata f5bf49
	if [[ $(echo $check_fs | wc -w) -ne 0 ]]; then
DistroBaker 5cac7c
		dwarn "Warning: Detected '$check_fs' signature on $raw_target, data loss is expected."
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	fi
6afe4e
	kdump_dir=$(kdump_get_conf_val path)
Petr Šabata f5bf49
	if [ -z "${kdump_dir}" ]; then
Petr Šabata f5bf49
		coredir="/var/crash/`date +"%Y-%m-%d-%H:%M"`"
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		coredir="${kdump_dir}/`date +"%Y-%m-%d-%H:%M"`"
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	mkdir -p "$coredir"
Petr Šabata f5bf49
	[ -d "$coredir" ] || {
DistroBaker 5cac7c
		derror "failed to create $coredir"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	}
Petr Šabata f5bf49
	if makedumpfile -R $coredir/vmcore <$raw_target >/dev/null 2>&1; then
Petr Šabata f5bf49
		# dump found
DistroBaker 5cac7c
		dinfo "Dump saved to $coredir/vmcore"
Petr Šabata f5bf49
		# wipe makedumpfile header
Petr Šabata f5bf49
		dd if=/dev/zero of=$raw_target bs=1b count=1 2>/dev/null
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		rm -rf "$coredir"
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
local_fs_dump_target()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local _target
Petr Šabata f5bf49
Petr Šabata f5bf49
	_target=$(egrep "^ext[234]|^xfs|^btrfs|^minix" /etc/kdump.conf)
Petr Šabata f5bf49
	if [ $? -eq 0 ]; then
Petr Šabata f5bf49
		echo $_target|awk '{print $2}'
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
path_to_be_relabeled()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local _path _target _mnt="/" _rmnt
Petr Šabata f5bf49
Petr Šabata f5bf49
	if is_user_configured_dump_target; then
Petr Šabata f5bf49
		if is_mount_in_dracut_args; then
Petr Šabata f5bf49
		    return;
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
Petr Šabata f5bf49
		_target=$(local_fs_dump_target)
Petr Šabata f5bf49
		if [[ -n "$_target" ]]; then
Petr Šabata f5bf49
			_mnt=$(get_mntpoint_from_target $_target)
Petr Šabata f5bf49
			if ! is_mounted "$_mnt"; then
Petr Šabata f5bf49
				return
Petr Šabata f5bf49
			fi
Petr Šabata f5bf49
		else
Petr Šabata f5bf49
			return
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	_path=$(get_save_path)
Petr Šabata f5bf49
	# if $_path is masked by other mount, we will not relabel it.
Petr Šabata f5bf49
	_rmnt=$(df $_mnt/$_path 2>/dev/null | tail -1 | awk '{ print $NF }')
Petr Šabata f5bf49
	if [ "$_rmnt" == "$_mnt" ]; then
Petr Šabata f5bf49
		echo $_mnt/$_path
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
selinux_relabel()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local _path _i _attr
Petr Šabata f5bf49
Petr Šabata f5bf49
	_path=$(path_to_be_relabeled)
Petr Šabata f5bf49
	if [ -z "$_path" ] || ! [ -d "$_path" ] ; then
Petr Šabata f5bf49
		return
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	for _i in $(find $_path); do
Petr Šabata f5bf49
		_attr=$(getfattr -m "security.selinux" $_i 2>/dev/null)
Petr Šabata f5bf49
		if [ -z "$_attr" ]; then
Petr Šabata f5bf49
			restorecon $_i;
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	done
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_fence_kdump_config()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local hostname=`hostname`
Petr Šabata f5bf49
	local ipaddrs=`hostname -I`
14205c
	local nodes=$(kdump_get_conf_val "fence_kdump_nodes")
Petr Šabata f5bf49
Petr Šabata f5bf49
	for node in $nodes; do
Petr Šabata f5bf49
		if [ "$node" = "$hostname" ]; then
DistroBaker 5cac7c
			derror "Option fence_kdump_nodes cannot contain $hostname"
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
		# node can be ipaddr
DistroBaker 633317
		echo "$ipaddrs " | grep "$node " > /dev/null
Petr Šabata f5bf49
		if [ $? -eq 0 ]; then
DistroBaker 5cac7c
			derror "Option fence_kdump_nodes cannot contain $node"
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	done
Petr Šabata f5bf49
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_dump_feasibility()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	if [ $DEFAULT_DUMP_MODE == "fadump" ]; then
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	check_kdump_feasibility
Petr Šabata f5bf49
	return $?
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
start_fadump()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	echo 1 > $FADUMP_REGISTER_SYS_NODE
Petr Šabata f5bf49
	if ! check_current_fadump_status; then
DistroBaker 5cac7c
		derror "fadump: failed to register"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "fadump: registered successfully"
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
start_dump()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	if [ $DEFAULT_DUMP_MODE == "fadump" ]; then
Petr Šabata f5bf49
		start_fadump
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		load_kdump
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	return $?
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_failure_action_config()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local default_option
Petr Šabata f5bf49
	local failure_action
Petr Šabata f5bf49
	local option="failure_action"
Petr Šabata f5bf49
6afe4e
	default_option=$(kdump_get_conf_val default)
6afe4e
	failure_action=$(kdump_get_conf_val failure_action)
Petr Šabata f5bf49
Petr Šabata f5bf49
	if [ -z "$failure_action" -a -z "$default_option" ]; then
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	elif [ -n "$failure_action" -a -n "$default_option" ]; then
DistroBaker 5cac7c
		derror "Cannot specify 'failure_action' and 'default' option together"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	if [ -n "$default_option" ]; then
Petr Šabata f5bf49
		option="default"
Petr Šabata f5bf49
		failure_action="$default_option"
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	case "$failure_action" in
Petr Šabata f5bf49
	  reboot|halt|poweroff|shell|dump_to_rootfs)
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	  ;;
Petr Šabata f5bf49
	  *)
DistroBaker 5cac7c
		dinfo $"Usage kdump.conf: $option {reboot|halt|poweroff|shell|dump_to_rootfs}"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	esac
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
check_final_action_config()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	local final_action
Petr Šabata f5bf49
6afe4e
	final_action=$(kdump_get_conf_val final_action)
Petr Šabata f5bf49
	if [ -z "$final_action" ]; then
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		case "$final_action" in
Petr Šabata f5bf49
		  reboot|halt|poweroff)
Petr Šabata f5bf49
			return 0
Petr Šabata f5bf49
		  ;;
Petr Šabata f5bf49
		  *)
DistroBaker 5cac7c
			dinfo $"Usage kdump.conf: final_action {reboot|halt|poweroff}"
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
		esac
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
start()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	check_dump_feasibility
Petr Šabata f5bf49
	if [ $? -ne 0 ]; then
DistroBaker 5cac7c
		derror "Starting kdump: [FAILED]"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	check_config
Petr Šabata f5bf49
	if [ $? -ne 0 ]; then
DistroBaker 5cac7c
		derror "Starting kdump: [FAILED]"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	if sestatus 2>/dev/null | grep -q "SELinux status.*enabled"; then
Petr Šabata f5bf49
		selinux_relabel
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	save_raw
Petr Šabata f5bf49
	if [ $? -ne 0 ]; then
DistroBaker 5cac7c
		derror "Starting kdump: [FAILED]"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	check_current_status
Petr Šabata f5bf49
	if [ $? == 0 ]; then
DistroBaker 5cac7c
		dwarn "Kdump already running: [WARNING]"
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	if check_ssh_config; then
Petr Šabata f5bf49
		if ! check_ssh_target; then
DistroBaker 5cac7c
			derror "Starting kdump: [FAILED]"
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	check_rebuild
Petr Šabata f5bf49
	if [ $? != 0 ]; then
DistroBaker 5cac7c
		derror "Starting kdump: [FAILED]"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	start_dump
Petr Šabata f5bf49
	if [ $? != 0 ]; then
DistroBaker 5cac7c
		derror "Starting kdump: [FAILED]"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "Starting kdump: [OK]"
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
reload()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	check_current_status
Petr Šabata f5bf49
	if [ $? -ne 0 ]; then
DistroBaker 5cac7c
		dwarn "Kdump was not running: [WARNING]"
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	if [ $DEFAULT_DUMP_MODE == "fadump" ]; then
Petr Šabata f5bf49
		reload_fadump
Petr Šabata f5bf49
		return $?
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		stop_kdump
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	if [ $? -ne 0 ]; then
DistroBaker 5cac7c
		derror "Stopping kdump: [FAILED]"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "Stopping kdump: [OK]"
Petr Šabata f5bf49
Petr Šabata f5bf49
	setup_initrd
Petr Šabata f5bf49
	if [ $? -ne 0 ]; then
DistroBaker 5cac7c
		derror "Starting kdump: [FAILED]"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	start_dump
Petr Šabata f5bf49
	if [ $? -ne 0 ]; then
DistroBaker 5cac7c
		derror "Starting kdump: [FAILED]"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "Starting kdump: [OK]"
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
stop_fadump()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	echo 0 > $FADUMP_REGISTER_SYS_NODE
Petr Šabata f5bf49
	if check_current_fadump_status; then
DistroBaker 5cac7c
		derror "fadump: failed to unregister"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "fadump: unregistered successfully"
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
stop_kdump()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	if is_secure_boot_enforced; then
Petr Šabata f5bf49
		$KEXEC -s -p -u
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		$KEXEC -p -u
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	if [ $? != 0 ]; then
DistroBaker 5cac7c
		derror "kexec: failed to unload kdump kernel"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "kexec: unloaded kdump kernel"
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
reload_fadump()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	echo 1 > $FADUMP_REGISTER_SYS_NODE
Petr Šabata f5bf49
	if [ $? == 0 ]; then
DistroBaker 5cac7c
		dinfo "fadump: re-registered successfully"
Petr Šabata f5bf49
		return 0
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		# FADump could fail on older kernel where re-register
Petr Šabata f5bf49
		# support is not enabled. Try stop/start from userspace
Petr Šabata f5bf49
		# to handle such scenario.
Petr Šabata f5bf49
		stop_fadump
Petr Šabata f5bf49
		if [ $? == 0 ]; then
Petr Šabata f5bf49
			start_fadump
Petr Šabata f5bf49
			return $?
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	return 1
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
stop()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	if [ $DEFAULT_DUMP_MODE == "fadump" ]; then
Petr Šabata f5bf49
		stop_fadump
Petr Šabata f5bf49
	else
Petr Šabata f5bf49
		stop_kdump
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	if [ $? != 0 ]; then
DistroBaker 5cac7c
		derror "Stopping kdump: [FAILED]"
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "Stopping kdump: [OK]"
Petr Šabata f5bf49
	return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
rebuild() {
Petr Šabata f5bf49
	check_config
Petr Šabata f5bf49
	if [ $? -ne 0 ]; then
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	if check_ssh_config; then
Petr Šabata f5bf49
		if ! check_ssh_target; then
Petr Šabata f5bf49
			return 1
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
Petr Šabata f5bf49
	setup_initrd
Petr Šabata f5bf49
	if [ $? -ne 0 ]; then
Petr Šabata f5bf49
		return 1
Petr Šabata f5bf49
	fi
Petr Šabata f5bf49
DistroBaker 5cac7c
	dinfo "Rebuilding $TARGET_INITRD"
Petr Šabata f5bf49
	rebuild_initrd
Petr Šabata f5bf49
	return $?
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Kairui Song a9fda5
do_estimate() {
Kairui Song a9fda5
	local kdump_mods
Kairui Song a9fda5
	local -A large_mods
Kairui Song a9fda5
	local baseline
Kairui Song 6cc04b
	local kernel_size mod_size initrd_size baseline_size runtime_size reserved_size estimated_size recommended_size
Kairui Song a9fda5
	local size_mb=$(( 1024 * 1024 ))
Kairui Song a9fda5
Kairui Song a9fda5
	setup_initrd
Kairui Song a9fda5
	if [ ! -f "$TARGET_INITRD" ]; then
Kairui Song a9fda5
		derror "kdumpctl estimate: kdump initramfs is not built yet."
Kairui Song a9fda5
		exit 1
Kairui Song a9fda5
	fi
Kairui Song a9fda5
Kairui Song a9fda5
	kdump_mods="$(lsinitrd "$TARGET_INITRD" -f /usr/lib/dracut/hostonly-kernel-modules.txt | tr '\n' ' ')"
Kairui Song a9fda5
	baseline=$(kdump_get_arch_recommend_size)
Kairui Song a9fda5
	if [[ "${baseline: -1}" == "M" ]]; then
Kairui Song a9fda5
		baseline=${baseline%M}
Kairui Song a9fda5
	elif [[ "${baseline: -1}" == "G" ]]; then
Kairui Song a9fda5
		baseline=$(( ${baseline%G} * 1024 ))
Kairui Song a9fda5
	elif [[ "${baseline: -1}" == "T" ]]; then
Kairui Song a9fda5
		baseline=$(( ${baseline%Y} * 1048576 ))
Kairui Song a9fda5
	fi
Kairui Song a9fda5
Kairui Song f3db4a
	# The default pre-reserved crashkernel value
Kairui Song a9fda5
	baseline_size=$((baseline * size_mb))
Kairui Song a9fda5
	# Current reserved crashkernel size
Kairui Song a9fda5
	reserved_size=$(cat /sys/kernel/kexec_crash_size)
Kairui Song a9fda5
	# A pre-estimated value for userspace usage and kernel
Kairui Song a9fda5
	# runtime allocation, 64M should good for most cases
Kairui Song a9fda5
	runtime_size=$((64 * size_mb))
Kairui Song a9fda5
	# Kernel image size
Kairui Song a9fda5
	kernel_size=$(get_kernel_size "$KDUMP_KERNEL")
Kairui Song a9fda5
	# Kdump initramfs size
Kairui Song a9fda5
	initrd_size=$(du -b "$TARGET_INITRD" | awk '{print $1}')
Kairui Song a9fda5
	# Kernel modules static size after loaded
Kairui Song a9fda5
	mod_size=0
Kairui Song a9fda5
	while read -r _name _size _; do
Kairui Song a9fda5
		if [[ ! " $kdump_mods " == *" $_name "* ]]; then
Kairui Song a9fda5
			continue
Kairui Song a9fda5
		fi
Kairui Song a9fda5
		mod_size=$((mod_size + _size))
Kairui Song a9fda5
Kairui Song a9fda5
		# Mark module with static size larger than 2M as large module
Kairui Song a9fda5
		if [[ $((_size / size_mb)) -ge 1 ]]; then
Kairui Song a9fda5
			large_mods[$_name]=$_size
Kairui Song a9fda5
		fi
Kairui Song a9fda5
	done <<< "$(< /proc/modules)"
Kairui Song a9fda5
Kairui Song a9fda5
	# Extra memory usage required for LUKS2 decryption
Kairui Song a9fda5
	crypt_size=0
Kairui Song a9fda5
	for _dev in $(get_all_kdump_crypt_dev); do
Kairui Song a9fda5
		_crypt_info=$(cryptsetup luksDump "/dev/block/$_dev")
Kairui Song a9fda5
		[[ $(echo "$_crypt_info" | sed -n "s/^Version:\s*\(.*\)/\1/p" ) == "2" ]] || continue
Kairui Song a9fda5
		for _mem in $(echo "$_crypt_info" | sed -n "s/\sMemory:\s*\(.*\)/\1/p" | sort -n ); do
Kairui Song a9fda5
			crypt_size=$((crypt_size + _mem * 1024))
Kairui Song a9fda5
			break
Kairui Song a9fda5
		done
Kairui Song a9fda5
	done
Kairui Song a9fda5
	[[ $crypt_size -ne 0 ]] && echo -e "Encrypted kdump target requires extra memory, assuming using the keyslot with minimun memory requirement\n"
Kairui Song a9fda5
Kairui Song a9fda5
	estimated_size=$((kernel_size + mod_size + initrd_size + runtime_size + crypt_size))
Kairui Song a9fda5
	if [[ $baseline_size -gt $estimated_size ]]; then
Kairui Song 6cc04b
		recommended_size=$baseline_size
Kairui Song a9fda5
	else
Kairui Song 6cc04b
		recommended_size=$estimated_size
Kairui Song a9fda5
	fi
Kairui Song a9fda5
Kairui Song a9fda5
	echo "Reserved crashkernel:    $((reserved_size / size_mb))M"
Kairui Song 6cc04b
	echo "Recommended crashkernel: $((recommended_size / size_mb))M"
Kairui Song a9fda5
	echo
Kairui Song a9fda5
	echo "Kernel image size:   $((kernel_size / size_mb))M"
Kairui Song a9fda5
	echo "Kernel modules size: $((mod_size / size_mb))M"
Kairui Song a9fda5
	echo "Initramfs size:      $((initrd_size / size_mb))M"
Kairui Song a9fda5
	echo "Runtime reservation: $((runtime_size / size_mb))M"
Kairui Song a9fda5
	[[ $crypt_size -ne 0 ]] && \
Kairui Song a9fda5
	echo "LUKS required size:  $((crypt_size / size_mb))M"
Kairui Song a9fda5
	echo -n "Large modules:"
Kairui Song a9fda5
	if [[ "${#large_mods[@]}" -eq 0 ]]; then
Kairui Song a9fda5
		echo " <none>"
Kairui Song a9fda5
	else
Kairui Song a9fda5
		echo ""
Kairui Song a9fda5
		for _mod in "${!large_mods[@]}"; do
Kairui Song a9fda5
			echo "    $_mod: ${large_mods[$_mod]}"
Kairui Song a9fda5
		done
Kairui Song a9fda5
	fi
Kairui Song a9fda5
Kairui Song 6cc04b
	if [[ $reserved_size -lt $recommended_size ]]; then
Kairui Song 6cc04b
		echo "WARNING: Current crashkernel size is lower than recommended size $((recommended_size / size_mb))M."
Kairui Song a9fda5
	fi
Kairui Song a9fda5
}
Kairui Song a9fda5
Kairui Song a0fe51
reset_crashkernel() {
Kairui Song a0fe51
	local kernel=$1 entry crashkernel_default
Kairui Song a0fe51
	local grub_etc_default="/etc/default/grub"
Kairui Song a0fe51
Kairui Song a0fe51
	[[ -z "$kernel" ]] && kernel=$(uname -r)
Kairui Song a0fe51
	crashkernel_default=$(cat "/usr/lib/modules/$kernel/crashkernel.default" 2>/dev/null)
Kairui Song a0fe51
Kairui Song a0fe51
	if [[ -z "$crashkernel_default" ]]; then
Kairui Song a0fe51
		derror "$kernel doesn't have a crashkernel.default"
Kairui Song a0fe51
		exit 1
Kairui Song a0fe51
	fi
Kairui Song a0fe51
Kairui Song a0fe51
	if is_atomic; then
Kairui Song a0fe51
		if rpm-ostree kargs | grep -q "crashkernel="; then
Kairui Song a0fe51
			rpm-ostree --replace="crashkernel=$crashkernel_default"
Kairui Song a0fe51
		else
Kairui Song a0fe51
			rpm-ostree --append="crashkernel=$crashkernel_default"
Kairui Song a0fe51
		fi
Kairui Song a0fe51
	else
Kairui Song a0fe51
		entry=$(grubby --info ALL | grep "^kernel=.*$kernel")
Kairui Song a0fe51
		entry=${entry#kernel=}
Kairui Song a0fe51
		entry=${entry#\"}
Kairui Song a0fe51
		entry=${entry%\"}
Kairui Song a0fe51
Kairui Song a0fe51
		if [[ -f "$grub_etc_default" ]]; then
Kairui Song a0fe51
			sed -i -e "s/^\(GRUB_CMDLINE_LINUX=.*\)crashkernel=[^\ \"]*\([\ \"].*\)$/\1$crashkernel_default\2/" "$grub_etc_default"
Kairui Song a0fe51
		fi
Kairui Song a0fe51
Kairui Song a0fe51
		[[ -f /etc/zipl.conf ]] && zipl_arg="--zipl"
Kairui Song a0fe51
		grubby --args "$crashkernel_default" --update-kernel "$entry" $zipl_arg
Kairui Song a0fe51
		[[ $zipl_arg ]] && zipl > /dev/null
Kairui Song a0fe51
	fi
67b8dd
}
Kairui Song a0fe51
Petr Šabata f5bf49
if [ ! -f "$KDUMP_CONFIG_FILE" ]; then
DistroBaker 5cac7c
	derror "Error: No kdump config file found!"
Petr Šabata f5bf49
	exit 1
Petr Šabata f5bf49
fi
Petr Šabata f5bf49
Petr Šabata f5bf49
main ()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
	# Determine if the dump mode is kdump or fadump
Petr Šabata f5bf49
	determine_dump_mode
Petr Šabata f5bf49
Petr Šabata f5bf49
	case "$1" in
Petr Šabata f5bf49
	  start)
Petr Šabata f5bf49
		if [ -s /proc/vmcore ]; then
Petr Šabata f5bf49
			save_core
Petr Šabata f5bf49
			reboot
Petr Šabata f5bf49
		else
Petr Šabata f5bf49
			start
Petr Šabata f5bf49
		fi
Petr Šabata f5bf49
		;;
Petr Šabata f5bf49
	  stop)
Petr Šabata f5bf49
		stop
Petr Šabata f5bf49
		;;
Petr Šabata f5bf49
	  status)
Petr Šabata f5bf49
		EXIT_CODE=0
Petr Šabata f5bf49
		check_current_status
Petr Šabata f5bf49
		case "$?" in
Petr Šabata f5bf49
		  0)
DistroBaker 5cac7c
			dinfo "Kdump is operational"
Petr Šabata f5bf49
			EXIT_CODE=0
Petr Šabata f5bf49
			;;
Petr Šabata f5bf49
		  1)
DistroBaker 5cac7c
			dinfo "Kdump is not operational"
Petr Šabata f5bf49
			EXIT_CODE=3
Petr Šabata f5bf49
			;;
Petr Šabata f5bf49
		esac
Petr Šabata f5bf49
		exit $EXIT_CODE
Petr Šabata f5bf49
		;;
Petr Šabata f5bf49
	  reload)
Petr Šabata f5bf49
		reload
Petr Šabata f5bf49
		;;
Petr Šabata f5bf49
	  restart)
Petr Šabata f5bf49
		stop
Petr Šabata f5bf49
		start
Petr Šabata f5bf49
		;;
Petr Šabata f5bf49
	  rebuild)
Petr Šabata f5bf49
		rebuild
Petr Šabata f5bf49
		;;
Petr Šabata f5bf49
	  condrestart)
Petr Šabata f5bf49
		;;
Petr Šabata f5bf49
	  propagate)
Petr Šabata f5bf49
		propagate_ssh_key
Petr Šabata f5bf49
		;;
Petr Šabata f5bf49
	  showmem)
Petr Šabata f5bf49
		show_reserved_mem
Petr Šabata f5bf49
		;;
Kairui Song a9fda5
	  estimate)
Kairui Song a9fda5
		do_estimate
Kairui Song a9fda5
		;;
Kairui Song a0fe51
	  reset-crashkernel)
Kairui Song a0fe51
		reset_crashkernel "$2"
Kairui Song a0fe51
		;;
Petr Šabata f5bf49
	  *)
Kairui Song a0fe51
		dinfo $"Usage: $0 {estimate|start|stop|status|restart|reload|rebuild|reset-crashkernel|propagate|showmem}"
Petr Šabata f5bf49
		exit 1
Petr Šabata f5bf49
	esac
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
# Other kdumpctl instances will block in queue, until this one exits
Petr Šabata f5bf49
single_instance_lock
Petr Šabata f5bf49
Petr Šabata f5bf49
# To avoid fd 9 leaking, we invoke a subshell, close fd 9 and call main.
Petr Šabata f5bf49
# So that fd isn't leaking when main is invoking a subshell.
Kairui Song a0fe51
(exec 9<&-; main "$@")
Petr Šabata f5bf49
Petr Šabata f5bf49
exit $?