#! /bin/bash

# chkconfig: 2345 01 80
# description: configures the crash dump kernel

. /etc/init.d/functions

KEXEC=/sbin/kexec
KDUMP=/usr/lib/xen/bin/kdump

if [ ! -x $KEXEC ] ; then
    exit 0
fi

if [ -f /etc/sysconfig/kdump ]; then
    . /etc/sysconfig/kdump
fi

crash_dump()
{
    eval $(cat /proc/cmdline | awk 'BEGIN { RS=" " } /^kdump-/ { gsub("kdump-","") ; print }')

    if test -z $KDUMP_DUMPS_NUM || (test $KDUMP_DUMPS_NUM && test $KDUMP_DUMPS_NUM -gt "`ls -l /var/crash | grep -e "^d" | wc -l`")
    then
        echo -n $"Saving crash dump: "
        if [ -x $KDUMP ] ; then
            dir=${KDUMP_DIR:-/var/crash}/$(date  +%Y%m%d-%H%M%S-%Z)
            echo -n "$dir "
    
            if [ -f /proc/sys/kernel/core_pattern ] ; then
                old_core_pattern=$(cat /proc/sys/kernel/core_pattern)
                echo "$dir/core.%e.%p" > /proc/sys/kernel/core_pattern
                ulimit -c 16384 # 16M
            fi
    
            if [ -z "${KDUMP_OPTIONS}" ] ; then
                . /etc/xensource-inventory
                KDUMP_OPTIONS="--maxi"
                if [ -n "${xenversion}" -a -f "/boot/xen-${xenversion}.map" ] ; then
                    KDUMP_OPTIONS="$KDUMP_OPTIONS --symbol-table=/boot/xen-${xenversion}.map"
                elif [ -n "${XEN_VERSION}" -a -f "/boot/xen-${XEN_VERSION}.map" ] ; then
                    KDUMP_OPTIONS="$KDUMP_OPTIONS --symbol-table=/boot/xen-${XEN_VERSION}.map"
                fi
    
                if [ -n "${linuxversion}" -a -f "/boot/System.map-${linuxversion}" ] ; then
                    KDUMP_OPTIONS="$KDUMP_OPTIONS --symbol-table=0=/boot/System.map-${linuxversion}"
                elif [ -n "${KERNEL_VERSION}" -a -f "/boot/System.map-${KERNEL_VERSION}" ] ; then
                    KDUMP_OPTIONS="$KDUMP_OPTIONS --symbol-table=0=/boot/System.map-${KERNEL_VERSION}"
                fi
            fi
    
            if $KDUMP ${KDUMP_OPTIONS} --output "$dir" ; then
                success
            else
                failure
            fi
    
            if [ -f /proc/sys/kernel/core_pattern ] ; then
                echo "$old_core_pattern" > /proc/sys/kernel/core_pattern
            fi
    
        else
            echo -n "$KDUMP unavailable"
            failure
        fi
    
        echo
    fi

    if [ ${KDUMP_REBOOT:-yes} == "yes" ] ; then
        reboot -f
    fi
}

setup_kdump()
{
    if [ -d "/sys/hypervisor/version/" ] ; then
	xen_major=$(cat /sys/hypervisor/version/major)
	xen_minor=$(cat /sys/hypervisor/version/minor)
	xen_extra=$(cat /sys/hypervisor/version/extra)
	xen_version="${xen_major}.${xen_minor}${xen_extra}"
    fi

    linux_version=$(uname -r)

    if [ -z "$KDUMP_KERNEL_VERSION" ] ; then
	KDUMP_KERNEL_VERSION=${linux_version/xen/kdump}
    fi

    if [ -z "$KDUMP_KERNEL_CMDLINE" ] ; then
	KDUMP_KERNEL_CMDLINE=$(cat /proc/cmdline)
    fi
    
    if [ -z "$KDUMP_KERNEL_CMDLINE_EXTRA" ] ; then
	KDUMP_KERNEL_CMDLINE_EXTRA="irqpoll maxcpus=1 reset_devices"
	if [ -n "${xen_version}" ] ; then
	    KDUMP_KERNEL_CMDLINE_EXTRA="$KDUMP_KERNEL_CMDLINE_EXTRA kdump-xenversion=${xen_version}"
	fi
	if [ -n "${linux_version}" ] ; then
            KDUMP_KERNEL_CMDLINE_EXTRA="$KDUMP_KERNEL_CMDLINE_EXTRA kdump-linuxversion=${linux_version}"
	fi
    fi

    KERNEL=/boot/vmlinuz-${KDUMP_KERNEL_VERSION}
    INITRD=/boot/initrd-${KDUMP_KERNEL_VERSION}.img

    if [ ! -f "$KERNEL" ] ; then
	echo -n "No kdump kernel image found. "; warning; echo
	echo "Tried to locate ${KERNEL}"
	return 0
    fi

    if [ ! -f "$INITRD" ] ; then
	action $"Generating crash ramdisk:" \
	    mkinitrd $KDUMP_MKINITRD_OPTIONS $INITRD $KDUMP_KERNEL_VERSION
    fi

    action $"Loading crash kernel:" \
	$KEXEC -p --elf64-core-headers --args-linux --append="$KDUMP_KERNEL_CMDLINE $KDUMP_KERNEL_CMDLINE_EXTRA" \
	    --ramdisk=$INITRD $KERNEL

    return $?
}

case "$1" in
    start)
        if [ ! -f /proc/vmcore ]; then
	    setup_kdump
        fi
        ;;
    crash_dump)
        if [ -f /proc/vmcore ]; then
	    crash_dump
        else
	    echo -n "kdump crash_dump: cannot find /proc/vmcore" ; failure
	fi
	;;
    stop)
	action $"Unloading crash kernel: " $KEXEC -p -u
        ;;
    restart)
        $0 stop
	$0 start
        ;;
    condrestart)
        ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart}"
        exit 1
esac

exit $?
