Petr Šabata f5bf49
# These variables and functions are useful in 2nd kernel
Petr Šabata f5bf49
Petr Šabata f5bf49
. /lib/kdump-lib.sh
DistroBaker 624a64
. /lib/kdump-logger.sh
Petr Šabata f5bf49
Petr Šabata f5bf49
KDUMP_PATH="/var/crash"
DistroBaker 5cac7c
KDUMP_LOG_FILE="/run/initramfs/kexec-dmesg.log"
Petr Šabata f5bf49
CORE_COLLECTOR=""
DistroBaker 5cac7c
DEFAULT_CORE_COLLECTOR="makedumpfile -l --message-level 7 -d 31"
Petr Šabata f5bf49
DMESG_COLLECTOR="/sbin/vmcore-dmesg"
Petr Šabata f5bf49
FAILURE_ACTION="systemctl reboot -f"
Petr Šabata f5bf49
DATEDIR=`date +%Y-%m-%d-%T`
Petr Šabata f5bf49
HOST_IP='127.0.0.1'
Petr Šabata f5bf49
DUMP_INSTRUCTION=""
Petr Šabata f5bf49
SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa"
Petr Šabata f5bf49
KDUMP_SCRIPT_DIR="/kdumpscripts"
Petr Šabata f5bf49
DD_BLKSIZE=512
Petr Šabata f5bf49
FINAL_ACTION="systemctl reboot -f"
Petr Šabata f5bf49
KDUMP_CONF="/etc/kdump.conf"
Petr Šabata f5bf49
KDUMP_PRE=""
Petr Šabata f5bf49
KDUMP_POST=""
Petr Šabata f5bf49
NEWROOT="/sysroot"
Petr Šabata f5bf49
OPALCORE="/sys/firmware/opal/mpipl/core"
Petr Šabata f5bf49
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
get_kdump_confs()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
    local config_opt config_val
Petr Šabata f5bf49
Petr Šabata f5bf49
    while read config_opt config_val;
Petr Šabata f5bf49
    do
Petr Šabata f5bf49
        # remove inline comments after the end of a directive.
Petr Šabata f5bf49
        case "$config_opt" in
Petr Šabata f5bf49
            path)
Petr Šabata f5bf49
                KDUMP_PATH="$config_val"
Petr Šabata f5bf49
            ;;
Petr Šabata f5bf49
            core_collector)
Petr Šabata f5bf49
                [ -n "$config_val" ] && CORE_COLLECTOR="$config_val"
Petr Šabata f5bf49
            ;;
Petr Šabata f5bf49
            sshkey)
Petr Šabata f5bf49
                if [ -f "$config_val" ]; then
Petr Šabata f5bf49
                    SSH_KEY_LOCATION=$config_val
Petr Šabata f5bf49
                fi
Petr Šabata f5bf49
            ;;
Petr Šabata f5bf49
            kdump_pre)
Petr Šabata f5bf49
                KDUMP_PRE="$config_val"
Petr Šabata f5bf49
            ;;
Petr Šabata f5bf49
            kdump_post)
Petr Šabata f5bf49
                KDUMP_POST="$config_val"
Petr Šabata f5bf49
            ;;
Petr Šabata f5bf49
            fence_kdump_args)
Petr Šabata f5bf49
                FENCE_KDUMP_ARGS="$config_val"
Petr Šabata f5bf49
            ;;
Petr Šabata f5bf49
            fence_kdump_nodes)
Petr Šabata f5bf49
                FENCE_KDUMP_NODES="$config_val"
Petr Šabata f5bf49
            ;;
Petr Šabata f5bf49
            failure_action|default)
Petr Šabata f5bf49
                case $config_val in
Petr Šabata f5bf49
                    shell)
Petr Šabata f5bf49
                        FAILURE_ACTION="kdump_emergency_shell"
Petr Šabata f5bf49
                    ;;
Petr Šabata f5bf49
                    reboot)
Petr Šabata f5bf49
                        FAILURE_ACTION="systemctl reboot -f && exit"
Petr Šabata f5bf49
                    ;;
Petr Šabata f5bf49
                    halt)
Petr Šabata f5bf49
                        FAILURE_ACTION="halt && exit"
Petr Šabata f5bf49
                    ;;
Petr Šabata f5bf49
                    poweroff)
Petr Šabata f5bf49
                        FAILURE_ACTION="systemctl poweroff -f && exit"
Petr Šabata f5bf49
                    ;;
Petr Šabata f5bf49
                    dump_to_rootfs)
Petr Šabata f5bf49
                        FAILURE_ACTION="dump_to_rootfs"
Petr Šabata f5bf49
                    ;;
Petr Šabata f5bf49
                esac
Petr Šabata f5bf49
            ;;
Petr Šabata f5bf49
            final_action)
Petr Šabata f5bf49
                case $config_val in
Petr Šabata f5bf49
                    reboot)
Petr Šabata f5bf49
                        FINAL_ACTION="systemctl reboot -f"
Petr Šabata f5bf49
                    ;;
Petr Šabata f5bf49
                    halt)
Petr Šabata f5bf49
                        FINAL_ACTION="halt"
Petr Šabata f5bf49
                    ;;
Petr Šabata f5bf49
                    poweroff)
Petr Šabata f5bf49
                        FINAL_ACTION="systemctl poweroff -f"
Petr Šabata f5bf49
                    ;;
Petr Šabata f5bf49
                esac
Petr Šabata f5bf49
            ;;
Petr Šabata f5bf49
        esac
Petr Šabata f5bf49
    done <<< "$(read_strip_comments $KDUMP_CONF)"
Petr Šabata f5bf49
Petr Šabata f5bf49
    if [ -z "$CORE_COLLECTOR" ]; then
Petr Šabata f5bf49
        CORE_COLLECTOR="$DEFAULT_CORE_COLLECTOR"
Petr Šabata f5bf49
        if is_ssh_dump_target || is_raw_dump_target; then
Petr Šabata f5bf49
            CORE_COLLECTOR="$CORE_COLLECTOR -F"
Petr Šabata f5bf49
        fi
Petr Šabata f5bf49
    fi
Petr Šabata f5bf49
}
Petr Šabata f5bf49
DistroBaker 5cac7c
# store the kexec kernel log to a file.
DistroBaker 5cac7c
save_log()
DistroBaker 5cac7c
{
DistroBaker 5cac7c
    dmesg -T > $KDUMP_LOG_FILE
DistroBaker 5cac7c
DistroBaker 5cac7c
    if command -v journalctl > /dev/null; then
DistroBaker 5cac7c
        journalctl -ab >> $KDUMP_LOG_FILE
DistroBaker 5cac7c
    fi
337158
    chmod 600 $KDUMP_LOG_FILE
DistroBaker 5cac7c
}
DistroBaker 5cac7c
Petr Šabata f5bf49
# dump_fs <mount point>
Petr Šabata f5bf49
dump_fs()
Petr Šabata f5bf49
{
DistroBaker 633317
    local _exitcode
Petr Šabata f5bf49
    local _mp=$1
41f1d5
    local _op=$(get_mount_info OPTIONS target $_mp -f)
41f1d5
    ddebug "dump_fs _mp=$_mp _opts=$_op"
DistroBaker 624a64
DistroBaker 624a64
    if ! is_mounted "$_mp"; then
DistroBaker 624a64
        dinfo "dump path \"$_mp\" is not mounted, trying to mount..."
DistroBaker 624a64
        mount --target $_mp
DistroBaker 624a64
        if [ $? -ne 0 ]; then
DistroBaker 624a64
            derror "failed to dump to \"$_mp\", it's not a mount point!"
DistroBaker 624a64
            return 1
Petr Šabata f5bf49
        fi
Petr Šabata f5bf49
    fi
Petr Šabata f5bf49
Petr Šabata f5bf49
    # Remove -F in makedumpfile case. We don't want a flat format dump here.
Petr Šabata f5bf49
    [[ $CORE_COLLECTOR = *makedumpfile* ]] && CORE_COLLECTOR=`echo $CORE_COLLECTOR | sed -e "s/-F//g"`
Petr Šabata f5bf49
Petr Šabata f5bf49
    local _dump_path=$(echo "$_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/" | tr -s /)
Petr Šabata f5bf49
DistroBaker 5cac7c
    dinfo "saving to $_dump_path"
Petr Šabata f5bf49
Petr Šabata f5bf49
    # Only remount to read-write mode if the dump target is mounted read-only.
Petr Šabata f5bf49
    if [[ "$_op" = "ro"* ]]; then
41f1d5
       dinfo "Remounting the dump target in rw mode."
41f1d5
       mount -o remount,rw $_mp || return 1
Petr Šabata f5bf49
    fi
Petr Šabata f5bf49
Petr Šabata f5bf49
    mkdir -p $_dump_path || return 1
Petr Šabata f5bf49
Petr Šabata f5bf49
    save_vmcore_dmesg_fs ${DMESG_COLLECTOR} "$_dump_path"
Petr Šabata f5bf49
    save_opalcore_fs "$_dump_path"
Petr Šabata f5bf49
DistroBaker 5cac7c
    dinfo "saving vmcore"
DistroBaker 5cac7c
    $CORE_COLLECTOR /proc/vmcore $_dump_path/vmcore-incomplete
DistroBaker 633317
    _exitcode=$?
DistroBaker 633317
    if [ $_exitcode -eq 0 ]; then
DistroBaker 633317
        mv $_dump_path/vmcore-incomplete $_dump_path/vmcore
DistroBaker 633317
        sync
DistroBaker 633317
        dinfo "saving vmcore complete"
DistroBaker 633317
    else
DistroBaker 633317
        derror "saving vmcore failed, _exitcode:$_exitcode"
DistroBaker 633317
    fi
DistroBaker 633317
DistroBaker 624a64
    dinfo "saving the $KDUMP_LOG_FILE to $_dump_path/"
DistroBaker 5cac7c
    save_log
DistroBaker 5cac7c
    mv $KDUMP_LOG_FILE $_dump_path/
DistroBaker 633317
    if [ $_exitcode -ne 0 ]; then
DistroBaker 633317
        return 1
DistroBaker 5cac7c
    fi
Petr Šabata f5bf49
Petr Šabata f5bf49
    # improper kernel cmdline can cause the failure of echo, we can ignore this kind of failure
Petr Šabata f5bf49
    return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
save_vmcore_dmesg_fs() {
Petr Šabata f5bf49
    local _dmesg_collector=$1
Petr Šabata f5bf49
    local _path=$2
Petr Šabata f5bf49
DistroBaker 5cac7c
    dinfo "saving vmcore-dmesg.txt to ${_path}"
Petr Šabata f5bf49
    $_dmesg_collector /proc/vmcore > ${_path}/vmcore-dmesg-incomplete.txt
Petr Šabata f5bf49
    _exitcode=$?
Petr Šabata f5bf49
    if [ $_exitcode -eq 0 ]; then
Petr Šabata f5bf49
        mv ${_path}/vmcore-dmesg-incomplete.txt ${_path}/vmcore-dmesg.txt
337158
        chmod 600 ${_path}/vmcore-dmesg.txt
Petr Šabata f5bf49
Petr Šabata f5bf49
        # Make sure file is on disk. There have been instances where later
Petr Šabata f5bf49
        # saving vmcore failed and system rebooted without sync and there
Petr Šabata f5bf49
        # was no vmcore-dmesg.txt available.
Petr Šabata f5bf49
        sync
DistroBaker 5cac7c
        dinfo "saving vmcore-dmesg.txt complete"
Petr Šabata f5bf49
    else
134a76
        if [ -f ${_path}/vmcore-dmesg-incomplete.txt ]; then
134a76
            chmod 600 ${_path}/vmcore-dmesg-incomplete.txt
134a76
        fi
DistroBaker 5cac7c
        derror "saving vmcore-dmesg.txt failed"
Petr Šabata f5bf49
    fi
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
save_opalcore_fs() {
Petr Šabata f5bf49
    local _path=$1
Petr Šabata f5bf49
Petr Šabata f5bf49
    if [ ! -f $OPALCORE ]; then
Petr Šabata f5bf49
        # Check if we are on an old kernel that uses a different path
Petr Šabata f5bf49
        if [ -f /sys/firmware/opal/core ]; then
Petr Šabata f5bf49
            OPALCORE="/sys/firmware/opal/core"
Petr Šabata f5bf49
        else
Petr Šabata f5bf49
            return 0
Petr Šabata f5bf49
        fi
Petr Šabata f5bf49
    fi
Petr Šabata f5bf49
DistroBaker 5cac7c
    dinfo "saving opalcore:$OPALCORE to ${_path}/opalcore"
Petr Šabata f5bf49
    cp $OPALCORE ${_path}/opalcore
Petr Šabata f5bf49
    if [ $? -ne 0 ]; then
DistroBaker 5cac7c
        derror "saving opalcore failed"
Petr Šabata f5bf49
        return 1
Petr Šabata f5bf49
    fi
Petr Šabata f5bf49
Petr Šabata f5bf49
    sync
DistroBaker 5cac7c
    dinfo "saving opalcore complete"
Petr Šabata f5bf49
    return 0
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
dump_to_rootfs()
Petr Šabata f5bf49
{
Petr Šabata f5bf49
Kairui Song e5ccb8
    if [[ $(systemctl status dracut-initqueue | sed -n "s/^\s*Active: \(\S*\)\s.*$/\1/p") == "inactive" ]]; then
Kairui Song e5ccb8
        dinfo "Trying to bring up initqueue for rootfs mount"
Kairui Song e5ccb8
        systemctl start dracut-initqueue
Kairui Song e5ccb8
    fi
Kairui Song e5ccb8
Kairui Song da6b28
    dinfo "Clean up dead systemd services"
Kairui Song da6b28
    systemctl cancel
DistroBaker 5cac7c
    dinfo "Waiting for rootfs mount, will timeout after 90 seconds"
Kairui Song 0cbec8
    systemctl start --no-block sysroot.mount
Petr Šabata f5bf49
Kairui Song 0cbec8
    _loop=0
Kairui Song 0cbec8
    while [ $_loop -lt 90 ] && ! is_mounted /sysroot; do
Kairui Song 0cbec8
        sleep 1
Kairui Song 0cbec8
        _loop=$((_loop + 1))
Kairui Song 0cbec8
    done
Kairui Song 0cbec8
Kairui Song 0cbec8
    if ! is_mounted /sysroot; then
Kairui Song 0cbec8
        derror "Failed to mount rootfs"
Kairui Song 0cbec8
        return
Kairui Song 0cbec8
    fi
DistroBaker 5cac7c
Kairui Song 0cbec8
    ddebug "NEWROOT=$NEWROOT"
Petr Šabata f5bf49
    dump_fs $NEWROOT
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
kdump_emergency_shell()
Petr Šabata f5bf49
{
Kairui Song 50d77e
    ddebug "Switching to kdump emergency shell..."
Kairui Song 50d77e
Kairui Song 50d77e
    [ -f /etc/profile ] && . /etc/profile
Kairui Song 50d77e
    export PS1='kdump:${PWD}# '
Kairui Song 50d77e
Kairui Song 50d77e
    . /lib/dracut-lib.sh
Kairui Song 50d77e
    if [ -f /dracut-state.sh ]; then
Kairui Song 50d77e
        . /dracut-state.sh 2>/dev/null
Kairui Song 50d77e
    fi
Kairui Song 50d77e
Kairui Song 50d77e
    source_conf /etc/conf.d
Kairui Song 50d77e
Kairui Song 50d77e
    type plymouth >/dev/null 2>&1 && plymouth quit
Kairui Song 50d77e
Kairui Song 50d77e
    source_hook "emergency"
Kairui Song 50d77e
    while read _tty rest; do
Kairui Song 50d77e
        (
Kairui Song 50d77e
        echo
Kairui Song 50d77e
        echo
Kairui Song 50d77e
        echo 'Entering kdump emergency mode.'
Kairui Song 50d77e
        echo 'Type "journalctl" to view system logs.'
Kairui Song 50d77e
        echo 'Type "rdsosreport" to generate a sosreport, you can then'
Kairui Song 50d77e
        echo 'save it elsewhere and attach it to a bug report.'
Kairui Song 50d77e
        echo
Kairui Song 50d77e
        echo
Kairui Song 50d77e
        ) > /dev/$_tty
Kairui Song 50d77e
    done < /proc/consoles
Kairui Song 50d77e
    sh -i -l
Kairui Song 50d77e
    /bin/rm -f -- /.console_lock
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
do_failure_action()
Petr Šabata f5bf49
{
DistroBaker 5cac7c
    dinfo "Executing failure action $FAILURE_ACTION"
Petr Šabata f5bf49
    eval $FAILURE_ACTION
Petr Šabata f5bf49
}
Petr Šabata f5bf49
Petr Šabata f5bf49
do_final_action()
Petr Šabata f5bf49
{
DistroBaker 5cac7c
    dinfo "Executing final action $FINAL_ACTION"
Petr Šabata f5bf49
    eval $FINAL_ACTION
Petr Šabata f5bf49
}