Compare commits

..

No commits in common. "rawhide" and "f29" have entirely different histories.

75 changed files with 6392 additions and 3001 deletions

View file

@ -1,32 +0,0 @@
# EditorConfig configuration for kexec-tools
# http://EditorConfig.org
# Top-most EditorConfig file
root = true
# Default code style for kexec-tools scripts
[*]
end_of_line = lf
shell_variant = posix
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = tab
indent_size = 1
switch_case_indent = false
function_next_line = true
binary_next_line = false
space_redirects = true
# Some scripts will only run with bash
[{mkfadumprd,mkdumprd,kdumpctl,kdump-lib.sh}]
shell_variant = bash
# Use dracut code style for *-module-setup.sh
[*-module-setup.sh,dracut-early-kdump.sh]
shell_variant = bash
indent_style = space
indent_size = 4
switch_case_indent = true
function_next_line = false
binary_next_line = true
space_redirects = true

1
.gitignore vendored
View file

@ -21,4 +21,3 @@
/kexec-tools-2.0.11.tar.xz
/makedumpfile-1.5.9.tar.gz
/kexec-tools-2.0.12.tar.xz
coverage/

View file

@ -1,36 +0,0 @@
# See the documentation for more information:
# https://packit.dev/docs/configuration/
upstream_project_url: https://github.com/horms/kexec-tools.git
specfile_path: kexec-tools.spec
# add or remove files that should be synced
files_to_sync:
- kexec-tools.spec
- .packit.yaml
# name in upstream package repository or registry (e.g. in PyPI)
upstream_package_name: kexec-tools
# downstream (Fedora) RPM package name
downstream_package_name: kexec-tools
upstream_tag_template: v{version}
jobs:
- job: pull_from_upstream
trigger: release
dist_git_branches:
- fedora-all
- job: koji_build
trigger: commit
allowed_pr_authors: ["all_committers", "packit"]
dist_git_branches:
- fedora-all
- job: bodhi_update
trigger: commit
allowed_builders: ["all_committers", "packit"]
dist_git_branches:
- fedora-all

View file

16
98-kexec.rules Normal file
View file

@ -0,0 +1,16 @@
SUBSYSTEM=="cpu", ACTION=="add", GOTO="kdump_reload"
SUBSYSTEM=="cpu", ACTION=="remove", GOTO="kdump_reload"
SUBSYSTEM=="memory", ACTION=="online", GOTO="kdump_reload"
SUBSYSTEM=="memory", ACTION=="offline", GOTO="kdump_reload"
GOTO="kdump_reload_end"
LABEL="kdump_reload"
# If kdump is not loaded, calling kdump-udev-throttle will end up
# doing nothing, but systemd-run will always generate extra logs for
# each call, so trigger the kdump-udev-throttler only if kdump
# service is active to avoid unnecessary logs
RUN+="/bin/sh -c '/usr/bin/systemctl is-active kdump.service || exit 0; /usr/bin/systemd-run --quiet --no-block /usr/lib/udev/kdump-udev-throttler'"
LABEL="kdump_reload_end"

View file

@ -1,3 +0,0 @@
This repository is maintained by packit.
https://packit.dev/
The file was generated using packit 1.11.0.post1.dev7+gfdcdf3a32.

View file

@ -0,0 +1,65 @@
#!/bin/bash
. /etc/sysconfig/kdump
. /lib/kdump/kdump-lib.sh
KDUMP_KERNEL=""
KDUMP_INITRD=""
check() {
if [ ! -f /etc/sysconfig/kdump ] || [ ! -f /lib/kdump/kdump-lib.sh ]\
|| [ -n "${IN_KDUMP}" ]
then
return 1
fi
return 255
}
depends() {
echo "base shutdown"
return 0
}
prepare_kernel_initrd() {
KDUMP_BOOTDIR=$(check_boot_dir "${KDUMP_BOOTDIR}")
if [ -z "$KDUMP_KERNELVER" ]; then
kdump_kver=`uname -r`
if [ "$kernel" != "$kdump_kver" ]; then
dwarn "Using current kernel version '$kdump_kver' for early kdump," \
"but the initramfs is generated for kernel version '$kernel'"
fi
else
kdump_kver=$KDUMP_KERNELVER
fi
KDUMP_KERNEL="${KDUMP_BOOTDIR}/${KDUMP_IMG}-${kdump_kver}${KDUMP_IMG_EXT}"
KDUMP_INITRD="${KDUMP_BOOTDIR}/initramfs-${kdump_kver}kdump.img"
}
install() {
prepare_kernel_initrd
if [ ! -f "$KDUMP_KERNEL" ]; then
derror "Could not find required kernel for earlykdump," \
"earlykdump will not work!"
return 1
fi
if [ ! -f "$KDUMP_INITRD" ]; then
derror "Could not find required kdump initramfs for earlykdump," \
"please ensure kdump initramfs is generated first," \
"earlykdump will not work!"
return 1
fi
inst_multiple tail find cut dirname hexdump
inst_simple "/etc/sysconfig/kdump"
inst_binary "/usr/sbin/kexec"
inst_binary "/usr/bin/gawk" "/usr/bin/awk"
inst_script "/lib/kdump/kdump-lib.sh" "/lib/kdump-lib.sh"
inst_hook cmdline 00 "$moddir/early-kdump.sh"
inst_binary "$KDUMP_KERNEL"
inst_binary "$KDUMP_INITRD"
ln_r "$KDUMP_KERNEL" "${KDUMP_BOOTDIR}/${KDUMP_IMG}-earlykdump${KDUMP_IMG_EXT}"
ln_r "$KDUMP_INITRD" "${KDUMP_BOOTDIR}/initramfs-earlykdump.img"
chmod -x "${initdir}/$KDUMP_KERNEL"
}

75
dracut-early-kdump.sh Executable file
View file

@ -0,0 +1,75 @@
#! /bin/sh
KEXEC=/sbin/kexec
standard_kexec_args="-p"
EARLY_KDUMP_INITRD=""
EARLY_KDUMP_KERNEL=""
EARLY_KDUMP_CMDLINE=""
EARLY_KDUMP_KERNELVER=""
EARLY_KEXEC_ARGS=""
. /etc/sysconfig/kdump
. /lib/dracut-lib.sh
. /lib/kdump-lib.sh
prepare_parameters()
{
EARLY_KDUMP_CMDLINE=$(prepare_cmdline "${KDUMP_COMMANDLINE}" "${KDUMP_COMMANDLINE_REMOVE}" "${KDUMP_COMMANDLINE_APPEND}")
KDUMP_BOOTDIR=$(check_boot_dir "${KDUMP_BOOTDIR}")
EARLY_KDUMP_KERNEL="${KDUMP_BOOTDIR}/${KDUMP_IMG}-earlykdump${KDUMP_IMG_EXT}"
EARLY_KDUMP_INITRD="${KDUMP_BOOTDIR}/initramfs-earlykdump.img"
}
early_kdump_load()
{
check_kdump_feasibility
if [ $? -ne 0 ]; then
return 1
fi
if is_fadump_capable; then
echo "WARNING: early kdump doesn't support fadump."
return 1
fi
check_current_kdump_status
if [ $? == 0 ]; then
return 1
fi
prepare_parameters
EARLY_KEXEC_ARGS=$(prepare_kexec_args "${KEXEC_ARGS}")
if is_secure_boot_enforced; then
echo "Secure Boot is enabled. Using kexec file based syscall."
EARLY_KEXEC_ARGS="$EARLY_KEXEC_ARGS -s"
fi
$KEXEC ${EARLY_KEXEC_ARGS} $standard_kexec_args \
--command-line="$EARLY_KDUMP_CMDLINE" \
--initrd=$EARLY_KDUMP_INITRD $EARLY_KDUMP_KERNEL
if [ $? == 0 ]; then
echo "kexec: loaded early-kdump kernel"
return 0
else
echo "kexec: failed to load early-kdump kernel"
return 1
fi
}
set_early_kdump()
{
if getargbool 0 rd.earlykdump; then
echo "early-kdump is enabled."
early_kdump_load
else
echo "early-kdump is disabled."
fi
return 0
}
set_early_kdump

View file

@ -0,0 +1,30 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Kdump Vmcore Save Service
After=initrd.target initrd-parse-etc.service sysroot.mount
After=dracut-initqueue.service dracut-pre-mount.service dracut-mount.service dracut-pre-pivot.service
Before=initrd-cleanup.service
ConditionPathExists=/etc/initrd-release
OnFailure=emergency.target
OnFailureIsolate=yes
[Service]
Environment=DRACUT_SYSTEMD=1
Environment=NEWROOT=/sysroot
Type=oneshot
ExecStart=/bin/kdump.sh
StandardInput=null
StandardOutput=syslog
StandardError=syslog+console
KillMode=process
RemainAfterExit=yes
# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
# terminates cleanly.
KillSignal=SIGHUP

View file

@ -0,0 +1,28 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
# This service will be placed in kdump initramfs and replace both the systemd
# emergency service and dracut emergency shell. IOW, any emergency will be
# kick this service and in turn isolating to kdump error handler.
[Unit]
Description=Kdump Emergency
DefaultDependencies=no
IgnoreOnIsolate=yes
[Service]
ExecStart=/usr/bin/systemctl --no-block isolate kdump-error-handler.service
Type=oneshot
StandardInput=tty-force
StandardOutput=inherit
StandardError=inherit
KillMode=process
IgnoreSIGPIPE=no
# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
# terminates cleanly.
KillSignal=SIGHUP

View file

@ -0,0 +1,14 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Emergency Mode
Documentation=man:systemd.special(7)
Requires=emergency.service
After=emergency.service
AllowIsolate=yes
IgnoreOnIsolate=yes

View file

@ -0,0 +1,34 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
# This service will run the real kdump error handler code. Executing the
# failure action configured in kdump.conf
[Unit]
Description=Kdump Error Handler
DefaultDependencies=no
After=systemd-vconsole-setup.service
Wants=systemd-vconsole-setup.service
AllowIsolate=yes
[Service]
Environment=HOME=/
Environment=DRACUT_SYSTEMD=1
Environment=NEWROOT=/sysroot
WorkingDirectory=/
ExecStart=/bin/kdump-error-handler.sh
ExecStopPost=-/usr/bin/systemctl --fail --no-block default
Type=oneshot
StandardInput=tty-force
StandardOutput=inherit
StandardError=inherit
KillMode=process
IgnoreSIGPIPE=no
# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
# terminates cleanly.
KillSignal=SIGHUP

10
dracut-kdump-error-handler.sh Executable file
View file

@ -0,0 +1,10 @@
#!/bin/sh
. /lib/kdump-lib-initramfs.sh
set -o pipefail
export PATH=$PATH:$KDUMP_SCRIPT_DIR
get_kdump_confs
do_failure_action
do_final_action

204
dracut-kdump.sh Executable file
View file

@ -0,0 +1,204 @@
#!/bin/sh
# continue here only if we have to save dump.
if [ -f /etc/fadump.initramfs ] && [ ! -f /proc/device-tree/rtas/ibm,kernel-dump ]; then
exit 0
fi
exec &> /dev/console
. /lib/dracut-lib.sh
. /lib/kdump-lib-initramfs.sh
set -o pipefail
DUMP_RETVAL=0
export PATH=$PATH:$KDUMP_SCRIPT_DIR
do_dump()
{
local _ret
eval $DUMP_INSTRUCTION
_ret=$?
if [ $_ret -ne 0 ]; then
echo "kdump: saving vmcore failed"
fi
return $_ret
}
do_kdump_pre()
{
if [ -n "$KDUMP_PRE" ]; then
"$KDUMP_PRE"
fi
}
do_kdump_post()
{
if [ -n "$KDUMP_POST" ]; then
"$KDUMP_POST" "$1"
fi
}
add_dump_code()
{
DUMP_INSTRUCTION=$1
}
dump_raw()
{
local _raw=$1
[ -b "$_raw" ] || return 1
echo "kdump: saving to raw disk $_raw"
if ! $(echo -n $CORE_COLLECTOR|grep -q makedumpfile); then
_src_size=`ls -l /proc/vmcore | cut -d' ' -f5`
_src_size_mb=$(($_src_size / 1048576))
monitor_dd_progress $_src_size_mb &
fi
echo "kdump: saving vmcore"
$CORE_COLLECTOR /proc/vmcore | dd of=$_raw bs=$DD_BLKSIZE >> /tmp/dd_progress_file 2>&1 || return 1
sync
echo "kdump: saving vmcore complete"
return 0
}
dump_ssh()
{
local _opt="-i $1 -o BatchMode=yes -o StrictHostKeyChecking=yes"
local _dir="$KDUMP_PATH/$HOST_IP-$DATEDIR"
local _host=$2
echo "kdump: saving to $_host:$_dir"
cat /var/lib/random-seed > /dev/urandom
ssh -q $_opt $_host mkdir -p $_dir || return 1
save_vmcore_dmesg_ssh ${DMESG_COLLECTOR} ${_dir} "${_opt}" $_host
echo "kdump: saving vmcore"
if [ "${CORE_COLLECTOR%%[[:blank:]]*}" = "scp" ]; then
scp -q $_opt /proc/vmcore "$_host:$_dir/vmcore-incomplete" || return 1
ssh $_opt $_host "mv $_dir/vmcore-incomplete $_dir/vmcore" || return 1
else
$CORE_COLLECTOR /proc/vmcore | ssh $_opt $_host "dd bs=512 of=$_dir/vmcore-incomplete" || return 1
ssh $_opt $_host "mv $_dir/vmcore-incomplete $_dir/vmcore.flat" || return 1
fi
echo "kdump: saving vmcore complete"
return 0
}
save_vmcore_dmesg_ssh() {
local _dmesg_collector=$1
local _path=$2
local _opts="$3"
local _location=$4
echo "kdump: saving vmcore-dmesg.txt"
$_dmesg_collector /proc/vmcore | ssh $_opts $_location "dd of=$_path/vmcore-dmesg-incomplete.txt"
_exitcode=$?
if [ $_exitcode -eq 0 ]; then
ssh -q $_opts $_location mv $_path/vmcore-dmesg-incomplete.txt $_path/vmcore-dmesg.txt
echo "kdump: saving vmcore-dmesg.txt complete"
else
echo "kdump: saving vmcore-dmesg.txt failed"
fi
}
get_host_ip()
{
local _host
if is_nfs_dump_target || is_ssh_dump_target
then
kdumpnic=$(getarg kdumpnic=)
[ -z "$kdumpnic" ] && echo "kdump: failed to get kdumpnic!" && return 1
_host=`ip addr show dev $kdumpnic|grep '[ ]*inet'`
[ $? -ne 0 ] && echo "kdump: wrong kdumpnic: $kdumpnic" && return 1
_host=`echo $_host | head -n 1 | cut -d' ' -f2`
_host="${_host%%/*}"
[ -z "$_host" ] && echo "kdump: wrong kdumpnic: $kdumpnic" && return 1
HOST_IP=$_host
fi
return 0
}
read_kdump_conf()
{
if [ ! -f "$KDUMP_CONF" ]; then
echo "kdump: $KDUMP_CONF not found"
return
fi
get_kdump_confs
# rescan for add code for dump target
while read config_opt config_val;
do
# remove inline comments after the end of a directive.
config_val=$(strip_comments $config_val)
case "$config_opt" in
dracut_args)
config_val=$(get_dracut_args_target "$config_val")
[ -n "$config_val" ] && add_dump_code "dump_fs $config_val"
;;
ext[234]|xfs|btrfs|minix|nfs)
add_dump_code "dump_fs $config_val"
;;
raw)
add_dump_code "dump_raw $config_val"
;;
ssh)
add_dump_code "dump_ssh $SSH_KEY_LOCATION $config_val"
;;
esac
done < $KDUMP_CONF
}
fence_kdump_notify()
{
if [ -n "$FENCE_KDUMP_NODES" ]; then
$FENCE_KDUMP_SEND $FENCE_KDUMP_ARGS $FENCE_KDUMP_NODES &
fi
}
read_kdump_conf
fence_kdump_notify
get_host_ip
if [ $? -ne 0 ]; then
echo "kdump: get_host_ip exited with non-zero status!"
exit 1
fi
if [ -z "$DUMP_INSTRUCTION" ]; then
add_dump_code "dump_fs $NEWROOT"
fi
do_kdump_pre
if [ $? -ne 0 ]; then
echo "kdump: kdump_pre script exited with non-zero status!"
do_final_action
fi
make_trace_mem "kdump saving vmcore" '1:shortmem' '2+:mem' '3+:slab'
do_dump
DUMP_RETVAL=$?
do_kdump_post $DUMP_RETVAL
if [ $? -ne 0 ]; then
echo "kdump: kdump_post script exited with non-zero status!"
fi
if [ $DUMP_RETVAL -ne 0 ]; then
exit 1
fi
do_final_action

826
dracut-module-setup.sh Executable file
View file

@ -0,0 +1,826 @@
#!/bin/bash
. $dracutfunctions
. /lib/kdump/kdump-lib.sh
if ! [[ -d "${initdir}/tmp" ]]; then
mkdir -p "${initdir}/tmp"
fi
check() {
[[ $debug ]] && set -x
#kdumpctl sets this explicitly
if [ -z "$IN_KDUMP" ] || [ ! -f /etc/kdump.conf ]
then
return 1
fi
return 0
}
depends() {
local _dep="base shutdown"
is_squash_available() {
for kmodule in squashfs overlay loop; do
if [ -z "$KDUMP_KERNELVER" ]; then
modprobe --dry-run $kmodule &>/dev/null || return 1
else
modprobe -S $KDUMP_KERNELVER --dry-run $kmodule &>/dev/null || return 1
fi
done
}
if is_squash_available; then
_dep="$_dep squash"
else
dwarning "Required modules to build a squashed kdump image is missing!"
fi
if [ -n "$( find /sys/devices -name drm )" ] || [ -d /sys/module/hyperv_fb ]; then
_dep="$_dep drm"
fi
if is_generic_fence_kdump -o is_pcs_fence_kdump; then
_dep="$_dep network"
fi
echo $_dep
return 0
}
kdump_get_persistent_dev() {
local dev="${1//\"/}"
case "$dev" in
UUID=*)
dev=`blkid -U "${dev#UUID=}"`
;;
LABEL=*)
dev=`blkid -L "${dev#LABEL=}"`
;;
esac
echo $(get_persistent_dev "$dev")
}
kdump_is_bridge() {
[ -d /sys/class/net/"$1"/bridge ]
}
kdump_is_bond() {
[ -d /sys/class/net/"$1"/bonding ]
}
kdump_is_team() {
[ -f /usr/bin/teamnl ] && teamnl $1 ports &> /dev/null
}
kdump_is_vlan() {
[ -f /proc/net/vlan/"$1" ]
}
# $1: netdev name
source_ifcfg_file() {
local ifcfg_file
ifcfg_file=$(get_ifcfg_filename $1)
if [ -f "${ifcfg_file}" ]; then
. ${ifcfg_file}
else
dwarning "The ifcfg file of $1 is not found!"
fi
}
# $1: netdev name
kdump_setup_dns() {
local _nameserver _dns
local _dnsfile=${initdir}/etc/cmdline.d/42dns.conf
source_ifcfg_file $1
[ -n "$DNS1" ] && echo "nameserver=$DNS1" > "$_dnsfile"
[ -n "$DNS2" ] && echo "nameserver=$DNS2" >> "$_dnsfile"
while read content;
do
_nameserver=$(echo $content | grep ^nameserver)
[ -z "$_nameserver" ] && continue
_dns=$(echo $_nameserver | cut -d' ' -f2)
[ -z "$_dns" ] && continue
if [ ! -f $_dnsfile ] || [ ! $(cat $_dnsfile | grep -q $_dns) ]; then
echo "nameserver=$_dns" >> "$_dnsfile"
fi
done < "/etc/resolv.conf"
}
#$1: netdev name
#$2: srcaddr
#if it use static ip echo it, or echo null
kdump_static_ip() {
local _netdev="$1" _srcaddr="$2" _ipv6_flag
local _netmask _gateway _ipaddr _target _nexthop
_ipaddr=$(ip addr show dev $_netdev permanent | awk "/ $_srcaddr\/.* /{print \$2}")
if is_ipv6_address $_srcaddr; then
_ipv6_flag="-6"
fi
if [ -n "$_ipaddr" ]; then
_gateway=$(ip $_ipv6_flag route list dev $_netdev | \
awk '/^default /{print $3}' | head -n 1)
if [ "x" != "x"$_ipv6_flag ]; then
# _ipaddr="2002::56ff:feb6:56d5/64", _netmask is the number after "/"
_netmask=${_ipaddr#*\/}
_srcaddr="[$_srcaddr]"
_gateway="[$_gateway]"
else
_netmask=$(ipcalc -m $_ipaddr | cut -d'=' -f2)
fi
echo -n "${_srcaddr}::${_gateway}:${_netmask}::"
fi
/sbin/ip $_ipv6_flag route show | grep -v default |\
grep ".*via.* $_netdev " | grep -v "^[[:space:]]*nexthop" |\
while read _route; do
_target=`echo $_route | cut -d ' ' -f1`
_nexthop=`echo $_route | cut -d ' ' -f3`
if [ "x" != "x"$_ipv6_flag ]; then
_target="[$_target]"
_nexthop="[$_nexthop]"
fi
echo "rd.route=$_target:$_nexthop:$_netdev"
done >> ${initdir}/etc/cmdline.d/45route-static.conf
kdump_handle_mulitpath_route $_netdev $_srcaddr
}
kdump_handle_mulitpath_route() {
local _netdev="$1" _srcaddr="$2" _ipv6_flag
local _target _nexthop _route _weight _max_weight _rule
if is_ipv6_address $_srcaddr; then
_ipv6_flag="-6"
fi
while IFS="" read _route; do
if [[ "$_route" =~ [[:space:]]+nexthop ]]; then
_route=$(echo "$_route" | sed -e 's/^[[:space:]]*//')
# Parse multipath route, using previous _target
[[ "$_target" == 'default' ]] && continue
[[ "$_route" =~ .*via.*\ $_netdev ]] || continue
_weight=`echo "$_route" | cut -d ' ' -f7`
if [[ "$_weight" -gt "$_max_weight" ]]; then
_nexthop=`echo "$_route" | cut -d ' ' -f3`
_max_weight=$_weight
if [ "x" != "x"$_ipv6_flag ]; then
_rule="rd.route=[$_target]:[$_nexthop]:$_netdev"
else
_rule="rd.route=$_target:$_nexthop:$_netdev"
fi
fi
else
[[ -n "$_rule" ]] && echo "$_rule"
_target=`echo "$_route" | cut -d ' ' -f1`
_rule="" _max_weight=0 _weight=0
fi
done >> ${initdir}/etc/cmdline.d/45route-static.conf\
< <(/sbin/ip $_ipv6_flag route show)
[[ -n $_rule ]] && echo $_rule >> ${initdir}/etc/cmdline.d/45route-static.conf
}
kdump_get_mac_addr() {
cat /sys/class/net/$1/address
}
#Bonding or team master modifies the mac address
#of its slaves, we should use perm address
kdump_get_perm_addr() {
local addr=$(ethtool -P $1 | sed -e 's/Permanent address: //')
if [ -z "$addr" ] || [ "$addr" = "00:00:00:00:00:00" ]
then
derror "Can't get the permanent address of $1"
else
echo "$addr"
fi
}
# Prefix kernel assigned names with "kdump-". EX: eth0 -> kdump-eth0
# Because kernel assigned names are not persistent between 1st and 2nd
# kernel. We could probably end up with eth0 being eth1, eth0 being
# eth1, and naming conflict happens.
kdump_setup_ifname() {
local _ifname
# If ifname already has 'kdump-' prefix, we must be switching from
# fadump to kdump. Skip prefixing 'kdump-' in this case as adding
# another prefix may truncate the ifname. Since an ifname with
# 'kdump-' is already persistent, this should be fine.
if [[ $1 =~ eth* ]] && [[ ! $1 =~ ^kdump-* ]]; then
_ifname="kdump-$1"
else
_ifname="$1"
fi
echo "$_ifname"
}
kdump_setup_bridge() {
local _netdev=$1
local _brif _dev _mac _kdumpdev
for _dev in `ls /sys/class/net/$_netdev/brif/`; do
_kdumpdev=$_dev
if kdump_is_bond "$_dev"; then
kdump_setup_bond "$_dev"
elif kdump_is_team "$_dev"; then
kdump_setup_team "$_dev"
elif kdump_is_vlan "$_dev"; then
kdump_setup_vlan "$_dev"
else
_mac=$(kdump_get_mac_addr $_dev)
_kdumpdev=$(kdump_setup_ifname $_dev)
echo -n " ifname=$_kdumpdev:$_mac" >> ${initdir}/etc/cmdline.d/41bridge.conf
fi
_brif+="$_kdumpdev,"
done
echo " bridge=$_netdev:$(echo $_brif | sed -e 's/,$//')" >> ${initdir}/etc/cmdline.d/41bridge.conf
}
kdump_setup_bond() {
local _netdev=$1
local _dev _mac _slaves _kdumpdev
for _dev in `cat /sys/class/net/$_netdev/bonding/slaves`; do
_mac=$(kdump_get_perm_addr $_dev)
_kdumpdev=$(kdump_setup_ifname $_dev)
echo -n " ifname=$_kdumpdev:$_mac" >> ${initdir}/etc/cmdline.d/42bond.conf
_slaves+="$_kdumpdev,"
done
echo -n " bond=$_netdev:$(echo $_slaves | sed 's/,$//')" >> ${initdir}/etc/cmdline.d/42bond.conf
# Get bond options specified in ifcfg
source_ifcfg_file $_netdev
bondoptions="$(echo :$BONDING_OPTS | sed 's/\s\+/,/')"
echo "$bondoptions" >> ${initdir}/etc/cmdline.d/42bond.conf
}
kdump_setup_team() {
local _netdev=$1
local _dev _mac _slaves _kdumpdev
for _dev in `teamnl $_netdev ports | awk -F':' '{print $2}'`; do
_mac=$(kdump_get_perm_addr $_dev)
_kdumpdev=$(kdump_setup_ifname $_dev)
echo -n " ifname=$_kdumpdev:$_mac" >> ${initdir}/etc/cmdline.d/44team.conf
_slaves+="$_kdumpdev,"
done
echo " team=$_netdev:$(echo $_slaves | sed -e 's/,$//')" >> ${initdir}/etc/cmdline.d/44team.conf
#Buggy version teamdctl outputs to stderr!
#Try to use the latest version of teamd.
teamdctl "$_netdev" config dump > ${initdir}/tmp/$$-$_netdev.conf
if [ $? -ne 0 ]
then
derror "teamdctl failed."
exit 1
fi
inst_dir /etc/teamd
inst_simple ${initdir}/tmp/$$-$_netdev.conf "/etc/teamd/$_netdev.conf"
rm -f ${initdir}/tmp/$$-$_netdev.conf
}
kdump_setup_vlan() {
local _netdev=$1
local _phydev="$(awk '/^Device:/{print $2}' /proc/net/vlan/"$_netdev")"
local _netmac="$(kdump_get_mac_addr $_phydev)"
local _kdumpdev
#Just support vlan over bond, it is not easy
#to support all other complex setup
if kdump_is_bridge "$_phydev"; then
derror "Vlan over bridge is not supported!"
exit 1
elif kdump_is_team "$_phydev"; then
derror "Vlan over team is not supported!"
exit 1
elif kdump_is_bond "$_phydev"; then
kdump_setup_bond "$_phydev"
echo " vlan=$_netdev:$_phydev" > ${initdir}/etc/cmdline.d/43vlan.conf
else
_kdumpdev="$(kdump_setup_ifname $_phydev)"
echo " vlan=$_netdev:$_kdumpdev ifname=$_kdumpdev:$_netmac" > ${initdir}/etc/cmdline.d/43vlan.conf
fi
}
# setup s390 znet cmdline
# $1: netdev name
kdump_setup_znet() {
local _options=""
source_ifcfg_file $1
for i in $OPTIONS; do
_options=${_options},$i
done
echo rd.znet=${NETTYPE},${SUBCHANNELS}${_options} > ${initdir}/etc/cmdline.d/30znet.conf
}
# Setup dracut to bringup a given network interface
kdump_setup_netdev() {
local _netdev=$1 _srcaddr=$2
local _static _proto _ip_conf _ip_opts _ifname_opts
local _netmac=$(kdump_get_mac_addr $_netdev)
if [ "$(uname -m)" = "s390x" ]; then
kdump_setup_znet $_netdev
fi
_static=$(kdump_static_ip $_netdev $_srcaddr)
if [ -n "$_static" ]; then
_proto=none
elif is_ipv6_address $_srcaddr; then
_proto=either6
else
_proto=dhcp
fi
_ip_conf="${initdir}/etc/cmdline.d/40ip.conf"
_ip_opts=" ip=${_static}$(kdump_setup_ifname $_netdev):${_proto}"
# dracut doesn't allow duplicated configuration for same NIC, even they're exactly the same.
# so we have to avoid adding duplicates
# We should also check /proc/cmdline for existing ip=xx arg.
# For example, iscsi boot will specify ip=xxx arg in cmdline.
if [ ! -f $_ip_conf ] || ! grep -q $_ip_opts $_ip_conf &&\
! grep -q "ip=[^[:space:]]*$_netdev" /proc/cmdline; then
echo "$_ip_opts" >> $_ip_conf
fi
if kdump_is_bridge "$_netdev"; then
kdump_setup_bridge "$_netdev"
elif kdump_is_bond "$_netdev"; then
kdump_setup_bond "$_netdev"
elif kdump_is_team "$_netdev"; then
kdump_setup_team "$_netdev"
elif kdump_is_vlan "$_netdev"; then
kdump_setup_vlan "$_netdev"
else
_ifname_opts=" ifname=$(kdump_setup_ifname $_netdev):$_netmac"
echo "$_ifname_opts" >> $_ip_conf
fi
kdump_setup_dns "$_netdev"
}
get_ip_route_field()
{
if `echo $1 | grep -q $2`; then
echo ${1##*$2} | cut -d ' ' -f1
fi
}
#Function:kdump_install_net
#$1: config values of net line in kdump.conf
#$2: srcaddr of network device
kdump_install_net() {
local _server _netdev _srcaddr _route _serv_tmp
local config_val="$1"
_server=$(get_remote_host $config_val)
if is_hostname $_server; then
_serv_tmp=`getent ahosts $_server | grep -v : | head -n 1`
if [ -z "$_serv_tmp" ]; then
_serv_tmp=`getent ahosts $_server | head -n 1`
fi
_server=`echo $_serv_tmp | cut -d' ' -f1`
fi
_route=`/sbin/ip -o route get to $_server 2>&1`
[ $? != 0 ] && echo "Bad kdump location: $config_val" && exit 1
#the field in the ip output changes if we go to another subnet
_srcaddr=$(get_ip_route_field "$_route" "src")
_netdev=$(get_ip_route_field "$_route" "dev")
kdump_setup_netdev "${_netdev}" "${_srcaddr}"
#save netdev used for kdump as cmdline
# Whoever calling kdump_install_net() is setting up the default gateway,
# ie. bootdev/kdumpnic. So don't override the setting if calling
# kdump_install_net() for another time. For example, after setting eth0 as
# the default gate way for network dump, eth1 in the fence kdump path will
# call kdump_install_net again and we don't want eth1 to be the default
# gateway.
if [ ! -f ${initdir}/etc/cmdline.d/60kdumpnic.conf ] &&
[ ! -f ${initdir}/etc/cmdline.d/70bootdev.conf ]; then
echo "kdumpnic=$(kdump_setup_ifname $_netdev)" > ${initdir}/etc/cmdline.d/60kdumpnic.conf
echo "bootdev=$(kdump_setup_ifname $_netdev)" > ${initdir}/etc/cmdline.d/70bootdev.conf
fi
}
default_dump_target_install_conf()
{
local _target _fstype
local _mntpoint _save_path
is_user_configured_dump_target && return
_save_path=$(get_option_value "path")
[ -z "$_save_path" ] && _save_path=$DEFAULT_PATH
# strip the duplicated "/"
_save_path=$(echo $_save_path | tr -s /)
_mntpoint=$(get_mntpoint_from_path $_save_path)
_target=$(get_target_from_path $_save_path)
if is_atomic && is_bind_mount $_mntpoint; then
_save_path=${_save_path##"$_mntpoint"}
# the real dump path in the 2nd kernel, if the mount point is bind mounted.
_save_path=$(get_bind_mount_directory $_mntpoint)/$_save_path
_mntpoint=$(get_mntpoint_from_target $_target)
# the absolute path in the 1st kernel
_save_path=$_mntpoint/$_save_path
fi
_fstype=$(get_fs_type_from_target $_target)
if is_fs_type_nfs $_fstype; then
kdump_install_net "$_target"
_fstype="nfs"
else
_target=$(kdump_get_persistent_dev $_target)
fi
echo "$_fstype $_target" >> ${initdir}/tmp/$$-kdump.conf
# strip the duplicated "/"
_save_path=$(echo $_save_path | tr -s /)
# don't touch the path under root mount
if [ "$_mntpoint" != "/" ]; then
_save_path=${_save_path##"$_mntpoint"}
fi
#erase the old path line, then insert the parsed path
sed -i "/^path/d" ${initdir}/tmp/$$-kdump.conf
echo "path $_save_path" >> ${initdir}/tmp/$$-kdump.conf
}
adjust_bind_mount_path()
{
local _target=$1
local _save_path=$(get_option_value "path")
[ -z "$_save_path" ] && _save_path=$DEFAULT_PATH
# strip the duplicated "/"
_save_path=$(echo $_save_path | tr -s /)
local _absolute_save_path=$(get_mntpoint_from_target $_target)/$_save_path
_absolute_save_path=$(echo "$_absolute_save_path" | tr -s /)
local _mntpoint=$(get_mntpoint_from_path $_absolute_save_path)
if is_bind_mount $_mntpoint; then
_save_path=${_absolute_save_path##"$_mntpoint"}
# the real dump path in the 2nd kernel, if the mount point is bind mounted.
_save_path=$(get_bind_mount_directory $_mntpoint)/$_save_path
#erase the old path line, then insert the parsed path
sed -i "/^path/d" ${initdir}/tmp/$$-kdump.conf
echo "path $_save_path" >> ${initdir}/tmp/$$-kdump.conf
fi
}
#install kdump.conf and what user specifies in kdump.conf
kdump_install_conf() {
local _opt _val _pdev
sed -ne '/^#/!p' /etc/kdump.conf > ${initdir}/tmp/$$-kdump.conf
while read _opt _val;
do
# remove inline comments after the end of a directive.
_val=$(strip_comments $_val)
case "$_opt" in
raw)
_pdev=$(persistent_policy="by-id" kdump_get_persistent_dev $_val)
sed -i -e "s#^$_opt[[:space:]]\+$_val#$_opt $_pdev#" ${initdir}/tmp/$$-kdump.conf
;;
ext[234]|xfs|btrfs|minix)
_pdev=$(kdump_get_persistent_dev $_val)
sed -i -e "s#^$_opt[[:space:]]\+$_val#$_opt $_pdev#" ${initdir}/tmp/$$-kdump.conf
if is_atomic; then
adjust_bind_mount_path "$_val"
fi
;;
ssh|nfs)
kdump_install_net "$_val"
;;
dracut_args)
if [[ $(get_dracut_args_fstype "$_val") = nfs* ]] ; then
kdump_install_net "$(get_dracut_args_target "$_val")"
fi
;;
kdump_pre|kdump_post|extra_bins)
dracut_install $_val
;;
core_collector)
dracut_install "${_val%%[[:blank:]]*}"
;;
esac
done < /etc/kdump.conf
default_dump_target_install_conf
kdump_configure_fence_kdump "${initdir}/tmp/$$-kdump.conf"
inst "${initdir}/tmp/$$-kdump.conf" "/etc/kdump.conf"
rm -f ${initdir}/tmp/$$-kdump.conf
}
# Default sysctl parameters should suffice for kdump kernel.
# Remove custom configurations sysctl.conf & sysctl.d/*
remove_sysctl_conf() {
# As custom configurations like vm.min_free_kbytes can lead
# to OOM issues in kdump kernel, avoid them
rm -f "${initdir}/etc/sysctl.conf"
rm -rf "${initdir}/etc/sysctl.d"
rm -rf "${initdir}/run/sysctl.d"
rm -rf "${initdir}/usr/lib/sysctl.d"
}
kdump_iscsi_get_rec_val() {
local result
# The open-iscsi 742 release changed to using flat files in
# /var/lib/iscsi.
result=$(/sbin/iscsiadm --show -m session -r ${1} | grep "^${2} = ")
result=${result##* = }
echo $result
}
kdump_get_iscsi_initiator() {
local _initiator
local initiator_conf="/etc/iscsi/initiatorname.iscsi"
[ -f "$initiator_conf" ] || return 1
while read _initiator; do
[ -z "${_initiator%%#*}" ] && continue # Skip comment lines
case $_initiator in
InitiatorName=*)
initiator=${_initiator#InitiatorName=}
echo "rd.iscsi.initiator=${initiator}"
return 0;;
*) ;;
esac
done < ${initiator_conf}
return 1
}
# Figure out iBFT session according to session type
is_ibft() {
[ "$(kdump_iscsi_get_rec_val $1 "node.discovery_type")" = fw ]
}
kdump_setup_iscsi_device() {
local path=$1
local tgt_name; local tgt_ipaddr;
local username; local password; local userpwd_str;
local username_in; local password_in; local userpwd_in_str;
local netdev
local srcaddr
local idev
local netroot_str ; local initiator_str;
local netroot_conf="${initdir}/etc/cmdline.d/50iscsi.conf"
local initiator_conf="/etc/iscsi/initiatorname.iscsi"
dinfo "Found iscsi component $1"
# Check once before getting explicit values, so we can bail out early,
# e.g. in case of pure-hardware(all-offload) iscsi.
if ! /sbin/iscsiadm -m session -r ${path} &>/dev/null ; then
return 1
fi
if is_ibft ${path}; then
return
fi
# Remove software iscsi cmdline generated by 95iscsi,
# and let kdump regenerate here.
rm -f ${initdir}/etc/cmdline.d/95iscsi.conf
tgt_name=$(kdump_iscsi_get_rec_val ${path} "node.name")
tgt_ipaddr=$(kdump_iscsi_get_rec_val ${path} "node.conn\[0\].address")
# get and set username and password details
username=$(kdump_iscsi_get_rec_val ${path} "node.session.auth.username")
[ "$username" == "<empty>" ] && username=""
password=$(kdump_iscsi_get_rec_val ${path} "node.session.auth.password")
[ "$password" == "<empty>" ] && password=""
username_in=$(kdump_iscsi_get_rec_val ${path} "node.session.auth.username_in")
[ -n "$username" ] && userpwd_str="$username:$password"
# get and set incoming username and password details
[ "$username_in" == "<empty>" ] && username_in=""
password_in=$(kdump_iscsi_get_rec_val ${path} "node.session.auth.password_in")
[ "$password_in" == "<empty>" ] && password_in=""
[ -n "$username_in" ] && userpwd_in_str=":$username_in:$password_in"
netdev=$(/sbin/ip route get to ${tgt_ipaddr} | \
sed 's|.*dev \(.*\).*|\1|g')
srcaddr=$(echo $netdev | awk '{ print $3; exit }')
netdev=$(echo $netdev | awk '{ print $1; exit }')
kdump_setup_netdev $netdev $srcaddr
# prepare netroot= command line
# FIXME: Do we need to parse and set other parameters like protocol, port
# iscsi_iface_name, netdev_name, LUN etc.
if is_ipv6_address $tgt_ipaddr; then
tgt_ipaddr="[$tgt_ipaddr]"
fi
netroot_str="netroot=iscsi:${userpwd_str}${userpwd_in_str}@$tgt_ipaddr::::$tgt_name"
[[ -f $netroot_conf ]] || touch $netroot_conf
# If netroot target does not exist already, append.
if ! grep -q $netroot_str $netroot_conf; then
echo $netroot_str >> $netroot_conf
dinfo "Appended $netroot_str to $netroot_conf"
fi
# Setup initator
initiator_str=$(kdump_get_iscsi_initiator)
[ $? -ne "0" ] && derror "Failed to get initiator name" && return 1
# If initiator details do not exist already, append.
if ! grep -q "$initiator_str" $netroot_conf; then
echo "$initiator_str" >> $netroot_conf
dinfo "Appended "$initiator_str" to $netroot_conf"
fi
}
kdump_check_iscsi_targets () {
# If our prerequisites are not met, fail anyways.
type -P iscsistart >/dev/null || return 1
kdump_check_setup_iscsi() (
local _dev
_dev=$1
[[ -L /sys/dev/block/$_dev ]] || return
cd "$(readlink -f /sys/dev/block/$_dev)"
until [[ -d sys || -d iscsi_session ]]; do
cd ..
done
[[ -d iscsi_session ]] && kdump_setup_iscsi_device "$PWD"
)
[[ $hostonly ]] || [[ $mount_needs ]] && {
for_each_host_dev_and_slaves_all kdump_check_setup_iscsi
}
}
# retrieves fence_kdump nodes from Pacemaker cluster configuration
get_pcs_fence_kdump_nodes() {
local nodes
# get cluster nodes from cluster cib, get interface and ip address
nodelist=`pcs cluster cib | xmllint --xpath "/cib/status/node_state/@uname" -`
# nodelist is formed as 'uname="node1" uname="node2" ... uname="nodeX"'
# we need to convert each to node1, node2 ... nodeX in each iteration
for node in ${nodelist}; do
# convert $node from 'uname="nodeX"' to 'nodeX'
eval $node
nodename=$uname
# Skip its own node name
if [ "$nodename" = `hostname` -o "$nodename" = `hostname -s` ]; then
continue
fi
nodes="$nodes $nodename"
done
echo $nodes
}
# retrieves fence_kdump args from config file
get_pcs_fence_kdump_args() {
if [ -f $FENCE_KDUMP_CONFIG_FILE ]; then
. $FENCE_KDUMP_CONFIG_FILE
echo $FENCE_KDUMP_OPTS
fi
}
# setup fence_kdump in cluster
# setup proper network and install needed files
kdump_configure_fence_kdump () {
local kdump_cfg_file=$1
local nodes
local args
if is_generic_fence_kdump; then
nodes=$(get_option_value "fence_kdump_nodes")
elif is_pcs_fence_kdump; then
nodes=$(get_pcs_fence_kdump_nodes)
# set appropriate options in kdump.conf
echo "fence_kdump_nodes $nodes" >> ${kdump_cfg_file}
args=$(get_pcs_fence_kdump_args)
if [ -n "$args" ]; then
echo "fence_kdump_args $args" >> ${kdump_cfg_file}
fi
else
# fence_kdump not configured
return 1
fi
# setup network for each node
for node in ${nodes}; do
kdump_install_net $node
done
dracut_install /etc/hosts
dracut_install /etc/nsswitch.conf
dracut_install $FENCE_KDUMP_SEND
}
# Install a random seed used to feed /dev/urandom
# By the time kdump service starts, /dev/uramdom is already fed by systemd
kdump_install_random_seed() {
local poolsize=`cat /proc/sys/kernel/random/poolsize`
if [ ! -d ${initdir}/var/lib/ ]; then
mkdir -p ${initdir}/var/lib/
fi
dd if=/dev/urandom of=${initdir}/var/lib/random-seed \
bs=$poolsize count=1 2> /dev/null
}
install() {
kdump_install_conf
remove_sysctl_conf
if is_ssh_dump_target; then
kdump_install_random_seed
fi
dracut_install -o /etc/adjtime /etc/localtime
inst "$moddir/monitor_dd_progress" "/kdumpscripts/monitor_dd_progress"
chmod +x ${initdir}/kdumpscripts/monitor_dd_progress
inst "/bin/dd" "/bin/dd"
inst "/bin/tail" "/bin/tail"
inst "/bin/date" "/bin/date"
inst "/bin/sync" "/bin/sync"
inst "/bin/cut" "/bin/cut"
inst "/bin/head" "/bin/head"
inst "/sbin/makedumpfile" "/sbin/makedumpfile"
inst "/sbin/vmcore-dmesg" "/sbin/vmcore-dmesg"
inst "/lib/kdump/kdump-lib.sh" "/lib/kdump-lib.sh"
inst "/lib/kdump/kdump-lib-initramfs.sh" "/lib/kdump-lib-initramfs.sh"
inst "$moddir/kdump.sh" "/usr/bin/kdump.sh"
inst "$moddir/kdump-capture.service" "$systemdsystemunitdir/kdump-capture.service"
ln_r "$systemdsystemunitdir/kdump-capture.service" "$systemdsystemunitdir/initrd.target.wants/kdump-capture.service"
inst "$moddir/kdump-error-handler.sh" "/usr/bin/kdump-error-handler.sh"
inst "$moddir/kdump-error-handler.service" "$systemdsystemunitdir/kdump-error-handler.service"
# Replace existing emergency service and emergency target
cp "$moddir/kdump-emergency.service" "$initdir/$systemdsystemunitdir/emergency.service"
cp "$moddir/kdump-emergency.target" "$initdir/$systemdsystemunitdir/emergency.target"
# Also redirect dracut-emergency to kdump error handler
ln_r "$systemdsystemunitdir/emergency.service" "$systemdsystemunitdir/dracut-emergency.service"
# Check for all the devices and if any device is iscsi, bring up iscsi
# target. Ideally all this should be pushed into dracut iscsi module
# at some point of time.
kdump_check_iscsi_targets
# For the lvm type target under kdump, in /etc/lvm/lvm.conf we can
# safely replace "reserved_memory=XXXX"(default value is 8192) with
# "reserved_memory=1024" to lower memory pressure under kdump. We do
# it unconditionally here, if "/etc/lvm/lvm.conf" doesn't exist, it
# actually does nothing.
sed -i -e \
's/\(^[[:space:]]*reserved_memory[[:space:]]*=\)[[:space:]]*[[:digit:]]*/\1 1024/' \
${initdir}/etc/lvm/lvm.conf &>/dev/null
# Kdump turns out to require longer default systemd mount timeout
# than 1st kernel(90s by default), we use default 300s for kdump.
grep -r "^[[:space:]]*DefaultTimeoutStartSec=" ${initdir}/etc/systemd/system.conf* &>/dev/null
if [ $? -ne 0 ]; then
mkdir -p ${initdir}/etc/systemd/system.conf.d
echo "[Manager]" > ${initdir}/etc/systemd/system.conf.d/kdump.conf
echo "DefaultTimeoutStartSec=300s" >> ${initdir}/etc/systemd/system.conf.d/kdump.conf
fi
}

View file

@ -0,0 +1,28 @@
#!/bin/sh
SRC_FILE_MB=$1
while true
do
DD_PID=`pidof dd`
if [ -n "$DD_PID" ]; then
break
fi
done
while true
do
sleep 5
if [ ! -d /proc/$DD_PID ]; then
break
fi
kill -s USR1 $DD_PID
CURRENT_SIZE=`tail -n 1 /tmp/dd_progress_file | sed "s/[^0-9].*//g"`
[ -n "$CURRENT_SIZE" ] && {
CURRENT_MB=$(($CURRENT_SIZE / 1048576))
echo -e "Copied $CURRENT_MB MB / $SRC_FILE_MB MB\r"
}
done
rm -f /tmp/dd_progress_file

67
early-kdump-howto.txt Normal file
View file

@ -0,0 +1,67 @@
Early Kdump HOWTO
Introduction
------------
Kdump service starts too late, so early crashes will have no chance to get
kdump kernel booting, this will cause crash information to be lost. It is
necessary to add a dracut module in order to load crash kernel and initramfs
as early as possible. You can provide "rd.earlykdump" in grub commandline
to enable, then the early kdump will load those files like the normal kdump,
which is disabled by default.
For the normal kdump service, it can check whether the early kdump has loaded
the crash kernel and initramfs. It has no conflict with the early kdump.
How to configure early kdump
----------------------------
We assume if you're reading this document, you should already have kexec-tools
installed.
You can rebuild the initramfs with earlykdump support with below steps:
1. start kdump service to make sure kdump initramfs is created.
# systemctl start kdump
NOTE: If a crash occurs during boot process, early kdump captures a vmcore
and reboot the system by default, so the system might go into crash loop.
You can avoid such a crash loop by adding the following settings, which
power off the system after dump capturing, to kdump.conf in advance:
final_action poweroff
failure_action poweroff
For the failure_action, you can choose anything other than "reboot".
2. rebuild system initramfs with earlykdump support.
# dracut --add earlykdump
3. add rd.earlykdump in grub kernel command line.
Note: earlykdump initramfs size will be large because it includes vmlinuz and
kdump initramfs. And for step 2 if you are sure to overwrite system initramfs
you can backup the original initramfs and use "--force" option.
After making said changes, reboot your system to take effect. Of course, if you
want to disable early kdump, you can simply remove "rd.earlykdump" from kernel
boot parameters in grub, and reboot system like above.
Once the boot is completed, you can check the status of the early kdump support
on the command prompt:
# journalctl -x|grep early-kdump
Then, you will see some useful logs, for exapmle:
1. if early kdump is successful.
Mar 09 09:57:56 localhost.localdomain dracut-cmdline[190]: early-kdump is enabled.
Mar 09 09:57:56 localhost.localdomain dracut-cmdline[190]: kexec: loaded early-
kdump kernel
2. if early kdump is disabled.
Mar 09 10:02:47 localhost.localdomain dracut-cmdline[189]: early-kdump is disabled.
Limitation
----------
At present, early kdump doesn't support fadump.

252
fadump-howto.txt Normal file
View file

@ -0,0 +1,252 @@
Firmware assisted dump (fadump) HOWTO
Introduction
Firmware assisted dump is a new feature in the 3.4 mainline kernel supported
only on powerpc architecture. The goal of firmware-assisted dump is to enable
the dump of a crashed system, and to do so from a fully-reset system, and to
minimize the total elapsed time until the system is back in production use. A
complete documentation on implementation can be found at
Documentation/powerpc/firmware-assisted-dump.txt in upstream linux kernel tree
from 3.4 version and above.
Please note that the firmware-assisted dump feature is only available on Power6
and above systems with recent firmware versions.
Overview
Fadump
Fadump is a robust kernel crash dumping mechanism to get reliable kernel crash
dump with assistance from firmware. This approach does not use kexec, instead
firmware assists in booting the kdump kernel while preserving memory contents.
Unlike kdump, the system is fully reset, and loaded with a fresh copy of the
kernel. In particular, PCI and I/O devices are reinitialized and are in a
clean, consistent state. This second kernel, often called a capture kernel,
boots with very little memory and captures the dump image.
The first kernel registers the sections of memory with the Power firmware for
dump preservation during OS initialization. These registered sections of memory
are reserved by the first kernel during early boot. When a system crashes, the
Power firmware fully resets the system, preserves all the system memory
contents, save the low memory (boot memory of size larger of 5% of system
RAM or 256MB) of RAM to the previous registered region. It will also save
system registers, and hardware PTE's.
Fadump is supported only on ppc64 platform. The standard kernel and capture
kernel are one and the same on ppc64.
If you're reading this document, you should already have kexec-tools
installed. If not, you install it via the following command:
# yum install kexec-tools
Fadump Operational Flow:
Like kdump, fadump also exports the ELF formatted kernel crash dump through
/proc/vmcore. Hence existing kdump infrastructure can be used to capture fadump
vmcore. The idea is to keep the functionality transparent to end user. From
user perspective there is no change in the way kdump init script works.
However, unlike kdump, fadump does not pre-load kdump kernel and initrd into
reserved memory, instead it always uses default OS initrd during second boot
after crash. Hence, for fadump, we rebuild the new kdump initrd and replace it
with default initrd. Before replacing existing default initrd we take a backup
of original default initrd for user's reference. The dracut package has been
enhanced to rebuild the default initrd with vmcore capture steps. The initrd
image is rebuilt as per the configuration in /etc/kdump.conf file.
The control flow of fadump works as follows:
01. System panics.
02. At the crash, kernel informs power firmware that kernel has crashed.
03. Firmware takes the control and reboots the entire system preserving
only the memory (resets all other devices).
04. The reboot follows the normal booting process (non-kexec).
05. The boot loader loads the default kernel and initrd from /boot
06. The default initrd loads and runs /init
07. dracut-kdump.sh script present in fadump aware default initrd checks if
'/proc/device-tree/rtas/ibm,kernel-dump' file exists before executing
steps to capture vmcore.
(This check will help to bypass the vmcore capture steps during normal boot
process.)
09. Captures dump according to /etc/kdump.conf
10. Is dump capture successful (yes goto 12, no goto 11)
11. Perform the failure action specified in /etc/kdump.conf
(The default failure action is reboot, if unspecified)
12. Perform the final action specified in /etc/kdump.conf
(The default final action is reboot, if unspecified)
How to configure fadump:
Again, we assume if you're reading this document, you should already have
kexec-tools installed. If not, you install it via the following command:
# yum install kexec-tools
To be able to do much of anything interesting in the way of debug analysis,
you'll also need to install the kernel-debuginfo package, of the same arch
as your running kernel, and the crash utility:
# yum --enablerepo=\*debuginfo install kernel-debuginfo.$(uname -m) crash
Next up, we need to modify some boot parameters to enable firmware assisted
dump. With the help of grubby, it's very easy to append "fadump=on" to the end
of your kernel boot parameters. Optionally, user can also append
'fadump_reserve_mem=X' kernel cmdline to specify size of the memory to reserve
for boot memory dump preservation.
# grubby --args="fadump=on" --update-kernel=/boot/vmlinuz-`uname -r`
The term 'boot memory' means size of the low memory chunk that is required for
a kernel to boot successfully when booted with restricted memory. By default,
the boot memory size will be the larger of 5% of system RAM or 256MB.
Alternatively, user can also specify boot memory size through boot parameter
'fadump_reserve_mem=' which will override the default calculated size. Use this
option if default boot memory size is not sufficient for second kernel to boot
successfully.
After making said changes, reboot your system, so that the specified memory is
reserved and left untouched by the normal system. Take note that the output of
'free -m' will show X MB less memory than without this parameter, which is
expected. If you see OOM (Out Of Memory) error messages while loading capture
kernel, then you should bump up the memory reservation size.
Now that you've got that reserved memory region set up, you want to turn on
the kdump init script:
# systemctl enable kdump.service
Then, start up kdump as well:
# systemctl start kdump.service
This should turn on the firmware assisted functionality in kernel by
echo'ing 1 to /sys/kernel/fadump_registered, leaving the system ready
to capture a vmcore upon crashing. To test this out, you can force-crash
your system by echo'ing a c into /proc/sysrq-trigger:
# echo c > /proc/sysrq-trigger
You should see some panic output, followed by the system reset and booting into
fresh copy of kernel. When default initrd loads and runs /init, vmcore should
be copied out to disk (by default, in /var/crash/<YYYY.MM.DD-HH:MM:SS>/vmcore),
then the system rebooted back into your normal kernel.
Once back to your normal kernel, you can use the previously installed crash
kernel in conjunction with the previously installed kernel-debuginfo to
perform postmortem analysis:
# crash /usr/lib/debug/lib/modules/2.6.17-1.2621.el5/vmlinux
/var/crash/2006-08-23-15:34/vmcore
crash> bt
and so on...
Saving vmcore-dmesg.txt
----------------------
Kernel log bufferes are one of the most important information available
in vmcore. Now before saving vmcore, kernel log bufferes are extracted
from /proc/vmcore and saved into a file vmcore-dmesg.txt. After
vmcore-dmesg.txt, vmcore is saved. Destination disk and directory for
vmcore-dmesg.txt is same as vmcore. Note that kernel log buffers will
not be available if dump target is raw device.
Dump Triggering methods:
This section talks about the various ways, other than a Kernel Panic, in which
fadump can be triggered. The following methods assume that fadump is configured
on your system, with the scripts enabled as described in the section above.
1) AltSysRq C
FAdump can be triggered with the combination of the 'Alt','SysRq' and 'C'
keyboard keys. Please refer to the following link for more details:
https://fedoraproject.org/wiki/QA/Sysrq
In addition, on PowerPC boxes, fadump can also be triggered via Hardware
Management Console(HMC) using 'Ctrl', 'O' and 'C' keyboard keys.
2) Kernel OOPs
If we want to generate a dump everytime the Kernel OOPses, we can achieve this
by setting the 'Panic On OOPs' option as follows:
# echo 1 > /proc/sys/kernel/panic_on_oops
3) PowerPC specific methods:
On IBM PowerPC machines, issuing a soft reset invokes the XMON debugger(if
XMON is configured). To configure XMON one needs to compile the kernel with
the CONFIG_XMON and CONFIG_XMON_DEFAULT options, or by compiling with
CONFIG_XMON and booting the kernel with xmon=on option.
Following are the ways to remotely issue a soft reset on PowerPC boxes, which
would drop you to XMON. Pressing a 'X' (capital alphabet X) followed by an
'Enter' here will trigger the dump.
3.1) HMC
Hardware Management Console(HMC) available on Power4 and Power5 machines allow
partitions to be reset remotely. This is specially useful in hang situations
where the system is not accepting any keyboard inputs.
Once you have HMC configured, the following steps will enable you to trigger
fadump via a soft reset:
On Power4
Using GUI
* In the right pane, right click on the partition you wish to dump.
* Select "Operating System->Reset".
* Select "Soft Reset".
* Select "Yes".
Using HMC Commandline
# reset_partition -m <machine> -p <partition> -t soft
On Power5
Using GUI
* In the right pane, right click on the partition you wish to dump.
* Select "Restart Partition".
* Select "Dump".
* Select "OK".
Using HMC Commandline
# chsysstate -m <managed system name> -n <lpar name> -o dumprestart -r lpar
3.2) Blade Management Console for Blade Center
To initiate a dump operation, go to Power/Restart option under "Blade Tasks" in
the Blade Management Console. Select the corresponding blade for which you want
to initate the dump and then click "Restart blade with NMI". This issues a
system reset and invokes xmon debugger.
Advanced Setups & Failure action:
Kdump and fadump exhibit similar behavior in terms of setup & failure action.
For fadump advanced setup related information see section "Advanced Setups" in
"kexec-kdump-howto.txt" document. Refer to "Failure action" section in "kexec-
kdump-howto.txt" document for fadump failure action related information.
Compression and filtering
Refer "Compression and filtering" section in "kexec-kdump-howto.txt" document.
Compression and filtering are same for kdump & fadump.
Notes on rootfs mount:
Dracut is designed to mount rootfs by default. If rootfs mounting fails it
will refuse to go on. So fadump leaves rootfs mounting to dracut currently.
We make the assumtion that proper root= cmdline is being passed to dracut
initramfs for the time being. If you need modify "KDUMP_COMMANDLINE=" in
/etc/sysconfig/kdump, you will need to make sure that appropriate root=
options are copied from /proc/cmdline. In general it is best to append
command line options using "KDUMP_COMMANDLINE_APPEND=" instead of replacing
the original command line completely.

22
kdump-dep-generator.sh Normal file
View file

@ -0,0 +1,22 @@
#!/bin/sh
# More details about systemd generator:
# http://www.freedesktop.org/wiki/Software/systemd/Generators/
. /usr/lib/kdump/kdump-lib.sh
# If invokded with no arguments for testing purpose, output to /tmp to
# avoid overriding the existing.
dest_dir="/tmp"
if [ -n "$1" ]; then
dest_dir=$1
fi
systemd_dir=/usr/lib/systemd/system
kdump_wants=$dest_dir/kdump.service.wants
if is_ssh_dump_target; then
mkdir -p $kdump_wants
ln -sf $systemd_dir/network-online.target $kdump_wants/
fi

View file

@ -0,0 +1,91 @@
Kdump-in-cluster-environment HOWTO
Introduction
Kdump is a kexec based crash dumping mechansim for Linux. This docuement
illustrate how to configure kdump in cluster environment to allow the kdump
crash recovery service complete without being preempted by traditional power
fencing methods.
Overview
Kexec/Kdump
Details about Kexec/Kdump are available in Kexec-Kdump-howto file and will not
be described here.
fence_kdump
fence_kdump is an I/O fencing agent to be used with the kdump crash recovery
service. When the fence_kdump agent is invoked, it will listen for a message
from the failed node that acknowledges that the failed node is executing the
kdump crash kernel. Note that fence_kdump is not a replacement for traditional
fencing methods. The fence_kdump agent can only detect that a node has entered
the kdump crash recovery service. This allows the kdump crash recovery service
complete without being preempted by traditional power fencing methods.
fence_kdump_send
fence_kdump_send is a utility used to send messages that acknowledge that the
node itself has entered the kdump crash recovery service. The fence_kdump_send
utility is typically run in the kdump kernel after a cluster node has
encountered a kernel panic. Once the cluster node has entered the kdump crash
recovery service, fence_kdump_send will periodically send messages to all
cluster nodes. When the fence_kdump agent receives a valid message from the
failed nodes, fencing is complete.
How to configure Pacemaker cluster environment:
If we want to use kdump in Pacemaker cluster environment, fence-agents-kdump
should be installed in every nodes in the cluster. You can achieve this via
the following command:
# yum install -y fence-agents-kdump
Next is to add kdump_fence to the cluster. Assuming that the cluster consists
of three nodes, they are node1, node2 and node3, and use Pacemaker to perform
resource management and pcs as cli configuration tool.
With pcs it is easy to add a stonith resource to the cluster. For example, add
a stonith resource named mykdumpfence with fence type of fence_kdump via the
following commands:
# pcs stonith create mykdumpfence fence_kdump \
pcmk_host_check=static-list pcmk_host_list="node1 node2 node3"
# pcs stonith update mykdumpfence pcmk_monitor_action=metadata --force
# pcs stonith update mykdumpfence pcmk_status_action=metadata --force
# pcs stonith update mykdumpfence pcmk_reboot_action=off --force
Then enable stonith
# pcs property set stonith-enabled=true
How to configure kdump:
Actually there are two ways how to configure fence_kdump support:
1) Pacemaker based clusters
If you have successfully configured fence_kdump in Pacemaker, there is
no need to add some special configuration in kdump. So please refer to
Kexec-Kdump-howto file for more information.
2) Generic clusters
For other types of clusters there are two configuration options in
kdump.conf which enables fence_kdump support:
fence_kdump_nodes <node(s)>
Contains list of cluster node(s) separated by space to send
fence_kdump notification to (this option is mandatory to enable
fence_kdump)
fence_kdump_args <arg(s)>
Command line arguments for fence_kdump_send (it can contain
all valid arguments except hosts to send notification to)
These options will most probably be configured by your cluster software,
so please refer to your cluster documentation how to enable fence_kdump
support.
Please be aware that these two ways cannot be combined and 2) has precedence
over 1). It means that if fence_kdump is configured using fence_kdump_nodes
and fence_kdump_args options in kdump.conf, Pacemaker configuration is not
used even if it exists.

184
kdump-lib-initramfs.sh Executable file
View file

@ -0,0 +1,184 @@
# These variables and functions are useful in 2nd kernel
. /lib/kdump-lib.sh
KDUMP_PATH="/var/crash"
CORE_COLLECTOR=""
DEFAULT_CORE_COLLECTOR="makedumpfile -l --message-level 1 -d 31"
DMESG_COLLECTOR="/sbin/vmcore-dmesg"
FAILURE_ACTION="systemctl reboot -f"
DATEDIR=`date +%Y-%m-%d-%T`
HOST_IP='127.0.0.1'
DUMP_INSTRUCTION=""
SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa"
KDUMP_SCRIPT_DIR="/kdumpscripts"
DD_BLKSIZE=512
FINAL_ACTION="systemctl reboot -f"
KDUMP_CONF="/etc/kdump.conf"
KDUMP_PRE=""
KDUMP_POST=""
NEWROOT="/sysroot"
get_kdump_confs()
{
local config_opt config_val
while read config_opt config_val;
do
# remove inline comments after the end of a directive.
config_val=$(strip_comments $config_val)
case "$config_opt" in
path)
KDUMP_PATH="$config_val"
;;
core_collector)
[ -n "$config_val" ] && CORE_COLLECTOR="$config_val"
;;
sshkey)
if [ -f "$config_val" ]; then
SSH_KEY_LOCATION=$config_val
fi
;;
kdump_pre)
KDUMP_PRE="$config_val"
;;
kdump_post)
KDUMP_POST="$config_val"
;;
fence_kdump_args)
FENCE_KDUMP_ARGS="$config_val"
;;
fence_kdump_nodes)
FENCE_KDUMP_NODES="$config_val"
;;
failure_action|default)
case $config_val in
shell)
FAILURE_ACTION="kdump_emergency_shell"
;;
reboot)
FAILURE_ACTION="systemctl reboot -f"
;;
halt)
FAILURE_ACTION="halt"
;;
poweroff)
FAILURE_ACTION="systemctl poweroff -f"
;;
dump_to_rootfs)
FAILURE_ACTION="dump_to_rootfs"
;;
esac
;;
final_action)
case $config_val in
reboot)
FINAL_ACTION="systemctl reboot -f"
;;
halt)
FINAL_ACTION="halt"
;;
poweroff)
FINAL_ACTION="systemctl poweroff -f"
;;
esac
;;
esac
done < $KDUMP_CONF
if [ -z "$CORE_COLLECTOR" ]; then
CORE_COLLECTOR="$DEFAULT_CORE_COLLECTOR"
if is_ssh_dump_target || is_raw_dump_target; then
CORE_COLLECTOR="$CORE_COLLECTOR -F"
fi
fi
}
# dump_fs <mount point| device>
dump_fs()
{
local _dev=$(findmnt -k -f -n -r -o SOURCE $1)
local _mp=$(findmnt -k -f -n -r -o TARGET $1)
local _op=$(findmnt -k -f -n -r -o OPTIONS $1)
echo "kdump: dump target is $_dev"
if [ -z "$_mp" ]; then
echo "kdump: error: Dump target $_dev is not mounted."
return 1
fi
# Remove -F in makedumpfile case. We don't want a flat format dump here.
[[ $CORE_COLLECTOR = *makedumpfile* ]] && CORE_COLLECTOR=`echo $CORE_COLLECTOR | sed -e "s/-F//g"`
echo "kdump: saving to $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/"
# Only remount to read-write mode if the dump target is mounted read-only.
if [[ "$_op" = "ro"* ]]; then
echo "kdump: Mounting Dump target $_dev in rw mode."
mount -o remount,rw $_dev $_mp || return 1
fi
mkdir -p $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR || return 1
save_vmcore_dmesg_fs ${DMESG_COLLECTOR} "$_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/"
echo "kdump: saving vmcore"
$CORE_COLLECTOR /proc/vmcore $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/vmcore-incomplete || return 1
mv $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/vmcore-incomplete $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/vmcore
sync
echo "kdump: saving vmcore complete"
# improper kernel cmdline can cause the failure of echo, we can ignore this kind of failure
return 0
}
save_vmcore_dmesg_fs() {
local _dmesg_collector=$1
local _path=$2
echo "kdump: saving vmcore-dmesg.txt"
$_dmesg_collector /proc/vmcore > ${_path}/vmcore-dmesg-incomplete.txt
_exitcode=$?
if [ $_exitcode -eq 0 ]; then
mv ${_path}/vmcore-dmesg-incomplete.txt ${_path}/vmcore-dmesg.txt
# Make sure file is on disk. There have been instances where later
# saving vmcore failed and system rebooted without sync and there
# was no vmcore-dmesg.txt available.
sync
echo "kdump: saving vmcore-dmesg.txt complete"
else
echo "kdump: saving vmcore-dmesg.txt failed"
fi
}
dump_to_rootfs()
{
echo "Kdump: trying to bring up rootfs device"
systemctl start dracut-initqueue
echo "Kdump: waiting for rootfs mount, will timeout after 90 seconds"
systemctl start sysroot.mount
dump_fs $NEWROOT
}
kdump_emergency_shell()
{
echo "PS1=\"kdump:\\\${PWD}# \"" >/etc/profile
/bin/dracut-emergency
rm -f /etc/profile
}
do_failure_action()
{
echo "Kdump: Executing failure action $FAILURE_ACTION"
eval $FAILURE_ACTION
}
do_final_action()
{
eval $FINAL_ACTION
}

709
kdump-lib.sh Executable file
View file

@ -0,0 +1,709 @@
#!/bin/sh
#
# Kdump common variables and functions
#
DEFAULT_PATH="/var/crash/"
FENCE_KDUMP_CONFIG_FILE="/etc/sysconfig/fence_kdump"
FENCE_KDUMP_SEND="/usr/libexec/fence_kdump_send"
FADUMP_ENABLED_SYS_NODE="/sys/kernel/fadump_enabled"
is_fadump_capable()
{
# Check if firmware-assisted dump is enabled
# if no, fallback to kdump check
if [ -f $FADUMP_ENABLED_SYS_NODE ]; then
rc=`cat $FADUMP_ENABLED_SYS_NODE`
[ $rc -eq 1 ] && return 0
fi
return 1
}
perror_exit() {
echo $@ >&2
exit 1
}
perror() {
echo $@ >&2
}
is_ssh_dump_target()
{
grep -q "^ssh[[:blank:]].*@" /etc/kdump.conf
}
is_nfs_dump_target()
{
grep -q "^nfs" /etc/kdump.conf || \
[[ $(get_dracut_args_fstype "$(grep "^dracut_args .*\-\-mount" /etc/kdump.conf)") = nfs* ]]
}
is_raw_dump_target()
{
grep -q "^raw" /etc/kdump.conf
}
is_fs_type_nfs()
{
local _fstype=$1
[ $_fstype = "nfs" ] || [ $_fstype = "nfs4" ] && return 0
return 1
}
is_fs_dump_target()
{
egrep -q "^ext[234]|^xfs|^btrfs|^minix" /etc/kdump.conf
}
strip_comments()
{
echo $@ | sed -e 's/\(.*\)#.*/\1/'
}
# Check if fence kdump is configured in Pacemaker cluster
is_pcs_fence_kdump()
{
# no pcs or fence_kdump_send executables installed?
type -P pcs > /dev/null || return 1
[ -x $FENCE_KDUMP_SEND ] || return 1
# fence kdump not configured?
(pcs cluster cib | grep 'type="fence_kdump"') &> /dev/null || return 1
}
# Check if fence_kdump is configured using kdump options
is_generic_fence_kdump()
{
[ -x $FENCE_KDUMP_SEND ] || return 1
grep -q "^fence_kdump_nodes" /etc/kdump.conf
}
to_dev_name() {
local dev="${1//\"/}"
case "$dev" in
UUID=*)
dev=`blkid -U "${dev#UUID=}"`
;;
LABEL=*)
dev=`blkid -L "${dev#LABEL=}"`
;;
esac
echo $dev
}
is_user_configured_dump_target()
{
return $(is_mount_in_dracut_args || is_ssh_dump_target || is_nfs_dump_target || \
is_raw_dump_target || is_fs_dump_target)
}
get_user_configured_dump_disk()
{
local _target
_target=$(egrep "^ext[234]|^xfs|^btrfs|^minix|^raw" /etc/kdump.conf 2>/dev/null |awk '{print $2}')
[ -n "$_target" ] && echo $_target && return
_target=$(get_dracut_args_target "$(grep "^dracut_args .*\-\-mount" /etc/kdump.conf)")
[ -b "$_target" ] && echo $_target
}
get_root_fs_device()
{
local _target
_target=$(findmnt -k -f -n -o SOURCE /)
[ -n "$_target" ] && echo $_target
return
}
get_save_path()
{
local _save_path=$(grep "^path" /etc/kdump.conf|awk '{print $2}')
if [ -z "$_save_path" ]; then
_save_path=$DEFAULT_PATH
fi
echo $_save_path
}
get_block_dump_target()
{
local _target _path
if is_ssh_dump_target || is_nfs_dump_target; then
return
fi
_target=$(get_user_configured_dump_disk)
[ -n "$_target" ] && echo $(to_dev_name $_target) && return
# Get block device name from local save path
_path=$(get_save_path)
_target=$(get_target_from_path $_path)
[ -b "$_target" ] && echo $(to_dev_name $_target)
}
is_dump_to_rootfs()
{
grep -E "^(failure_action|default)[[:space:]]dump_to_rootfs" /etc/kdump.conf >/dev/null
}
get_failure_action_target()
{
local _target
if is_dump_to_rootfs; then
# Get rootfs device name
_target=$(get_root_fs_device)
[ -b "$_target" ] && echo $(to_dev_name $_target) && return
# Then, must be nfs root
echo "nfs"
fi
}
# Get kdump targets(including root in case of dump_to_rootfs).
get_kdump_targets()
{
local _target _root
local kdump_targets
_target=$(get_block_dump_target)
if [ -n "$_target" ]; then
kdump_targets=$_target
elif is_ssh_dump_target; then
kdump_targets="ssh"
else
kdump_targets="nfs"
fi
# Add the root device if dump_to_rootfs is specified.
_root=$(get_failure_action_target)
if [ -n "$_root" -a "$kdump_targets" != "$_root" ]; then
kdump_targets="$kdump_targets $_root"
fi
echo "$kdump_targets"
}
# findmnt uses the option "-v, --nofsroot" to exclusive the [/dir]
# in the SOURCE column for bind-mounts, then if $_mntpoint equals to
# $_mntpoint_nofsroot, the mountpoint is not bind mounted directory.
is_bind_mount()
{
local _mntpoint=$(findmnt $1 | tail -n 1 | awk '{print $2}')
local _mntpoint_nofsroot=$(findmnt -v $1 | tail -n 1 | awk '{print $2}')
if [[ $_mntpoint = $_mntpoint_nofsroot ]]; then
return 1
else
return 0
fi
}
# Below is just an example for mount info
# /dev/mapper/atomicos-root[/ostree/deploy/rhel-atomic-host/var], if the
# directory is bind mounted. The former part represents the device path, rest
# part is the bind mounted directory which quotes by bracket "[]".
get_bind_mount_directory()
{
local _mntpoint=$(findmnt $1 | tail -n 1 | awk '{print $2}')
local _mntpoint_nofsroot=$(findmnt -v $1 | tail -n 1 | awk '{print $2}')
_mntpoint=${_mntpoint#*$_mntpoint_nofsroot}
_mntpoint=${_mntpoint#[}
_mntpoint=${_mntpoint%]}
echo $_mntpoint
}
get_mntpoint_from_path()
{
echo $(df $1 | tail -1 | awk '{print $NF}')
}
get_target_from_path()
{
local _target
_target=$(df $1 2>/dev/null | tail -1 | awk '{print $1}')
[[ "$_target" == "/dev/root" ]] && [[ ! -e /dev/root ]] && _target=$(get_root_fs_device)
echo $_target
}
get_fs_type_from_target()
{
echo $(findmnt -k -f -n -r -o FSTYPE $1)
}
# input: device path
# output: the general mount point
# find the general mount point, not the bind mounted point in atomic
# As general system, Use the previous code
#
# ERROR and EXIT:
# the device can be umounted the general mount point, if one of the mount point is bind mounted
# For example:
# mount /dev/sda /mnt/
# mount -o bind /mnt/var /var
# umount /mnt
get_mntpoint_from_target()
{
if is_atomic; then
for _mnt in $(findmnt -k -n -r -o TARGET $1)
do
if ! is_bind_mount $_mnt; then
echo $_mnt
return
fi
done
echo "Mount $1 firstly, without the bind mode" >&2
exit 1
else
echo $(findmnt -k -f -n -r -o TARGET $1)
fi
}
# get_option_value <option_name>
# retrieves value of option defined in kdump.conf
get_option_value() {
echo $(strip_comments `grep "^$1[[:space:]]\+" /etc/kdump.conf | tail -1 | cut -d\ -f2-`)
}
#This function compose a absolute path with the mount
#point and the relative $SAVE_PATH.
#target is passed in as argument, could be UUID, LABEL,
#block device or even nfs server export of the form of
#"my.server.com:/tmp/export"?
#And possibly this could be used for both default case
#as well as when dump taret is specified. When dump
#target is not specified, then $target would be null.
make_absolute_save_path()
{
local _target=$1
local _mnt
[ -n $_target ] && _mnt=$(get_mntpoint_from_target $1)
_mnt="${_mnt}/$SAVE_PATH"
# strip the duplicated "/"
echo "$_mnt" | tr -s /
}
check_save_path_fs()
{
local _path=$1
if [ ! -d $_path ]; then
perror_exit "Dump path $_path does not exist."
fi
}
is_atomic()
{
grep -q "ostree" /proc/cmdline
}
is_ipv6_address()
{
echo $1 | grep -q ":"
}
# get ip address or hostname from nfs/ssh config value
get_remote_host()
{
local _config_val=$1
# ipv6 address in kdump.conf is around with "[]",
# factor out the ipv6 address
_config_val=${_config_val#*@}
_config_val=${_config_val%:/*}
_config_val=${_config_val#[}
_config_val=${_config_val%]}
echo $_config_val
}
is_hostname()
{
local _hostname=`echo $1 | grep ":"`
if [ -n "$_hostname" ]; then
return 1
fi
echo $1 | grep -q "[a-zA-Z]"
}
# Copied from "/etc/sysconfig/network-scripts/network-functions"
get_hwaddr()
{
if [ -f "/sys/class/net/${1}/address" ]; then
awk '{ print toupper($0) }' < /sys/class/net/${1}/address
elif [ -d "/sys/class/net/${1}" ]; then
LC_ALL= LANG= ip -o link show ${1} 2>/dev/null | \
awk '{ print toupper(gensub(/.*link\/[^ ]* ([[:alnum:]:]*).*/,
"\\1", 1)); }'
fi
}
get_ifcfg_by_device()
{
grep -E -i -l "^[[:space:]]*DEVICE=\"*${1}\"*[[:space:]]*$" \
/etc/sysconfig/network-scripts/ifcfg-* 2>/dev/null | head -1
}
get_ifcfg_by_hwaddr()
{
grep -E -i -l "^[[:space:]]*HWADDR=\"*${1}\"*[[:space:]]*$" \
/etc/sysconfig/network-scripts/ifcfg-* 2>/dev/null | head -1
}
get_ifcfg_by_uuid()
{
grep -E -i -l "^[[:space:]]*UUID=\"*${1}\"*[[:space:]]*$" \
/etc/sysconfig/network-scripts/ifcfg-* 2>/dev/null | head -1
}
get_ifcfg_by_name()
{
grep -E -i -l "^[[:space:]]*NAME=\"*${1}\"*[[:space:]]*$" \
/etc/sysconfig/network-scripts/ifcfg-* 2>/dev/null | head -1
}
is_nm_running()
{
[ "$(LANG=C nmcli -t --fields running general status 2>/dev/null)" = "running" ]
}
is_nm_handling()
{
LANG=C nmcli -t --fields device,state dev status 2>/dev/null \
| grep -q "^\(${1}:connected\)\|\(${1}:connecting.*\)$"
}
# $1: netdev name
get_ifcfg_nmcli()
{
local nm_uuid nm_name
local ifcfg_file
# Get the active nmcli config name of $1
if is_nm_running && is_nm_handling "${1}" ; then
# The configuration "uuid" and "name" generated by nm is wrote to
# the ifcfg file as "UUID=<nm_uuid>" and "NAME=<nm_name>".
nm_uuid=$(LANG=C nmcli -t --fields uuid,device c show --active 2>/dev/null \
| grep "${1}" | head -1 | cut -d':' -f1)
nm_name=$(LANG=C nmcli -t --fields name,device c show --active 2>/dev/null \
| grep "${1}" | head -1 | cut -d':' -f1)
ifcfg_file=$(get_ifcfg_by_uuid "${nm_uuid}")
[ -z "${ifcfg_file}" ] && ifcfg_file=$(get_ifcfg_by_name "${nm_name}")
fi
echo -n "${ifcfg_file}"
}
# $1: netdev name
get_ifcfg_legacy()
{
local ifcfg_file
ifcfg_file="/etc/sysconfig/network-scripts/ifcfg-${1}"
[ -f "${ifcfg_file}" ] && echo -n "${ifcfg_file}" && return
ifcfg_file=$(get_ifcfg_by_name "${1}")
[ -f "${ifcfg_file}" ] && echo -n "${ifcfg_file}" && return
local hwaddr=$(get_hwaddr "${1}")
if [ -n "$hwaddr" ]; then
ifcfg_file=$(get_ifcfg_by_hwaddr "${hwaddr}")
[ -f "${ifcfg_file}" ] && echo -n "${ifcfg_file}" && return
fi
ifcfg_file=$(get_ifcfg_by_device "${1}")
echo -n "${ifcfg_file}"
}
# $1: netdev name
# Return the ifcfg file whole name(including the path) of $1 if any.
get_ifcfg_filename() {
local ifcfg_file
ifcfg_file=$(get_ifcfg_nmcli "${1}")
if [ -z "${ifcfg_file}" ]; then
ifcfg_file=$(get_ifcfg_legacy "${1}")
fi
echo -n "${ifcfg_file}"
}
# returns 0 when omission of watchdog module is desired in dracut_args
# returns 1 otherwise
is_wdt_mod_omitted() {
local dracut_args
local ret=1
dracut_args=$(grep "^dracut_args" /etc/kdump.conf)
[[ -z $dracut_args ]] && return $ret
eval set -- $dracut_args
while :; do
[[ -z $1 ]] && break
case $1 in
-o|--omit)
echo $2 | grep -qw "watchdog"
[[ $? == 0 ]] && ret=0
break
esac
shift
done
return $ret
}
# If "dracut_args" contains "--mount" information, use it
# directly without any check(users are expected to ensure
# its correctness).
is_mount_in_dracut_args()
{
grep -q "^dracut_args .*\-\-mount" /etc/kdump.conf
}
# If $1 contains dracut_args "--mount", return <filesystem type>
get_dracut_args_fstype()
{
echo $1 | grep "\-\-mount" | sed "s/.*--mount .\(.*\)/\1/" | cut -d' ' -f3
}
# If $1 contains dracut_args "--mount", return <device>
get_dracut_args_target()
{
echo $1 | grep "\-\-mount" | sed "s/.*--mount .\(.*\)/\1/" | cut -d' ' -f1
}
check_crash_mem_reserved()
{
local mem_reserved
mem_reserved=$(cat /sys/kernel/kexec_crash_size)
if [ $mem_reserved -eq 0 ]; then
echo "No memory reserved for crash kernel"
return 1
fi
return 0
}
check_kdump_feasibility()
{
if [ ! -e /sys/kernel/kexec_crash_loaded ]; then
echo "Kdump is not supported on this kernel"
return 1
fi
check_crash_mem_reserved
return $?
}
check_current_kdump_status()
{
if [ ! -f /sys/kernel/kexec_crash_loaded ];then
echo "Perhaps CONFIG_CRASH_DUMP is not enabled in kernel"
return 1
fi
rc=`cat /sys/kernel/kexec_crash_loaded`
if [ $rc == 1 ]; then
return 0
else
return 1
fi
}
# remove_cmdline_param <kernel cmdline> <param1> [<param2>] ... [<paramN>]
# Remove a list of kernel parameters from a given kernel cmdline and print the result.
# For each "arg" in the removing params list, "arg" and "arg=xxx" will be removed if exists.
remove_cmdline_param()
{
local cmdline=$1
shift
for arg in $@; do
cmdline=`echo $cmdline | \
sed -e "s/\b$arg=[^ ]*//g" \
-e "s/^$arg\b//g" \
-e "s/[[:space:]]$arg\b//g" \
-e "s/\s\+/ /g"`
done
echo $cmdline
}
#
# This function returns the "apicid" of the boot
# cpu (cpu 0) if present.
#
get_bootcpu_apicid()
{
awk ' \
BEGIN { CPU = "-1"; } \
$1=="processor" && $2==":" { CPU = $NF; } \
CPU=="0" && /^apicid/ { print $NF; } \
' \
/proc/cpuinfo
}
#
# append_cmdline <kernel cmdline> <parameter name> <parameter value>
# This function appends argument "$2=$3" to string ($1) if not already present.
#
append_cmdline()
{
local cmdline=$1
local newstr=${cmdline/$2/""}
# unchanged str implies argument wasn't there
if [ "$cmdline" == "$newstr" ]; then
cmdline="${cmdline} ${2}=${3}"
fi
echo $cmdline
}
# This function check iomem and determines if we have more than
# 4GB of ram available. Returns 1 if we do, 0 if we dont
need_64bit_headers()
{
return `tail -n 1 /proc/iomem | awk '{ split ($1, r, "-"); \
print (strtonum("0x" r[2]) > strtonum("0xffffffff")); }'`
}
# Check if secure boot is being enforced.
#
# Per Peter Jones, we need check efivar SecureBoot-$(the UUID) and
# SetupMode-$(the UUID), they are both 5 bytes binary data. The first four
# bytes are the attributes associated with the variable and can safely be
# ignored, the last bytes are one-byte true-or-false variables. If SecureBoot
# is 1 and SetupMode is 0, then secure boot is being enforced.
#
# Assume efivars is mounted at /sys/firmware/efi/efivars.
is_secure_boot_enforced()
{
local secure_boot_file setup_mode_file
local secure_boot_byte setup_mode_byte
secure_boot_file=$(find /sys/firmware/efi/efivars -name SecureBoot-* 2>/dev/null)
setup_mode_file=$(find /sys/firmware/efi/efivars -name SetupMode-* 2>/dev/null)
if [ -f "$secure_boot_file" ] && [ -f "$setup_mode_file" ]; then
secure_boot_byte=$(hexdump -v -e '/1 "%d\ "' $secure_boot_file|cut -d' ' -f 5)
setup_mode_byte=$(hexdump -v -e '/1 "%d\ "' $setup_mode_file|cut -d' ' -f 5)
if [ "$secure_boot_byte" = "1" ] && [ "$setup_mode_byte" = "0" ]; then
return 0
fi
fi
return 1
}
#
# prepare_kexec_args <kexec args>
# This function prepares kexec argument.
#
prepare_kexec_args()
{
local kexec_args=$1
local found_elf_args
ARCH=`uname -m`
if [ "$ARCH" == "i686" -o "$ARCH" == "i386" ]
then
need_64bit_headers
if [ $? == 1 ]
then
found_elf_args=`echo $kexec_args | grep elf32-core-headers`
if [ -n "$found_elf_args" ]
then
echo -n "Warning: elf32-core-headers overrides correct elf64 setting"
echo
else
kexec_args="$kexec_args --elf64-core-headers"
fi
else
found_elf_args=`echo $kexec_args | grep elf64-core-headers`
if [ -z "$found_elf_args" ]
then
kexec_args="$kexec_args --elf32-core-headers"
fi
fi
fi
echo $kexec_args
}
check_boot_dir()
{
local kdump_bootdir=$1
#If user specify a boot dir for kdump kernel, let's use it. Otherwise
#check whether it's a atomic host. If yes parse the subdirectory under
#/boot; If not just find it under /boot.
if [ -n "$kdump_bootdir" ]; then
echo "$kdump_bootdir"
return
fi
if ! is_atomic || [ "$(uname -m)" = "s390x" ]; then
kdump_bootdir="/boot"
else
eval $(cat /proc/cmdline| grep "BOOT_IMAGE" | cut -d' ' -f1)
kdump_bootdir="/boot"$(dirname $BOOT_IMAGE)
fi
echo $kdump_bootdir
}
#
# prepare_cmdline <commandline> <commandline remove> <commandline append>
# This function performs a series of edits on the command line.
# Store the final result in global $KDUMP_COMMANDLINE.
prepare_cmdline()
{
local cmdline id
if [ -z "$1" ]; then
cmdline=$(cat /proc/cmdline)
else
cmdline="$1"
fi
# These params should always be removed
cmdline=$(remove_cmdline_param "$cmdline" crashkernel panic_on_warn)
# These params can be removed configurably
cmdline=$(remove_cmdline_param "$cmdline" "$2")
# Always remove "root=X", as we now explicitly generate all kinds
# of dump target mount information including root fs.
#
# We do this before KDUMP_COMMANDLINE_APPEND, if one really cares
# about it(e.g. for debug purpose), then can pass "root=X" using
# KDUMP_COMMANDLINE_APPEND.
cmdline=$(remove_cmdline_param "$cmdline" root)
# With the help of "--hostonly-cmdline", we can avoid some interitage.
cmdline=$(remove_cmdline_param "$cmdline" rd.lvm.lv rd.luks.uuid rd.dm.uuid rd.md.uuid fcoe)
# Remove netroot, rd.iscsi.initiator and iscsi_initiator since
# we get duplicate entries for the same in case iscsi code adds
# it as well.
cmdline=$(remove_cmdline_param "$cmdline" netroot rd.iscsi.initiator iscsi_initiator)
cmdline="${cmdline} $3"
id=$(get_bootcpu_apicid)
if [ ! -z ${id} ] ; then
cmdline=$(append_cmdline "${cmdline}" disable_cpu_apicid ${id})
fi
echo ${cmdline}
}

42
kdump-udev-throttler Executable file
View file

@ -0,0 +1,42 @@
#!/bin/bash
# This util helps to reduce the workload of kdump service restarting
# on udev event. When hotplugging memory / CPU, multiple udev
# events may be triggered concurrently, and obviously, we don't want
# to restart kdump service for each event.
# This script will be called by udev, and make sure kdump service is
# restart after all events we are watching are settled.
# On each call, this script will update try to aquire the $throttle_lock
# The first instance acquired the file lock will keep waiting for events
# to settle and then reload kdump. Other instances will just exit
# In this way, we can make sure kdump service is restarted immediately
# and for exactly once after udev events are settled.
throttle_lock="/var/lock/kdump-udev-throttle"
exec 9>$throttle_lock
if [ $? -ne 0 ]; then
echo "Failed to create the lock file! Fallback to non-throttled kdump service restart"
/bin/kdumpctl reload
exit 1
fi
flock -n 9
if [ $? -ne 0 ]; then
echo "Throttling kdump restart for concurrent udev event"
exit 0
fi
# Wait for at least 1 second, at most 4 seconds for udev to settle
# Idealy we will have a less than 1 second lag between udev events settle
# and kdump reload
sleep 1 && udevadm settle --timeout 3
# Release the lock, /bin/kdumpctl will block and make the process
# holding two locks at the same time and we might miss some events
exec 9>&-
/bin/kdumpctl reload
exit 0

175
kdump.conf Normal file
View file

@ -0,0 +1,175 @@
# This file contains a series of commands to perform (in order) in the kdump
# kernel after a kernel crash in the crash kernel(1st kernel) has happened.
#
# Directives in this file are only applicable to the kdump initramfs, and have
# no effect once the root filesystem is mounted and the normal init scripts are
# processed.
#
# Currently, only one dump target and path can be specified. If the dumping to
# the configured target fails, the failure action which can be configured via
# the "failure_action" directive will be performed.
#
# Supported options:
#
# raw <partition>
# - Will dd /proc/vmcore into <partition>.
# Use persistent device names for partition devices,
# such as /dev/vg/<devname>.
#
# nfs <nfs mount>
# - Will mount nfs to <mnt>, and copy /proc/vmcore to
# <mnt>/<path>/%HOST-%DATE/, supports DNS.
#
# ssh <user@server>
# - Will scp /proc/vmcore to <user@server>:<path>/%HOST-%DATE/,
# supports DNS.
# NOTE: make sure the user has write permissions on the server.
#
# sshkey <path>
# - Will use the sshkey to do ssh dump.
# Specify the path of the ssh key to use when dumping
# via ssh. The default value is /root/.ssh/kdump_id_rsa.
#
# <fs type> <partition>
# - Will mount -t <fs type> <partition> <mnt>, and copy
# /proc/vmcore to <mnt>/<path>/%HOST_IP-%DATE/.
# NOTE: <partition> can be a device node, label or uuid.
# It's recommended to use persistent device names
# such as /dev/vg/<devname>.
# Otherwise it's suggested to use label or uuid.
#
# path <path>
# - "path" represents the file system path in which vmcore
# will be saved. If a dump target is specified in
# kdump.conf, then "path" is relative to the specified
# dump target.
#
# Interpretation of "path" changes a bit if the user didn't
# specify any dump target explicitly in kdump.conf. In this
# case, "path" represents the absolute path from root. The
# dump target and adjusted path are arrived at automatically
# depending on what's mounted in the current system.
#
# Ignored for raw device dumps. If unset, will use the default
# "/var/crash".
#
# core_collector <command> <options>
# - This allows you to specify the command to copy
# the vmcore. The default is makedumpfile, which on
# some architectures can drastically reduce vmcore size.
# See /sbin/makedumpfile --help for a list of options.
# Note that the -i and -g options are not needed here,
# as the initrd will automatically be populated with a
# config file appropriate for the running kernel.
# The default core_collector for raw/ssh dump is:
# "makedumpfile -F -l --message-level 1 -d 31".
# The default core_collector for other targets is:
# "makedumpfile -l --message-level 1 -d 31".
#
# "makedumpfile -F" will create a flattened vmcore.
# You need to use "makedumpfile -R" to rearrange the dump data to
# a normal dumpfile readable with analysis tools. For example:
# "makedumpfile -R vmcore < vmcore.flat".
#
# For core_collector format details, you can refer to
# kexec-kdump-howto.txt or kdump.conf manpage.
#
# kdump_post <binary | script>
# - This directive allows you to run a executable binary
# or script after the vmcore dump process terminates.
# The exit status of the current dump process is fed to
# the executable binary or script as its first argument.
#
# kdump_pre <binary | script>
# - Works like the "kdump_post" directive, but instead of running
# after the dump process, runs immediately before it.
# Exit status of this binary is interpreted as follows:
# 0 - continue with dump process as usual
# non 0 - reboot the system
#
# extra_bins <binaries | shell scripts>
# - This directive allows you to specify additional binaries or
# shell scripts to be included in the kdump initrd.
# Generally they are useful in conjunction with a kdump_post
# or kdump_pre binary or script which depends on these extra_bins.
#
# extra_modules <module(s)>
# - This directive allows you to specify extra kernel modules
# that you want to be loaded in the kdump initrd.
# Multiple modules can be listed, separated by spaces, and any
# dependent modules will automatically be included.
#
# failure_action <reboot | halt | poweroff | shell | dump_to_rootfs>
# - Action to perform in case dumping fails.
# reboot: Reboot the system.
# halt: Halt the system.
# poweroff: Power down the system.
# shell: Drop to a bash shell.
# Exiting the shell reboots the system by default,
# or perform "final_action".
# dump_to_rootfs: Dump vmcore to rootfs from initramfs context and
# reboot by default or perform "final_action".
# Useful when non-root dump target is specified.
# The default option is "reboot".
#
# default <reboot | halt | poweroff | shell | dump_to_rootfs>
# - Same as the "failure_action" directive above, but this directive
# is obsolete and will be removed in the future.
#
# final_action <reboot | halt | poweroff>
# - Action to perform in case dumping succeeds. Also performed
# when "shell" or "dump_to_rootfs" failure action finishes.
# Each action is same as the "failure_action" directive above.
# The default is "reboot".
#
# force_rebuild <0 | 1>
# - By default, kdump initrd will only be rebuilt when necessary.
# Specify 1 to force rebuilding kdump initrd every time when kdump
# service starts.
#
# force_no_rebuild <0 | 1>
# - By default, kdump initrd will be rebuilt when necessary.
# Specify 1 to bypass rebuilding of kdump initrd.
#
# force_no_rebuild and force_rebuild options are mutually
# exclusive and they should not be set to 1 simultaneously.
#
# override_resettable <0 | 1>
# - Usually an unresettable block device can't be a dump target.
# Specifying 1 when you want to dump even though the block
# target is unresettable
# By default, it is 0, which will not try dumping destined to fail.
#
# dracut_args <arg(s)>
# - Pass extra dracut options when rebuilding kdump initrd.
#
# fence_kdump_args <arg(s)>
# - Command line arguments for fence_kdump_send (it can contain
# all valid arguments except hosts to send notification to).
#
# fence_kdump_nodes <node(s)>
# - List of cluster node(s) except localhost, separated by spaces,
# to send fence_kdump notifications to.
# (this option is mandatory to enable fence_kdump).
#
#raw /dev/vg/lv_kdump
#ext4 /dev/vg/lv_kdump
#ext4 LABEL=/boot
#ext4 UUID=03138356-5e61-4ab3-b58e-27507ac41937
#nfs my.server.com:/export/tmp
#ssh user@my.server.com
#sshkey /root/.ssh/kdump_id_rsa
path /var/crash
core_collector makedumpfile -l --message-level 1 -d 31
#core_collector scp
#kdump_post /var/crash/scripts/kdump-post.sh
#kdump_pre /var/crash/scripts/kdump-pre.sh
#extra_bins /usr/bin/lftp
#extra_modules gfs2
#failure_action shell
#force_rebuild 1
#force_no_rebuild 1
#dracut_args --omit-drivers "cfg80211 snd" --add-drivers "ext2 ext3"
#fence_kdump_args -p 7410 -f auto -c 0 -i 10
#fence_kdump_nodes node1 node2

360
kdump.conf.5 Normal file
View file

@ -0,0 +1,360 @@
.TH KDUMP.CONF 5 "07/23/2008" "kexec-tools"
.SH NAME
kdump.conf \- configuration file for kdump kernel.
.SH DESCRIPTION
kdump.conf is a configuration file for the kdump kernel crash
collection service.
kdump.conf provides post-kexec instructions to the kdump kernel. It is
stored in the initrd file managed by the kdump service. If you change
this file and do not want to reboot in order for the changes to take
effect, restart the kdump service to rebuild the initrd.
For most configurations, you can simply review the examples provided
in the stock /etc/kdump.conf.
.B NOTE:
For filesystem dumps the dump target must be mounted before building
kdump initramfs.
kdump.conf only affects the behavior of the initramfs. Please read the
kdump operational flow section of kexec-kdump-howto.txt in the docs to better
understand how this configuration file affects the behavior of kdump.
.SH OPTIONS
.B raw <partition>
.RS
Will dd /proc/vmcore into <partition>. Use persistent device names for
partition devices, such as /dev/vg/<devname>.
.RE
.B nfs <nfs mount>
.RS
Will mount nfs to <mnt>, and copy /proc/vmcore to <mnt>/<path>/%HOST-%DATE/,
supports DNS. Note that a fqdn should be used as the server name in the
mount point.
.RE
.B ssh <user@server>
.RS
Will scp /proc/vmcore to <user@server>:<path>/%HOST-%DATE/,
supports DNS. NOTE: make sure user has necessary write permissions on
server and that a fqdn is used as the server name.
.RE
.B sshkey <path>
.RS
Specify the path of the ssh key to use when dumping via ssh.
The default value is /root/.ssh/kdump_id_rsa.
.RE
.B <fs type> <partition>
.RS
Will mount -t <fs type> <partition> <mnt>, and copy /proc/vmcore to
<mnt>/<path>/%HOST_IP-%DATE/. NOTE: <partition> can be a device node, label
or uuid. It's recommended to use persistent device names such as
/dev/vg/<devname>. Otherwise it's suggested to use label or uuid.
.RE
.B path <path>
.RS
"path" represents the file system path in which vmcore will be saved.
If a dump target is specified in kdump.conf, then "path" is relative to the
specified dump target.
.PP
Interpretation of "path" changes a bit if the user didn't specify any dump
target explicitly in kdump.conf. In this case, "path" represents the
absolute path from root. The dump target and adjusted path are arrived
at automatically depending on what's mounted in the current system.
.PP
Ignored for raw device dumps. If unset, will use the default "/var/crash".
.RE
.B core_collector <command> <options>
.RS
This allows you to specify the command to copy the vmcore.
The default is makedumpfile, which on some architectures can drastically reduce
core file size. See /sbin/makedumpfile --help for a list of options.
Note that the -i and -g options are not needed here, as the initrd
will automatically be populated with a config file appropriate
for the running kernel.
.PP
Note 1: About default core collector:
The default core_collector for raw/ssh dump is:
"makedumpfile -F -l --message-level 1 -d 31".
The default core_collector for other targets is:
"makedumpfile -l --message-level 1 -d 31".
Even if core_collector option is commented out in kdump.conf, makedumpfile
is the default core collector and kdump uses it internally.
If one does not want makedumpfile as default core_collector, then they
need to specify one using core_collector option to change the behavior.
.PP
Note 2: If "makedumpfile -F" is used then you will get a flattened format
vmcore.flat, you will need to use "makedumpfile -R" to rearrange the
dump data from standard input to a normal dumpfile (readable with analysis
tools).
ie. "makedumpfile -R vmcore < vmcore.flat"
.RE
.B kdump_post <binary | script>
.RS
This directive allows you to run a specified executable
just after the vmcore dump process terminates. The exit
status of the current dump process is fed to the kdump_post
executable as its first argument($1). Executable can modify
it to indicate the new exit status of succeeding dump process,
.PP
Note that scripts written for use with this directive must use
the /bin/bash interpreter.
.RE
.B kdump_pre <binary | script>
.RS
Works just like the "kdump_post" directive, but instead
of running after the dump process, runs immediately
before. Exit status of this binary is interpreted
as follows:
.PP
0 - continue with dump process as usual
.PP
non 0 - reboot the system
.PP
Note that scripts written for this directive must use
the /bin/bash interpreter.
.RE
.B extra_bins <binaries | shell scripts>
.RS
This directive allows you to specify additional
binaries or shell scripts you'd like to include in
your kdump initrd. Generally only useful in
conjunction with a kdump_post binary or script that
relies on other binaries or scripts.
.RE
.B extra_modules <module(s)>
.RS
This directive allows you to specify extra kernel
modules that you want to be loaded in the kdump
initrd, typically used to set up access to
non-boot-path dump targets that might otherwise
not be accessible in the kdump environment. Multiple
modules can be listed, separated by spaces, and any
dependent modules will automatically be included.
.RE
.B failure_action <reboot | halt | poweroff | shell | dump_to_rootfs>
.RS
Action to perform in case dumping to the intended target fails. The default is "reboot".
reboot: Reboot the system (this is what most people will want, as it returns the system
to a normal state). halt: Halt the system and lose the vmcore. poweroff: The system
will be powered down. shell: Drop to a shell session inside the initramfs, from which
you can manually perform additional recovery actions. Exiting this shell reboots the
system by default or performs "final_action".
Note: kdump uses bash as the default shell. dump_to_rootfs: If non-root dump
target is specified, the failure action can be set as dump_to_rootfs. That means when
dumping to target fails, dump vmcore to rootfs from initramfs context and reboot
by default or perform "final_action".
.RE
.B default <reboot | halt | poweroff | shell | dump_to_rootfs>
.RS
Same as the "failure_action" directive above, but this directive is obsolete
and will be removed in the future.
.RE
.B final_action <reboot | halt | poweroff>
.RS
Action to perform in case dumping to the intended target succeeds.
Also performed when "shell" or "dump_to_rootfs" failure action finishes.
Each action is same as the "failure_action" directive above.
The default is "reboot".
.RE
.B force_rebuild <0 | 1>
.RS
By default, kdump initrd will only be rebuilt when necessary.
Specify 1 to force rebuilding kdump initrd every time when kdump service starts.
.RE
.B force_no_rebuild <0 | 1>
.RS
By default, kdump initrd will be rebuilt when necessary.
Specify 1 to bypass rebuilding of kdump initrd.
.PP
force_no_rebuild and force_rebuild options are mutually exclusive and
they should not be set to 1 simultaneously.
.RE
.B override_resettable <0 | 1>
.RS
Usually an unresettable block device can't be a dump target. Specifying 1 means
that even though the block target is unresettable, the user wants to try dumping anyway.
By default, it's set to 0, which will not try something destined to fail.
.RE
.B dracut_args <arg(s)>
.RS
Kdump uses dracut to generate initramfs for second kernel. This option
allows a user to pass arguments to dracut directly.
.RE
.B fence_kdump_args <arg(s)>
.RS
Command line arguments for fence_kdump_send (it can contain all valid
arguments except hosts to send notification to).
.RE
.B fence_kdump_nodes <node(s)>
.RS
List of cluster node(s) except localhost, separated by spaces, to send fence_kdump notification
to (this option is mandatory to enable fence_kdump).
.RE
.SH DEPRECATED OPTIONS
.B net <nfs mount>|<user@server>
.RS
net option is replaced by nfs and ssh options. Use nfs or ssh options
directly.
.RE
.B options <module> <option list>
.RS
Use KDUMP_COMMANDLINE_APPEND in /etc/sysconfig/kdump to add module options as
kernel command line parameters. For example, specify 'loop.max_loop=1' to limit
maximum loop devices to 1.
.RE
.B link_delay <seconds>
.RS
link_delay was used to wait for a network device to initialize before using it.
Now dracut network module takes care of this issue automatically.
.RE
.B disk_timeout <seconds>
.RS
Similar to link_delay, dracut ensures disks are ready before kdump uses them.
.RE
.B debug_mem_level <0-3>
.RS
Turn on verbose debug output of kdump scripts regarding free/used memory at
various points of execution. This feature has been
moved to dracut now.
Use KDUMP_COMMANDLINE_APPEND in /etc/sysconfig/kdump and
append dracut cmdline param rd.memdebug=[0-3] to enable the debug output.
Higher level means more debugging output.
.PP
0 - no output
.PP
1 - partial /proc/meminfo
.PP
2 - /proc/meminfo
.PP
3 - /proc/meminfo + /proc/slabinfo
.RE
.B blacklist <list of kernel modules>
.RS
blacklist option was recently being used to prevent loading modules in
initramfs. General terminology for blacklist has been that module is
present in initramfs but it is not actually loaded in kernel. Hence
retaining blacklist option creates more confusing behavior. It has been
deprecated.
.PP
Instead, use rd.driver.blacklist option on second kernel to blacklist
a certain module. One can edit /etc/sysconfig/kdump.conf and edit
KDUMP_COMMANDLINE_APPEND to pass kernel command line options. Refer
to dracut.cmdline man page for more details on module blacklist option.
.RE
.RE
.SH EXAMPLES
Here are some examples for core_collector option:
.PP
Core collector command format depends on dump target type. Typically for
filesystem (local/remote), core_collector should accept two arguments.
First one is source file and second one is target file. For ex.
.TP
ex1.
core_collector "cp --sparse=always"
Above will effectively be translated to:
cp --sparse=always /proc/vmcore <dest-path>/vmcore
.TP
ex2.
core_collector "makedumpfile -l --message-level 1 -d 31"
Above will effectively be translated to:
makedumpfile -l --message-level 1 -d 31 /proc/vmcore <dest-path>/vmcore
.PP
For dump targets like raw and ssh, in general, core collector should expect
one argument (source file) and should output the processed core on standard
output (There is one exception of "scp", discussed later). This standard
output will be saved to destination using appropriate commands.
raw dumps examples:
.TP
ex3.
core_collector "cat"
Above will effectively be translated to.
cat /proc/vmcore | dd of=<target-device>
.TP
ex4.
core_collector "makedumpfile -F -l --message-level 1 -d 31"
Above will effectively be translated to.
makedumpfile -F -l --message-level 1 -d 31 | dd of=<target-device>
.PP
ssh dumps examples
.TP
ex5.
core_collector "cat"
Above will effectively be translated to.
cat /proc/vmcore | ssh <options> <remote-location> "dd of=path/vmcore"
.TP
ex6.
core_collector "makedumpfile -F -l --message-level 1 -d 31"
Above will effectively be translated to.
makedumpfile -F -l --message-level 1 -d 31 | ssh <options> <remote-location> "dd of=path/vmcore"
There is one exception to standard output rule for ssh dumps. And that is
scp. As scp can handle ssh destinations for file transfers, one can
specify "scp" as core collector for ssh targets (no output on stdout).
.TP
ex7.
core_collector "scp"
Above will effectively be translated to.
scp /proc/vmcore <user@host>:path/vmcore
.PP
examples for other options please see
.I /etc/kdump.conf
.SH SEE ALSO
kexec(8) mkdumprd(8) dracut.cmdline(7)

15
kdump.service Normal file
View file

@ -0,0 +1,15 @@
[Unit]
Description=Crash recovery kernel arming
After=network.target network-online.target remote-fs.target basic.target
DefaultDependencies=no
[Service]
Type=oneshot
ExecStart=/usr/bin/kdumpctl start
ExecStop=/usr/bin/kdumpctl stop
ExecReload=/usr/bin/kdumpctl reload
RemainAfterExit=yes
StartLimitInterval=0
[Install]
WantedBy=multi-user.target

37
kdump.sysconfig Normal file
View file

@ -0,0 +1,37 @@
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""
# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel. This will likely match the contents of the grub kernel
# line. For example:
# KDUMP_COMMANDLINE="ro root=LABEL=/"
# Dracut depends on proper root= options, so please make sure that appropriate
# root= options are copied from /proc/cmdline. In general it is best to append
# command line options using "KDUMP_COMMANDLINE_APPEND=".
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""
# This variable lets us remove arguments from the current kdump commandline
# as taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
# NOTE: some arguments such as crashkernel will always be removed
KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug quiet"
# This variable lets us append arguments to the current kdump commandline
# after processed by KDUMP_COMMANDLINE_REMOVE
KDUMP_COMMANDLINE_APPEND="irqpoll maxcpus=1 reset_devices"
# Any additional kexec arguments required. In most situations, this should
# be left empty
#
# Example:
# KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS=""
#Where to find the boot image
#KDUMP_BOOTDIR="/boot"
#What is the image type used for kdump
KDUMP_IMG="vmlinuz"

40
kdump.sysconfig.i386 Normal file
View file

@ -0,0 +1,40 @@
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""
# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel. This will likely match the contents of the grub kernel
# line. For example:
# KDUMP_COMMANDLINE="ro root=LABEL=/"
# Dracut depends on proper root= options, so please make sure that appropriate
# root= options are copied from /proc/cmdline. In general it is best to append
# command line options using "KDUMP_COMMANDLINE_APPEND=".
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""
# This variable lets us remove arguments from the current kdump commandline
# as taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
# NOTE: some arguments such as crashkernel will always be removed
KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug quiet"
# This variable lets us append arguments to the current kdump commandline
# after processed by KDUMP_COMMANDLINE_REMOVE
KDUMP_COMMANDLINE_APPEND="irqpoll nr_cpus=1 reset_devices numa=off udev.children-max=2 panic=10 transparent_hugepage=never"
# Any additional kexec arguments required. In most situations, this should
# be left empty
#
# Example:
# KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS=""
#Where to find the boot image
#KDUMP_BOOTDIR="/boot"
#What is the image type used for kdump
KDUMP_IMG="vmlinuz"
#What is the images extension. Relocatable kernels don't have one
KDUMP_IMG_EXT=""

42
kdump.sysconfig.ppc64 Normal file
View file

@ -0,0 +1,42 @@
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""
# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel. This will likely match the contents of the grub kernel
# line. For example:
# KDUMP_COMMANDLINE="ro root=LABEL=/"
# Dracut depends on proper root= options, so please make sure that appropriate
# root= options are copied from /proc/cmdline. In general it is best to append
# command line options using "KDUMP_COMMANDLINE_APPEND=".
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""
# This variable lets us remove arguments from the current kdump commandline
# as taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
# NOTE: some arguments such as crashkernel will always be removed
KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug quiet"
# This variable lets us append arguments to the current kdump commandline
# after processed by KDUMP_COMMANDLINE_REMOVE
KDUMP_COMMANDLINE_APPEND="irqpoll maxcpus=1 noirqdistrib reset_devices cgroup_disable=memory numa=off udev.children-max=2 ehea.use_mcs=0 panic=10 kvm_cma_resv_ratio=0 transparent_hugepage=never"
# Any additional kexec arguments required. In most situations, this should
# be left empty
#
# Example:
# KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS="--dt-no-old-root"
#Where to find the boot image
#KDUMP_BOOTDIR="/boot"
#What is the image type used for kdump
KDUMP_IMG="vmlinuz"
#What is the images extension. Relocatable kernels don't have one
KDUMP_IMG_EXT=""
#Specify the action after failure

42
kdump.sysconfig.ppc64le Normal file
View file

@ -0,0 +1,42 @@
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""
# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel. This will likely match the contents of the grub kernel
# line. For example:
# KDUMP_COMMANDLINE="ro root=LABEL=/"
# Dracut depends on proper root= options, so please make sure that appropriate
# root= options are copied from /proc/cmdline. In general it is best to append
# command line options using "KDUMP_COMMANDLINE_APPEND=".
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""
# This variable lets us remove arguments from the current kdump commandline
# as taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
# NOTE: some arguments such as crashkernel will always be removed
KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug quiet"
# This variable lets us append arguments to the current kdump commandline
# after processed by KDUMP_COMMANDLINE_REMOVE
KDUMP_COMMANDLINE_APPEND="irqpoll maxcpus=1 noirqdistrib reset_devices cgroup_disable=memory numa=off udev.children-max=2 ehea.use_mcs=0 panic=10 kvm_cma_resv_ratio=0 transparent_hugepage=never"
# Any additional kexec arguments required. In most situations, this should
# be left empty
#
# Example:
# KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS="--dt-no-old-root"
#Where to find the boot image
#KDUMP_BOOTDIR="/boot"
#What is the image type used for kdump
KDUMP_IMG="vmlinuz"
#What is the images extension. Relocatable kernels don't have one
KDUMP_IMG_EXT=""
#Specify the action after failure

43
kdump.sysconfig.s390x Normal file
View file

@ -0,0 +1,43 @@
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""
# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel. This will likely match the contents of the grub kernel
# line. For example:
# KDUMP_COMMANDLINE="ro root=LABEL=/"
# Dracut depends on proper root= options, so please make sure that appropriate
# root= options are copied from /proc/cmdline. In general it is best to append
# command line options using "KDUMP_COMMANDLINE_APPEND=".
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""
# This variable lets us remove arguments from the current kdump commandline
# as taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
# NOTE: some arguments such as crashkernel will always be removed
KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug quiet"
# This variable lets us append arguments to the current kdump commandline
# after processed by KDUMP_COMMANDLINE_REMOVE
KDUMP_COMMANDLINE_APPEND="nr_cpus=1 cgroup_disable=memory numa=off udev.children-max=2 panic=10 transparent_hugepage=never"
# Any additional /sbin/mkdumprd arguments required.
MKDUMPRD_ARGS=""
# Any additional kexec arguments required. In most situations, this should
# be left empty
#
# Example:
# KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS=""
#Where to find the boot image
#KDUMP_BOOTDIR="/boot"
#What is the image type used for kdump
KDUMP_IMG="vmlinuz"
#What is the images extension. Relocatable kernels don't have one
KDUMP_IMG_EXT=""

40
kdump.sysconfig.x86_64 Normal file
View file

@ -0,0 +1,40 @@
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""
# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel. This will likely match the contents of the grub kernel
# line. For example:
# KDUMP_COMMANDLINE="ro root=LABEL=/"
# Dracut depends on proper root= options, so please make sure that appropriate
# root= options are copied from /proc/cmdline. In general it is best to append
# command line options using "KDUMP_COMMANDLINE_APPEND=".
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""
# This variable lets us remove arguments from the current kdump commandline
# as taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
# NOTE: some arguments such as crashkernel will always be removed
KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug quiet"
# This variable lets us append arguments to the current kdump commandline
# after processed by KDUMP_COMMANDLINE_REMOVE
KDUMP_COMMANDLINE_APPEND="irqpoll nr_cpus=1 reset_devices cgroup_disable=memory mce=off numa=off udev.children-max=2 panic=10 acpi_no_memhotplug transparent_hugepage=never nokaslr"
# Any additional kexec arguments required. In most situations, this should
# be left empty
#
# Example:
# KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS=""
#Where to find the boot image
#KDUMP_BOOTDIR="/boot"
#What is the image type used for kdump
KDUMP_IMG="vmlinuz"
#What is the images extension. Relocatable kernels don't have one
KDUMP_IMG_EXT=""

1209
kdumpctl Executable file

File diff suppressed because it is too large Load diff

44
kdumpctl.8 Normal file
View file

@ -0,0 +1,44 @@
.TH KDUMPCTL 8 2015-07-13 kexec-tools
.SH NAME
kdumpctl \- control interface for kdump
.SH SYNOPSIS
.B kdumpctl
.I COMMAND
.SH DESCRIPTION
.B kdumpctl
is used to check or control the kdump service.
In most cases, you should use
.B systemctl
to start / stop / enable kdump service instead. However,
.B kdumpctl
provides more details for debug and a helper to setup ssh key authentication.
.SH COMMANDS
.TP
.I start
Start the service.
.TP
.I stop
Stop the service.
.TP
.I status
Prints the current status of kdump service.
It returns non-zero value if kdump is not operational.
.TP
.I restart
Is equal to
.I start; stop
.TP
.I propagate
Helps to setup key authentication for ssh storage since it's
impossible to use password authentication during kdump.
.TP
.I showmem
Prints the size of reserved memory for crash kernel in megabytes.
.SH "SEE ALSO"
.BR kdump.conf (5),
.BR mkdumprd (8)

709
kexec-kdump-howto.txt Normal file
View file

@ -0,0 +1,709 @@
Kexec/Kdump HOWTO
Introduction
Kexec and kdump are new features in the 2.6 mainstream kernel. These features
are included in Red Hat Enterprise Linux 5. The purpose of these features
is to ensure faster boot up and creation of reliable kernel vmcores for
diagnostic purposes.
Overview
Kexec
Kexec is a fastboot mechanism which allows booting a Linux kernel from the
context of already running kernel without going through BIOS. BIOS can be very
time consuming especially on the big servers with lots of peripherals. This can
save a lot of time for developers who end up booting a machine numerous times.
Kdump
Kdump is a new kernel crash dumping mechanism and is very reliable because
the crash dump is captured from the context of a freshly booted kernel and
not from the context of the crashed kernel. Kdump uses kexec to boot into
a second kernel whenever system crashes. This second kernel, often called
a capture kernel, boots with very little memory and captures the dump image.
The first kernel reserves a section of memory that the second kernel uses
to boot. Kexec enables booting the capture kernel without going through BIOS
hence contents of first kernel's memory are preserved, which is essentially
the kernel crash dump.
Kdump is supported on the i686, x86_64, ia64 and ppc64 platforms. The
standard kernel and capture kernel are one in the same on i686, x86_64,
ia64 and ppc64.
If you're reading this document, you should already have kexec-tools
installed. If not, you install it via the following command:
# yum install kexec-tools
Now load a kernel with kexec:
# kver=`uname -r` # kexec -l /boot/vmlinuz-$kver
--initrd=/boot/initrd-$kver.img \
--command-line="`cat /proc/cmdline`"
NOTE: The above will boot you back into the kernel you're currently running,
if you want to load a different kernel, substitute it in place of `uname -r`.
Now reboot your system, taking note that it should bypass the BIOS:
# reboot
How to configure kdump:
Again, we assume if you're reading this document, you should already have
kexec-tools installed. If not, you install it via the following command:
# yum install kexec-tools
To be able to do much of anything interesting in the way of debug analysis,
you'll also need to install the kernel-debuginfo package, of the same arch
as your running kernel, and the crash utility:
# yum --enablerepo=\*debuginfo install kernel-debuginfo.$(uname -m) crash
Next up, we need to modify some boot parameters to reserve a chunk of memory for
the capture kernel. With the help of grubby, it's very easy to append
"crashkernel=128M" to the end of your kernel boot parameters. Note that the X
values are such that X = the amount of memory to reserve for the capture kernel.
And based on arch and system configuration, one might require more than 128M to
be reserved for kdump. One need to experiment and test kdump, if 128M is not
sufficient, try reserving more memory.
# grubby --args="crashkernel=128M" --update-kernel=/boot/vmlinuz-`uname -r`
Note that there is an alternative form in which to specify a crashkernel
memory reservation, in the event that more control is needed over the size and
placement of the reserved memory. The format is:
crashkernel=range1:size1[,range2:size2,...][@offset]
Where range<n> specifies a range of values that are matched against the amount
of physical RAM present in the system, and the corresponding size<n> value
specifies the amount of kexec memory to reserve. For example:
crashkernel=512M-2G:64M,2G-:128M
This line tells kexec to reserve 64M of ram if the system contains between
512M and 2G of physical memory. If the system contains 2G or more of physical
memory, 128M should be reserved.
After making said changes, reboot your system, so that the X MB of memory is
left untouched by the normal system, reserved for the capture kernel. Take note
that the output of 'free -m' will show X MB less memory than without this
parameter, which is expected. You may be able to get by with less than 128M, but
testing with only 64M has proven unreliable of late. On ia64, as much as 512M
may be required.
Now that you've got that reserved memory region set up, you want to turn on
the kdump init script:
# chkconfig kdump on
Then, start up kdump as well:
# systemctl start kdump.service
This should load your kernel-kdump image via kexec, leaving the system ready
to capture a vmcore upon crashing. To test this out, you can force-crash
your system by echo'ing a c into /proc/sysrq-trigger:
# echo c > /proc/sysrq-trigger
You should see some panic output, followed by the system restarting into
the kdump kernel. When the boot process gets to the point where it starts
the kdump service, your vmcore should be copied out to disk (by default,
in /var/crash/<YYYY-MM-DD-HH:MM>/vmcore), then the system rebooted back into
your normal kernel.
Once back to your normal kernel, you can use the previously installed crash
kernel in conjunction with the previously installed kernel-debuginfo to
perform postmortem analysis:
# crash /usr/lib/debug/lib/modules/2.6.17-1.2621.el5/vmlinux
/var/crash/2006-08-23-15:34/vmcore
crash> bt
and so on...
Saving vmcore-dmesg.txt
----------------------
Kernel log bufferes are one of the most important information available
in vmcore. Now before saving vmcore, kernel log bufferes are extracted
from /proc/vmcore and saved into a file vmcore-dmesg.txt. After
vmcore-dmesg.txt, vmcore is saved. Destination disk and directory for
vmcore-dmesg.txt is same as vmcore. Note that kernel log buffers will
not be available if dump target is raw device.
Dump Triggering methods:
This section talks about the various ways, other than a Kernel Panic, in which
Kdump can be triggered. The following methods assume that Kdump is configured
on your system, with the scripts enabled as described in the section above.
1) AltSysRq C
Kdump can be triggered with the combination of the 'Alt','SysRq' and 'C'
keyboard keys. Please refer to the following link for more details:
http://kbase.redhat.com/faq/FAQ_43_5559.shtm
In addition, on PowerPC boxes, Kdump can also be triggered via Hardware
Management Console(HMC) using 'Ctrl', 'O' and 'C' keyboard keys.
2) NMI_WATCHDOG
In case a machine has a hard hang, it is quite possible that it does not
respond to keyboard interrupts. As a result 'Alt-SysRq' keys will not help
trigger a dump. In such scenarios Nmi Watchdog feature can prove to be useful.
The following link has more details on configuring Nmi watchdog option.
http://kbase.redhat.com/faq/FAQ_85_9129.shtm
Once this feature has been enabled in the kernel, any lockups will result in an
OOPs message to be generated, followed by Kdump being triggered.
3) Kernel OOPs
If we want to generate a dump everytime the Kernel OOPses, we can achieve this
by setting the 'Panic On OOPs' option as follows:
# echo 1 > /proc/sys/kernel/panic_on_oops
This is enabled by default on RHEL5.
4) NMI(Non maskable interrupt) button
In cases where the system is in a hung state, and is not accepting keyboard
interrupts, using NMI button for triggering Kdump can be very useful. NMI
button is present on most of the newer x86 and x86_64 machines. Please refer
to the User guides/manuals to locate the button, though in most occasions it
is not very well documented. In most cases it is hidden behind a small hole
on the front or back panel of the machine. You could use a toothpick or some
other non-conducting probe to press the button.
For example, on the IBM X series 366 machine, the NMI button is located behind
a small hole on the bottom center of the rear panel.
To enable this method of dump triggering using NMI button, you will need to set
the 'unknown_nmi_panic' option as follows:
# echo 1 > /proc/sys/kernel/unknown_nmi_panic
5) PowerPC specific methods:
On IBM PowerPC machines, issuing a soft reset invokes the XMON debugger(if
XMON is configured). To configure XMON one needs to compile the kernel with
the CONFIG_XMON and CONFIG_XMON_DEFAULT options, or by compiling with
CONFIG_XMON and booting the kernel with xmon=on option.
Following are the ways to remotely issue a soft reset on PowerPC boxes, which
would drop you to XMON. Pressing a 'X' (capital alphabet X) followed by an
'Enter' here will trigger the dump.
5.1) HMC
Hardware Management Console(HMC) available on Power4 and Power5 machines allow
partitions to be reset remotely. This is specially useful in hang situations
where the system is not accepting any keyboard inputs.
Once you have HMC configured, the following steps will enable you to trigger
Kdump via a soft reset:
On Power4
Using GUI
* In the right pane, right click on the partition you wish to dump.
* Select "Operating System->Reset".
* Select "Soft Reset".
* Select "Yes".
Using HMC Commandline
# reset_partition -m <machine> -p <partition> -t soft
On Power5
Using GUI
* In the right pane, right click on the partition you wish to dump.
* Select "Restart Partition".
* Select "Dump".
* Select "OK".
Using HMC Commandline
# chsysstate -m <managed system name> -n <lpar name> -o dumprestart -r lpar
5.2) Blade Management Console for Blade Center
To initiate a dump operation, go to Power/Restart option under "Blade Tasks" in
the Blade Management Console. Select the corresponding blade for which you want
to initate the dump and then click "Restart blade with NMI". This issues a
system reset and invokes xmon debugger.
Advanced Setups:
In addition to being able to capture a vmcore to your system's local file
system, kdump can be configured to capture a vmcore to a number of other
locations, including a raw disk partition, a dedicated file system, an NFS
mounted file system, or a remote system via ssh/scp. Additional options
exist for specifying the relative path under which the dump is captured,
what to do if the capture fails, and for compressing and filtering the dump
(so as to produce smaller, more manageable, vmcore files).
In theory, dumping to a location other than the local file system should be
safer than kdump's default setup, as its possible the default setup will try
dumping to a file system that has become corrupted. The raw disk partition and
dedicated file system options allow you to still dump to the local system,
but without having to remount your possibly corrupted file system(s),
thereby decreasing the chance a vmcore won't be captured. Dumping to an
NFS server or remote system via ssh/scp also has this advantage, as well
as allowing for the centralization of vmcore files, should you have several
systems from which you'd like to obtain vmcore files. Of course, note that
these configurations could present problems if your network is unreliable.
Advanced setups are configured via modifications to /etc/kdump.conf,
which out of the box, is fairly well documented itself. Any alterations to
/etc/kdump.conf should be followed by a restart of the kdump service, so
the changes can be incorporated in the kdump initrd. Restarting the kdump
service is as simple as '/sbin/systemctl restart kdump.service'.
Note that kdump.conf is used as a configuration mechanism for capturing dump
files from the initramfs (in the interests of safety), the root file system is
mounted, and the init process is started, only as a last resort if the
initramfs fails to capture the vmcore. As such, configuration made in
/etc/kdump.conf is only applicable to capture recorded in the initramfs. If
for any reason the init process is started on the root file system, only a
simple copying of the vmcore from /proc/vmcore to /var/crash/$DATE/vmcore will
be preformed.
For both local filesystem and nfs dump the dump target must be mounted before
building kdump initramfs. That means one needs to put an entry for the dump
file system in /etc/fstab so that after reboot when kdump service starts,
it can find the dump target and build initramfs instead of failing.
Usually the dump target should be used only for kdump. If you worry about
someone uses the filesystem for something else other than dumping vmcore
you can mount it as read-only. Mkdumprd will still remount it as read-write
for creating dump directory and will move it back to read-only afterwards.
Raw partition
Raw partition dumping requires that a disk partition in the system, at least
as large as the amount of memory in the system, be left unformatted. Assuming
/dev/vg/lv_kdump is left unformatted, kdump.conf can be configured with
'raw /dev/vg/lv_kdump', and the vmcore file will be copied via dd directly
onto partition /dev/vg/lv_kdump. Restart the kdump service via
'/sbin/systemctl restart kdump.service' to commit this change to your kdump
initrd. Dump target should be persistent device name, such as lvm or device
mapper canonical name.
Dedicated file system
Similar to raw partition dumping, you can format a partition with the file
system of your choice, Again, it should be at least as large as the amount
of memory in the system. Assuming it should be at least as large as the
amount of memory in the system. Assuming /dev/vg/lv_kdump has been
formatted ext4, specify 'ext4 /dev/vg/lv_kdump' in kdump.conf, and a
vmcore file will be copied onto the file system after it has been mounted.
Dumping to a dedicated partition has the advantage that you can dump multiple
vmcores to the file system, space permitting, without overwriting previous ones,
as would be the case in a raw partition setup. Restart the kdump service via
'/sbin/systemctl restart kdump.service' to commit this change to
your kdump initrd. Note that for local file systems ext4 and ext2 are
supported as dumpable targets. Kdump will not prevent you from specifying
other filesystems, and they will most likely work, but their operation
cannot be guaranteed. for instance specifying a vfat filesystem or msdos
filesystem will result in a successful load of the kdump service, but during
crash recovery, the dump will fail if the system has more than 2GB of memory
(since vfat and msdos filesystems do not support more than 2GB files).
Be careful of your filesystem selection when using this target.
It is recommended to use persistent device names or UUID/LABEL for file system
dumps. One example of persistent device is /dev/vg/<devname>.
NFS mount
Dumping over NFS requires an NFS server configured to export a file system
with full read/write access for the root user. All operations done within
the kdump initial ramdisk are done as root, and to write out a vmcore file,
we obviously must be able to write to the NFS mount. Configuring an NFS
server is outside the scope of this document, but either the no_root_squash
or anonuid options on the NFS server side are likely of interest to permit
the kdump initrd operations write to the NFS mount as root.
Assuming your're exporting /dump on the machine nfs-server.example.com,
once the mount is properly configured, specify it in kdump.conf, via
'nfs nfs-server.example.com:/dump'. The server portion can be specified either
by host name or IP address. Following a system crash, the kdump initrd will
mount the NFS mount and copy out the vmcore to your NFS server. Restart the
kdump service via '/sbin/systemctl restart kdump.service' to commit this change
to your kdump initrd.
Special mount via "dracut_args"
You can utilize "dracut_args" to pass "--mount" to kdump, see dracut manpage
about the format of "--mount" for details. If there is any "--mount" specified
via "dracut_args", kdump will build it as the mount target without doing any
validation (mounting or checking like mount options, fs size, save path, etc),
so you must test it to ensure all the correctness. You cannot use other targets
in /etc/kdump.conf if you use "--mount" in "dracut_args". You also cannot specify
mutliple "--mount" targets via "dracut_args".
One use case of "--mount" in "dracut_args" is you do not want to mount dump target
before kdump service startup, for example, to reduce the burden of the shared nfs
server. Such as the example below:
dracut_args --mount "192.168.1.1:/share /mnt/test nfs4 defaults"
NOTE:
- <mountpoint> must be specified as an absolute path.
Remote system via ssh/scp
Dumping over ssh/scp requires setting up passwordless ssh keys for every
machine you wish to have dump via this method. First up, configure kdump.conf
for ssh/scp dumping, adding a config line of 'ssh user@server', where 'user'
can be any user on the target system you choose, and 'server' is the host
name or IP address of the target system. Using a dedicated, restricted user
account on the target system is recommended, as there will be keyless ssh
access to this account.
Once kdump.conf is appropriately configured, issue the command
'kdumpctl propagate' to automatically set up the ssh host keys and transmit
the necessary bits to the target server. You'll have to type in 'yes'
to accept the host key for your targer server if this is the first time
you've connected to it, and then input the target system user's password
to send over the necessary ssh key file. Restart the kdump service via
'/sbin/systemctl restart kdump.service' to commit this change to your kdump initrd.
Path
====
"path" represents the file system path in which vmcore will be saved. In
fact kdump creates a directory $hostip-$date with-in "path" and saves
vmcore there. So practically dump is saved in $path/$hostip-$date/. To
simplify discussion further, if we say dump will be saved in $path, it
is implied that kdump will create another directory inside path and
save vmcore there.
If a dump target is specified in kdump.conf, then "path" is relative to the
specified dump target. For example, if dump target is "ext4 /dev/sda", then
dump will be saved in "$path" directory on /dev/sda.
Same is the case for nfs dump. If user specified "nfs foo.com:/export/tmp/"
as dump target, then dump will effectively be saved in
"foo.com:/export/tmp/var/crash/" directory.
Interpretation of path changes a bit if user has not specified a dump
target explicitly in kdump.conf. In this case, "path" represents the
absolute path from root. And dump target and adjusted path are arrived
at automatically depending on what's mounted in the current system.
Following are few examples.
path /var/crash/
----------------
Assuming there is no disk mounted on /var/ or on /var/crash, dump will
be saved on disk backing rootfs in directory /var/crash.
path /var/crash/ (A separate disk mounted on /var)
--------------------------------------------------
Say a disk /dev/sdb is mouted on /var. In this case dump target will
become /dev/sdb and path will become "/crash" and dump will be saved
on "sdb:/crash/" directory.
path /var/crash/ (NFS mounted on /var)
-------------------------------------
Say foo.com:/export/tmp is mounted on /var. In this case dump target is
nfs server and path will be adjusted to "/crash" and dump will be saved to
foo.com:/export/tmp/crash/ directory.
Kdump boot directory
====================
Usually kdump kernel is the same as 1st kernel. So kdump will try to find
kdump kernel under /boot according to /proc/cmdline. E.g we execute below
command and get an output:
cat /proc/cmdline
BOOT_IMAGE=/xxx/vmlinuz-3.yyy.zzz root=xxxx .....
Then kdump kernel will be /boot/xxx/vmlinuz-3.yyy.zzz.
However a variable KDUMP_BOOTDIR in /etc/sysconfig/kdump is provided to
user if kdump kernel is put in a different directory.
Kdump Post-Capture Executable
It is possible to specify a custom script or binary you wish to run following
an attempt to capture a vmcore. The executable is passed an exit code from
the capture process, which can be used to trigger different actions from
within your post-capture executable.
Kdump Pre-Capture Executable
It is possible to specify a custom script or binary you wish to run before
capturing a vmcore. Exit status of this binary is interpreted:
0 - continue with dump process as usual
non 0 - reboot the system
Extra Binaries
If you have specific binaries or scripts you want to have made available
within your kdump initrd, you can specify them by their full path, and they
will be included in your kdump initrd, along with all dependent libraries.
This may be particularly useful for those running post-capture scripts that
rely on other binaries.
Extra Modules
By default, only the bare minimum of kernel modules will be included in your
kdump initrd. Should you wish to capture your vmcore files to a non-boot-path
storage device, such as an iscsi target disk or clustered file system, you may
need to manually specify additional kernel modules to load into your kdump
initrd.
Failure action
==============
Failure action specifies what to do when dump to configured dump target
fails. By default, failure action is "reboot" and that is system reboots
if attempt to save dump to dump target fails.
There are other failure actions available though.
- dump_to_rootfs
This option tries to mount root and save dump on root filesystem
in a path specified by "path". This option will generally make
sense when dump target is not root filesystem. For example, if
dump is being saved over network using "ssh" then one can specify
failure action to "dump_to_rootfs" to try saving dump to root
filesystem if dump over network fails.
- shell
Drop into a shell session inside initramfs.
- halt
Halt system after failure
- poweroff
Poweroff system after failure.
Compression and filtering
The 'core_collector' parameter in kdump.conf allows you to specify a custom
dump capture method. The most common alternate method is makedumpfile, which
is a dump filtering and compression utility provided with kexec-tools. On
some architectures, it can drastically reduce the size of your vmcore files,
which becomes very useful on systems with large amounts of memory.
A typical setup is 'core_collector makedumpfile -F -l --message-level 1 -d 31',
but check the output of '/sbin/makedumpfile --help' for a list of all available
options (-i and -g don't need to be specified, they're automatically taken care
of). Note that use of makedumpfile requires that the kernel-debuginfo package
corresponding with your running kernel be installed.
Core collector command format depends on dump target type. Typically for
filesystem (local/remote), core_collector should accept two arguments.
First one is source file and second one is target file. For ex.
ex1.
---
core_collector "cp --sparse=always"
Above will effectively be translated to:
cp --sparse=always /proc/vmcore <dest-path>/vmcore
ex2.
---
core_collector "makedumpfile -l --message-level 1 -d 31"
Above will effectively be translated to:
makedumpfile -l --message-level 1 -d 31 /proc/vmcore <dest-path>/vmcore
For dump targets like raw and ssh, in general, core collector should expect
one argument (source file) and should output the processed core on standard
output (There is one exception of "scp", discussed later). This standard
output will be saved to destination using appropriate commands.
raw dumps core_collector examples:
---------
ex3.
---
core_collector "cat"
Above will effectively be translated to.
cat /proc/vmcore | dd of=<target-device>
ex4.
---
core_collector "makedumpfile -F -l --message-level 1 -d 31"
Above will effectively be translated to.
makedumpfile -F -l --message-level 1 -d 31 | dd of=<target-device>
ssh dumps core_collector examples:
---------
ex5.
---
core_collector "cat"
Above will effectively be translated to.
cat /proc/vmcore | ssh <options> <remote-location> "dd of=path/vmcore"
ex6.
---
core_collector "makedumpfile -F -l --message-level 1 -d 31"
Above will effectively be translated to.
makedumpfile -F -l --message-level 1 -d 31 | ssh <options> <remote-location> "dd of=path/vmcore"
There is one exception to standard output rule for ssh dumps. And that is
scp. As scp can handle ssh destinations for file transfers, one can
specify "scp" as core collector for ssh targets (no output on stdout).
ex7.
----
core_collector "scp"
Above will effectively be translated to.
scp /proc/vmcore <user@host>:path/vmcore
About default core collector
----------------------------
Default core_collector for ssh/raw dump is:
"makedumpfile -F -l --message-level 1 -d 31".
Default core_collector for other targets is:
"makedumpfile -l --message-level 1 -d 31".
Even if core_collector option is commented out in kdump.conf, makedumpfile
is default core collector and kdump uses it internally.
If one does not want makedumpfile as default core_collector, then they
need to specify one using core_collector option to change the behavior.
Note: If "makedumpfile -F" is used then you will get a flattened format
vmcore.flat, you will need to use "makedumpfile -R" to rearrange the
dump data from stdard input to a normal dumpfile (readable with analysis
tools).
For example: "makedumpfile -R vmcore < vmcore.flat"
Caveats:
Console frame-buffers and X are not properly supported. If you typically run
with something along the lines of "vga=791" in your kernel config line or
have X running, console video will be garbled when a kernel is booted via
kexec. Note that the kdump kernel should still be able to create a dump,
and when the system reboots, video should be restored to normal.
Notes on resetting video:
Video is a notoriously difficult issue with kexec. Video cards contain ROM code
that controls their initial configuration and setup. This code is nominally
accessed and executed from the Bios, and otherwise not safely executable. Since
the purpose of kexec is to reboot the system without re-executing the Bios, it
is rather difficult if not impossible to reset video cards with kexec. The
result is, that if a system crashes while running in a graphical mode (i.e.
running X), the screen may appear to become 'frozen' while the dump capture is
taking place. A serial console will of course reveal that the system is
operating and capturing a vmcore image, but a casual observer will see the
system as hung until the dump completes and a true reboot is executed.
There are two possiblilties to work around this issue. One is by adding
--reset-vga to the kexec command line options in /etc/sysconfig/kdump. This
tells kdump to write some reasonable default values to the video card register
file, in the hopes of returning it to a text mode such that boot messages are
visible on the screen. It does not work with all video cards however.
Secondly, it may be worth trying to add vga15fb.ko to the extra_modules list in
/etc/kdump.conf. This will attempt to use the video card in framebuffer mode,
which can blank the screen prior to the start of a dump capture.
Notes on rootfs mount:
Dracut is designed to mount rootfs by default. If rootfs mounting fails it
will refuse to go on. So kdump leaves rootfs mounting to dracut currently.
We make the assumtion that proper root= cmdline is being passed to dracut
initramfs for the time being. If you need modify "KDUMP_COMMANDLINE=" in
/etc/sysconfig/kdump, you will need to make sure that appropriate root=
options are copied from /proc/cmdline. In general it is best to append
command line options using "KDUMP_COMMANDLINE_APPEND=" instead of replacing
the original command line completely.
Notes on watchdog module handling:
If a watchdog is active in first kernel then, we must have it's module
loaded in crash kernel, so that either watchdog is deactivated or started
being kicked in second kernel. Otherwise, we might face watchdog reboot
when vmcore is being saved. When dracut watchdog module is enabled, it
installs kernel watchdog module of active watchdog device in initrd.
kexec-tools always add "-a watchdog" to the dracut_args if there exists at
least one active watchdog and user has not added specifically "-o watchdog"
in dracut_args of kdump.conf. If a watchdog module (such as hp_wdt) has
not been written in watchdog-core framework then this option will not have
any effect and module will not be added. Please note that only systemd
watchdog daemon is supported as watchdog kick application.
Parallel Dumping Operation
==========================
Kexec allows kdump using multiple cpus. So parallel feature can accelerate
dumping substantially, especially in executing compression and filter.
For example:
1."makedumpfile -c --num-threads [THREAD_NUM] /proc/vmcore dumpfile"
2."makedumpfile -c /proc/vmcore dumpfile",
1 has better performance than 2, if THREAD_NUM is larger than two
and the usable cpus number is larger than THREAD_NUM.
Notes on how to use multiple cpus on a capture kernel on x86 system:
Make sure that you are using a kernel that supports disable_cpu_apicid
kernel option as a capture kernel, which is needed to avoid x86 specific
hardware issue (*). The disable_cpu_apicid kernel option is automatically
appended by kdumpctl script and is ignored if the kernel doesn't support it.
You need to specify how many cpus to be used in a capture kernel by specifying
the number of cpus in nr_cpus kernel option in /etc/sysconfig/kdump. nr_cpus
is 1 at default.
You should use necessary and sufficient number of cpus on a capture kernel.
Warning: Don't use too many cpus on a capture kernel, or the capture kernel
may lead to panic due to Out Of Memory.
(*) Without disable_cpu_apicid kernel option, capture kernel may lead to
hang, system reset or power-off at boot, depending on your system and runtime
situation at the time of crash.
Debugging Tips
--------------
- One can drop into a shell before/after saving vmcore with the help of
using kdump_pre/kdump_post hooks. Use following in one of the pre/post
scripts to drop into a shell.
#!/bin/bash
_ctty=/dev/ttyS0
setsid /bin/sh -i -l 0<>$_ctty 1<>$_ctty 2<>$_ctty
One might have to change the terminal depending on what they are using.
- Serial console logging for virtual machines
I generally use "virsh console <domain-name>" to get to serial console.
I noticed after dump saving system reboots and when grub menu shows up
some of the previously logged messages are no more there. That means
any important debugging info at the end will be lost.
One can log serial console as follows to make sure messages are not lost.
virsh ttyconsole <domain-name>
ln -s <name-of-tty> /dev/modem
minicom -C /tmp/console-logs
Now minicom should be logging serial console in file console-logs.

View file

@ -0,0 +1,41 @@
From 2f007b48c581a81d7e95678b6bcb77cfbe177135 Mon Sep 17 00:00:00 2001
From: Kairui Song <kasong@redhat.com>
Date: Tue, 29 Jan 2019 11:14:15 +0800
Subject: [PATCH] [PATCH v2] honor the CFLAGS from environment variables
This makes it possible to pass in extra cflags, for example, hardening
flags could be passed in with environment variable when building a
hardened package.
Also introduce a CFLAGS_BASE to hold common CFLAGS, which simplify the
CFLAGS definition.
Suggested-by: Kazuhito Hagio <k-hagio@ab.jp.nec.com>
Signed-off-by: Kairui Song <kasong@redhat.com>
---
Makefile | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/Makefile b/Makefile
index ea3c47d..bd681d2 100644
--- a/makedumpfile-1.6.5/Makefile
+++ b/makedumpfile-1.6.5/Makefile
@@ -8,11 +8,10 @@ ifeq ($(strip $CC),)
CC = gcc
endif
-CFLAGS = -g -O2 -Wall -D_FILE_OFFSET_BITS=64 \
- -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE \
- -DVERSION='"$(VERSION)"' -DRELEASE_DATE='"$(DATE)"'
-CFLAGS_ARCH = -g -O2 -Wall -D_FILE_OFFSET_BITS=64 \
- -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
+CFLAGS_BASE := $(CFLAGS) -g -O2 -Wall -D_FILE_OFFSET_BITS=64 \
+ -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
+CFLAGS := $(CFLAGS_BASE) -DVERSION='"$(VERSION)"' -DRELEASE_DATE='"$(DATE)"'
+CFLAGS_ARCH := $(CFLAGS_BASE)
# LDFLAGS = -L/usr/local/lib -I/usr/local/include
HOST_ARCH := $(shell uname -m)
--
2.20.1

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,25 @@
Kdump now works on live images with some manual configurations. Here is the step
by step guide.
1. Enable crashkernel reservation
Since there isn't any config file that can be used to configure kernel
parameters for live images before booting them, we have to append 'crashkernel'
argument in boot menu every time we boot a live image.
2. Change dump target in /etc/kdump.conf
When kdump kernel boots in a live environment, the default target /var/crash is
in RAM so you need to change the dump target to an external disk or a network
dump target.
Besides, make sure that "default dump_to_rootfs" is not specified.
3. Start kdump service
$ kdumpctl start
4. Trigger a kdump test
$ echo 1 > /proc/sys/kernel/sysrq
$ echo c > /proc/sysrq-trigger

473
mkdumprd Normal file
View file

@ -0,0 +1,473 @@
#!/bin/bash --norc
# New mkdumprd
#
# Copyright 2011 Red Hat, Inc.
#
# Written by Cong Wang <amwang@redhat.com>
#
[[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut
. $dracutbasedir/dracut-functions.sh
. /lib/kdump/kdump-lib.sh
export IN_KDUMP=1
conf_file="/etc/kdump.conf"
SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa"
SAVE_PATH=$(awk '/^path/ {print $2}' $conf_file)
[ -z "$SAVE_PATH" ] && SAVE_PATH=$DEFAULT_PATH
# strip the duplicated "/"
SAVE_PATH=$(echo $SAVE_PATH | tr -s /)
is_wdt_addition_needed() {
local active
is_wdt_mod_omitted
[[ $? -eq 0 ]] && return 1
[[ -d /sys/class/watchdog/ ]] || return 1
for dir in /sys/class/watchdog/*; do
[[ -f "$dir/state" ]] || continue
active=$(< "$dir/state")
[[ "$active" = "active" ]] && return 0
done
return 1
}
WDTCFG=""
is_wdt_addition_needed
[[ $? -eq 0 ]] && WDTCFG="-a watchdog"
extra_modules=""
dracut_args=("--quiet" "--hostonly" "--hostonly-cmdline" "--hostonly-i18n" "--hostonly-mode" "strict" "-o" "plymouth dash resume ifcfg earlykdump" $WDTCFG)
OVERRIDE_RESETTABLE=0
add_dracut_arg() {
local arg qarg is_quoted=0
while [ $# -gt 0 ];
do
arg="${1//\'/\"}"
#Handle quoted substring properly for passing it to dracut_args array.
if [ $is_quoted -eq 0 ]; then
if [[ "$arg" == "\"" ]] || [[ $arg != ${arg#\"} ]]; then
is_quoted=1
arg=${arg#\"}
fi
fi
if [ $is_quoted -eq 1 ]; then
qarg="$qarg $arg"
if [[ "$arg" == "\"" ]] || [[ $arg != ${arg%\"} ]]; then
is_quoted=0
arg=${qarg%\"}
qarg=""
else
shift
continue
fi
fi
dracut_args+=("$arg")
shift
done
}
add_dracut_module() {
add_dracut_arg "--add" "$1"
}
add_dracut_mount() {
add_dracut_arg "--mount" "$1"
}
add_dracut_sshkey() {
add_dracut_arg "--sshkey" "$1"
}
# caller should ensure $1 is valid and mounted in 1st kernel
to_mount() {
local _dev=$1 _source _target _fstype _options _mntopts _pdev
_source=$(findmnt -k -f -n -r -o SOURCE $_dev)
_target=$(get_mntpoint_from_target $_dev)
# mount under /sysroot if dump to root disk or mount under
#/kdumproot/$_target in other cases in 2nd kernel. systemd
#will be in charge to umount it.
if [ "$_target" = "/" ];then
_target="/sysroot"
else
_target="/kdumproot/$_target"
fi
_fstype=$(findmnt -k -f -n -r -o FSTYPE $_dev)
[[ -e /etc/fstab ]] && _options=$(findmnt --fstab -f -n -r -o OPTIONS $_dev)
if [ -z "$_options" ]; then
_options=$(findmnt -k -f -n -r -o OPTIONS $_dev)
if [[ $_fstype == "nfs"* ]]; then
_options=$(echo $_options | sed 's/,addr=[^,]*//')
_options=$(echo $_options | sed 's/,proto=[^,]*//')
_options=$(echo $_options | sed 's/,clientaddr=[^,]*//')
fi
fi
# mount fs target as rw in 2nd kernel
_options=$(echo $_options | sed 's/\(^\|,\)ro\($\|,\)/\1rw\2/g')
# with 'noauto' in fstab nfs and non-root disk mount will fail in 2nd
# kernel, filter it out here.
_options=$(echo $_options | sed 's/\(^\|,\)noauto\($\|,\)/\1/g')
# drop nofail or nobootwait
_options=$(echo $_options | sed 's/\(^\|,\)nofail\($\|,\)/\1/g')
_options=$(echo $_options | sed 's/\(^\|,\)nobootwait\($\|,\)/\1/g')
_mntopts="$_target $_fstype $_options"
#for non-nfs _dev converting to use udev persistent name
if [ -b "$_source" ]; then
_pdev="$(get_persistent_dev $_source)"
if [ -z "$_pdev" ]; then
return 1
fi
else
_pdev=$_dev
fi
echo "$_pdev $_mntopts"
}
is_readonly_mount() {
local _mnt
_mnt=$(findmnt -k -f -n -r -o OPTIONS $1)
#fs/proc_namespace.c: show_mountinfo():
#seq_puts(m, mnt->mnt_flags & MNT_READONLY ? " ro" : " rw");
[[ "$_mnt" =~ ^ro ]]
}
#Function: get_ssh_size
#$1=dump target
#called from while loop and shouldn't read from stdin, so we're using "ssh -n"
get_ssh_size() {
local _opt _out _size
_opt="-i $SSH_KEY_LOCATION -o BatchMode=yes -o StrictHostKeyChecking=yes"
_out=$(ssh -q -n $_opt $1 "df -P $SAVE_PATH")
[ $? -ne 0 ] && {
perror_exit "checking remote ssh server available size failed."
}
#ssh output removed the line break, so print field NF-2
_size=$(echo -n $_out| awk '{avail=NF-2; print $avail}')
echo -n $_size
}
#mkdir if save path does not exist on ssh dump target
#$1=ssh dump target
#caller should ensure write permission on $DUMP_TARGET:$SAVE_PATH
#called from while loop and shouldn't read from stdin, so we're using "ssh -n"
mkdir_save_path_ssh()
{
local _opt _dir
_opt="-i $SSH_KEY_LOCATION -o BatchMode=yes -o StrictHostKeyChecking=yes"
ssh -qn $_opt $1 mkdir -p $SAVE_PATH 2>&1 > /dev/null
_ret=$?
if [ $_ret -ne 0 ]; then
perror_exit "mkdir failed on $DUMP_TARGET:$SAVE_PATH"
fi
#check whether user has write permission on $SAVE_PATH/$DUMP_TARGET
_dir=$(ssh -qn $_opt $1 mktemp -dqp $SAVE_PATH 2>/dev/null)
_ret=$?
if [ $_ret -ne 0 ]; then
perror_exit "Could not create temporary directory on $DUMP_TARGET:$SAVE_PATH. Make sure user has write permission on destination"
fi
ssh -qn $_opt $1 rmdir $_dir
return 0
}
#Function: get_fs_size
#$1=dump target
get_fs_size() {
local _mnt=$(get_mntpoint_from_target $1)
echo -n $(df -P "${_mnt}/$SAVE_PATH"|tail -1|awk '{print $4}')
}
#Function: get_raw_size
#$1=dump target
get_raw_size() {
echo -n $(fdisk -s "$1")
}
#Function: check_size
#$1: dump type string ('raw', 'fs', 'ssh')
#$2: dump target
check_size() {
local avail memtotal
memtotal=$(awk '/MemTotal/{print $2}' /proc/meminfo)
case "$1" in
raw)
avail=$(get_raw_size "$2")
;;
ssh)
avail=$(get_ssh_size "$2")
;;
fs)
avail=$(get_fs_size "$2")
;;
*)
return
esac
if [ $? -ne 0 ]; then
perror_exit "Check dump target size failed"
fi
if [ $avail -lt $memtotal ]; then
echo "Warning: There might not be enough space to save a vmcore."
echo " The size of $2 should be greater than $memtotal kilo bytes."
fi
}
# $1: core_collector config value
verify_core_collector() {
if grep -q "^raw" $conf_file && [ "${1%% *}" != "makedumpfile" ]; then
echo "Warning: specifying a non-makedumpfile core collector, you will have to recover the vmcore manually."
fi
if is_ssh_dump_target || is_raw_dump_target; then
if [ "${1%% *}" = "makedumpfile" ]; then
! strstr "$1" "-F" && {
perror_exit "The specified dump target needs makedumpfile \"-F\" option."
}
fi
fi
}
add_mount() {
local _mnt=$(to_mount "$1")
if [ $? -ne 0 ]; then
exit 1
fi
add_dracut_mount "$_mnt"
}
#handle the case user does not specify the dump target explicitly
handle_default_dump_target()
{
local _target
local _mntpoint
is_user_configured_dump_target && return
check_save_path_fs $SAVE_PATH
_mntpoint=$(get_mntpoint_from_path $SAVE_PATH)
_target=$(get_target_from_path $SAVE_PATH)
if is_atomic && is_bind_mount $_mntpoint; then
SAVE_PATH=${SAVE_PATH##"$_mntpoint"}
# the real dump path in the 2nd kernel, if the mount point is bind mounted.
SAVE_PATH=$(get_bind_mount_directory $_mntpoint)/$SAVE_PATH
_mntpoint=$(get_mntpoint_from_target $_target)
# the absolute path in the 1st kernel
SAVE_PATH=$_mntpoint/$SAVE_PATH
fi
SAVE_PATH=${SAVE_PATH##"$_mntpoint"}
add_mount "$_target"
check_size fs $_target
}
get_override_resettable()
{
local override_resettable
override_resettable=$(grep "^override_resettable" $conf_file)
if [ -n "$override_resettable" ]; then
OVERRIDE_RESETTABLE=$(echo $override_resettable | cut -d' ' -f2)
if [ "$OVERRIDE_RESETTABLE" != "0" ] && [ "$OVERRIDE_RESETTABLE" != "1" ];then
perror_exit "override_resettable value $OVERRIDE_RESETTABLE is invalid"
fi
fi
}
# $1: function name
for_each_block_target()
{
local dev majmin
for dev in $(get_kdump_targets); do
[ -b "$dev" ] || continue
majmin=$(get_maj_min $dev)
check_block_and_slaves $1 $majmin && return 1
done
return 0
}
#judge if a specific device with $1 is unresettable
#return false if unresettable.
is_unresettable()
{
local path="/sys/$(udevadm info --query=all --path=/sys/dev/block/$1 | awk '/^P:/ {print $2}' | sed -e 's/\(cciss[0-9]\+\/\).*/\1/g' -e 's/\/block\/.*$//')/resettable"
local resettable=1
if [ -f "$path" ]
then
resettable="$(cat $path)"
[ $resettable -eq 0 -a "$OVERRIDE_RESETTABLE" -eq 0 ] && {
local device=$(udevadm info --query=all --path=/sys/dev/block/$1 | awk -F= '/DEVNAME/{print $2}')
echo "Error: Can not save vmcore because device $device is unresettable"
return 0
}
fi
return 1
}
#check if machine is resettable.
#return true if resettable
check_resettable()
{
local _ret _target
get_override_resettable
for_each_block_target is_unresettable
_ret=$?
[ $_ret -eq 0 ] && return
return 1
}
# $1: maj:min
is_crypt()
{
local majmin=$1 dev line ID_FS_TYPE=""
line=$(udevadm info --query=property --path=/sys/dev/block/$majmin \
| grep "^ID_FS_TYPE")
eval "$line"
[[ "$ID_FS_TYPE" = "crypto_LUKS" ]] && {
dev=$(udevadm info --query=all --path=/sys/dev/block/$majmin | awk -F= '/DEVNAME/{print $2}')
echo "Device $dev is encrypted."
return 0
}
return 1
}
check_crypt()
{
local _ret _target
for_each_block_target is_crypt
_ret=$?
[ $_ret -eq 0 ] && return
return 1
}
if ! check_resettable; then
exit 1
fi
if ! check_crypt; then
echo "Warning: Encrypted device is in dump path. User will prompted for password during second kernel boot."
fi
# firstly get right SSH_KEY_LOCATION
keyfile=$(awk '/^sshkey/ {print $2}' $conf_file)
if [ -f "$keyfile" ]; then
# canonicalize the path
SSH_KEY_LOCATION=$(/usr/bin/readlink -m $keyfile)
fi
if [ "$(uname -m)" = "s390x" ]; then
add_dracut_module "znet"
fi
while read config_opt config_val;
do
# remove inline comments after the end of a directive.
config_val=$(strip_comments $config_val)
case "$config_opt" in
extra_modules)
extra_modules="$extra_modules $config_val"
;;
ext[234]|xfs|btrfs|minix|nfs)
if ! findmnt $config_val >/dev/null; then
perror_exit "Dump target $config_val is probably not mounted."
fi
_absolute_save_path=$(make_absolute_save_path $config_val)
_mntpoint=$(get_mntpoint_from_path $_absolute_save_path)
if is_atomic && is_bind_mount $_mntpoint; then
SAVE_PATH=${_absolute_save_path##"$_mntpoint"}
# the real dump path in the 2nd kernel, if the mount point is bind mounted.
SAVE_PATH=$(get_bind_mount_directory $_mntpoint)/$SAVE_PATH
fi
add_mount "$config_val"
check_save_path_fs $_absolute_save_path
check_size fs $config_val
;;
raw)
#checking raw disk writable
dd if=$config_val count=1 of=/dev/null > /dev/null 2>&1 || {
perror_exit "Bad raw disk $config_val"
}
_praw=$(persistent_policy="by-id" get_persistent_dev $config_val)
if [ -z "$_praw" ]; then
exit 1
fi
add_dracut_arg "--device" "$_praw"
check_size raw $config_val
;;
ssh)
if strstr "$config_val" "@";
then
check_size ssh $config_val
mkdir_save_path_ssh $config_val
add_dracut_module "ssh-client"
add_dracut_sshkey "$SSH_KEY_LOCATION"
else
perror_exit "Bad ssh dump target $config_val"
fi
;;
core_collector)
verify_core_collector "$config_val"
;;
dracut_args)
add_dracut_arg $config_val
;;
*)
if [ -n $(echo $config_opt | grep "^#.*$") ]
then
continue
fi
;;
esac
done < $conf_file
handle_default_dump_target
if [ -n "$extra_modules" ]
then
add_dracut_arg "--add-drivers" "$extra_modules"
fi
if ! is_fadump_capable; then
# The 2nd rootfs mount stays behind the normal dump target mount,
# so it doesn't affect the logic of check_dump_fs_modified().
is_dump_to_rootfs && add_mount "$(to_dev_name $(get_root_fs_device))"
add_dracut_arg "--no-hostonly-default-device"
fi
dracut "${dracut_args[@]}" "$@"
_rc=$?
sync
exit $_rc

33
mkdumprd.8 Normal file
View file

@ -0,0 +1,33 @@
.TH MKDUMRD 8 "Fri Feb 9 2007"
.SH NAME
mkdumprd \- creates initial ramdisk images for kdump crash recovery
.SH SYNOPSIS
\fBmkdumprd\fR [OPTION]
.SH DESCRIPTION
\fBmkdumprd\fR creates an initial ram file system for use in conjunction with
the booting of a kernel within the kdump framework for crash recovery.
\fBmkdumprds\fR purpose is to create an initial ram filesystem capable of copying
the crashed systems vmcore image to a location specified in \fI/etc/kdump.conf
\fBmkdumprd\fR interrogates the running system to understand what modules need to
be loaded in the initramfs (based on configuration retrieved from
\fI/etc/kdump.conf)\fR
\fBmkdumprd\fR add a new \fBdracut\fR module 99kdumpbase and use \fBdracut\fR
utility to generate the initramfs.
\fBmkdumprd\fR was not intended for casual use outside of the service
initialization script for the kdump utility, and should not be run manually. If
you require a custom kdump initramfs image, it is suggested that you use the
kdump service infrastructure to create one, and then manually unpack, modify and
repack the image.
.SH OPTIONS
.TP
All options here are passed to dracut directly, please refer \fBdracut\fR docs
for the info.
.SH "SEE ALSO"
.BR dracut (8)

View file

@ -1 +1,3 @@
SHA512 (kexec-tools-2.0.32.tar.xz) = 60f120f8e46b9fb5dcf5a5b344ee8b303878ba9f71d58a3eefa1c9f044a6a2192b285154b738970263384c6e7281a854cd48a185334c08141aa4e6cf08230654
SHA512 (makedumpfile-1.6.5.tar.gz) = bfbf9b373d435857530121f29fb3915cb263cfbaa2b877684a8cde2e8cd8b73fc2f02ffdf9b9108613d42aab7e5653877b092846545ceab865e9909e86145970
SHA512 (eppic-d84c354.tar.gz) = 455b3386c3e4cc546b858f1f8b0e6874072aaae708ebe072452fb5f0b6a81b1f3a315b40f94c3967f38525cadd276864a7bc7f0f12fa421655dcc3b15b70914d
SHA512 (kexec-tools-2.0.19.tar.xz) = 68b15fe46f9633d55c5ae51a6e7114b0c66bd8f4fe81197f581121939a7b21990a2eea89a0961ac6eb7af364ba0d3981ea504df81c7b4cc0b288ca6ac896730f

View file

@ -1,41 +0,0 @@
#!/bin/bash
Describe 'kdump-lib-initramfs'
Include ./kdump-lib-initramfs.sh
Describe 'Test kdump_get_conf_val'
KDUMP_CONFIG_FILE=/tmp/kdump_shellspec_test.conf
kdump_config() {
%text
#|default shell
#|nfs my.server.com:/export/tmp # trailing comment
#| failure_action shell
#|dracut_args --omit-drivers "cfg80211 snd" --add-drivers "ext2 ext3"
#|sshkey /root/.ssh/kdump_id_rsa
#|ssh user@my.server.com
}
kdump_config >$KDUMP_CONFIG_FILE
Context 'Given different cases'
# Test the following cases:
# - there is trailing comment
# - there is space before the parameter
# - complicate value for dracut_args
# - Given two parameters, retrive one parameter that has value specified
# - Given two parameters (in reverse order), retrive one parameter that has value specified
Parameters
"#1" nfs my.server.com:/export/tmp
"#2" ssh user@my.server.com
"#3" failure_action shell
"#4" dracut_args '--omit-drivers "cfg80211 snd" --add-drivers "ext2 ext3"'
"#5" 'ssh\|aaa' user@my.server.com
"#6" 'aaa\|ssh' user@my.server.com
End
It 'should handle all cases correctly'
When call kdump_get_conf_val "$2"
The output should equal "$3"
End
End
End
End

View file

@ -1,121 +0,0 @@
#!/bin/bash
Describe 'kdump-lib'
Include ./kdump-lib.sh
Describe 'get_system_size()'
PROC_IOMEM=$(mktemp -t spec_test_proc_iomem_file.XXXXXXXXXX)
cleanup() {
rm -rf "$PROC_IOMEM"
}
AfterAll 'cleanup'
ONE_GIGABYTE='000000-3fffffff : System RAM'
Parameters
1
3
End
It 'should return correct system RAM size'
echo -n >"$PROC_IOMEM"
for _ in $(seq 1 "$1"); do echo "$ONE_GIGABYTE" >>"$PROC_IOMEM"; done
When call get_system_size
The output should equal "$1"
End
End
Describe 'get_recommend_size()'
# Testing stragety:
# 1. inclusive for the lower bound of the range of crashkernel
# 2. exclusive for the upper bound of the range of crashkernel
# 3. supports ranges not sorted in increasing order
ck="4G-64G:256M,2G-4G:192M,64G-1T:512M,1T-:12345M"
Parameters
1 0M
2 192M
64 512M
1024 12345M
"$((64 * 1024))" 12345M
End
It 'should handle all cases correctly'
When call get_recommend_size "$1" $ck
The output should equal "$2"
End
End
Describe "_crashkernel_add()"
Context "For valid input values"
Parameters
"1G-4G:256M,4G-64G:320M,64G-:576M" "100M" "1G-4G:356M,4G-64G:420M,64G-:676M"
"1G-4G:256M" "100" "1G-4G:268435556" # avoids any rounding when size % 1024 != 0
"1G-4G:256M,4G-64G:320M,64G-:576M@4G" "100M" "1G-4G:356M,4G-64G:420M,64G-:676M@4G"
"1G-4G:1G,4G-64G:2G,64G-:3G@4G" "100M" "1G-4G:1124M,4G-64G:2148M,64G-:3172M@4G"
"1G-4G:10000K,4G-64G:20000K,64G-:40000K@4G" "100M" "1G-4G:112400K,4G-64G:122400K,64G-:142400K@4G"
"1,high" "1" "2,high"
"1K,low" "1" "1025,low"
"128G-1T:4G" "0" "128G-1T:4G"
"10T-100T:1T" "0" "10T-100T:1T"
"128G-1T:4G" "0M" "128G-1T:4G"
"128G-1P:4G" "0M" "128G-1P:4G"
"128G-1E:4G" "0M" "128G-1E:4G"
"1M@1G" "1k" "1025K@1G"
"500M@1G" "-100m" "400M@1G"
"1099511627776" "0" "1T"
End
It "should add delta to every value after ':'"
When call _crashkernel_add "$1" "$2"
The output should equal "$3"
End
End
Context "For invalid input values"
Parameters
"1G-4G:256M.4G-64G:320M" "100M"
"foo" "1"
"1" "bar"
End
It "shall return an error"
When call _crashkernel_add "$1" "$2"
The output should equal ""
The status should be failure
End
End
End
Describe 'prepare_cmdline()'
get_bootcpu_apicid() {
echo 1
}
get_watchdog_drvs() {
echo foo
}
add="disable_cpu_apicid=1 foo.pretimeout=0"
Parameters
#test cmdline remove add result
"#1" "a b c" "" "" "a b c"
"#2" "a b c" "b" "" "a c"
"#3" "a b=x c" "b" "" "a c"
"#4" "a b='x y' c" "b" "" "a c"
"#5" "a b='x y' c" "b=x" "" "a c"
"#6" "a b='x y' c" "b='x y'" "" "a c"
"#7" "a b c" "" "x" "a b c x"
"#8" "a b c" "" "x=1" "a b c x=1"
"#9" "a b c" "" "x='1 2'" "a b c x='1 2'"
"#10" "a b c" "a" "x='1 2'" "b c x='1 2'"
"#11" "a b c" "x" "x='1 2'" "a b c x='1 2'"
End
It "Test $1: should generate the correct kernel command line"
When call prepare_cmdline "$2" "$3" "$4"
The output should equal "$5 $add"
End
End
End

View file

@ -1,215 +0,0 @@
#!/bin/bash
Describe 'kdumpctl'
Include ./kdumpctl
Describe 'get_grub_kernel_boot_parameter()'
grubby() {
%text
#|index=1
#|kernel="/boot/vmlinuz-5.14.14-200.fc34.x86_64"
#|args="crashkernel=11M nvidia-drm.modeset=1 crashkernel=100M ro rhgb quiet crcrashkernel=200M crashkernel=32T-64T:128G,64T-102400T:180G fadump=on"
#|root="UUID=45fdf703-3966-401b-b8f7-cf056affd2b0"
}
DUMMY_PARAM=/boot/vmlinuz
Context "when given a kernel parameter in different positions"
# Test the following cases:
# - the kernel parameter in the end
# - the kernel parameter in the first
# - the kernel parameter is crashkernel (suffix of crcrashkernel)
# - the kernel parameter that does not exist
# - the kernel parameter doesn't have a value
Parameters
# parameter answer
fadump on
nvidia-drm.modeset 1
crashkernel 32T-64T:128G,64T-102400T:180G
aaaa ""
ro ""
End
It 'should retrieve the value succesfully'
When call get_grub_kernel_boot_parameter "$DUMMY_PARAM" "$2"
The output should equal "$3"
End
End
It 'should retrive the last value if multiple <parameter=value> entries exist'
When call get_grub_kernel_boot_parameter "$DUMMY_PARAM" crashkernel
The output should equal '32T-64T:128G,64T-102400T:180G'
End
It 'should fail when called with kernel_path=ALL'
When call get_grub_kernel_boot_parameter ALL ro
The status should be failure
The error should include "kernel_path=ALL invalid"
End
End
Describe 'get_dump_mode_by_fadump_val()'
Context 'when given valid fadump values'
Parameters
"#1" on fadump
"#2" nocma fadump
"#3" "" kdump
"#4" off kdump
End
It "should return the dump mode correctly"
When call get_dump_mode_by_fadump_val "$2"
The output should equal "$3"
The status should be success
End
End
It 'should complain given invalid fadump value'
When call get_dump_mode_by_fadump_val /boot/vmlinuz
The status should be failure
The error should include 'invalid fadump'
End
End
Describe "read_proc_environ_var()"
environ_test_file=$(mktemp -t spec_test_environ_test_file.XXXXXXXXXX)
cleanup() {
rm -rf "$environ_test_file"
}
AfterAll 'cleanup'
echo -ne "container=bwrap-osbuild\x00SSH_AUTH_SOCK=/tmp/ssh-XXXXXXEbw33A/agent.1794\x00SSH_AGENT_PID=1929\x00env=test_env" >"$environ_test_file"
Parameters
container bwrap-osbuild
SSH_AUTH_SOCK /tmp/ssh-XXXXXXEbw33A/agent.1794
env test_env
not_exist ""
End
It 'should read the environ variable value as expected'
When call read_proc_environ_var "$1" "$environ_test_file"
The output should equal "$2"
The status should be success
End
End
Describe "_is_osbuild()"
environ_test_file=$(mktemp -t spec_test_environ_test_file.XXXXXXXXXX)
# shellcheck disable=SC2034
# override the _OSBUILD_ENVIRON_PATH variable
_OSBUILD_ENVIRON_PATH="$environ_test_file"
Parameters
'container=bwrap-osbuild' success
'' failure
End
It 'should be able to tell if it is the osbuild environment'
echo -ne "$1" >"$environ_test_file"
When call _is_osbuild
The status should be "$2"
The stderr should equal ""
End
End
Describe "_get_dracut_arg"
dracut_args='-o "foo bar baz" -t 1 --test="a b c" --omit bla'
Parameters
-o --omit 2 "foo bar baz bla"
-e --empty 0 ""
-t "" 1 "1"
"" --test 1 "a b c"
"" "" 0 ""
End
It "should parse the dracut_args correctly"
When call _get_dracut_arg "$1" "$2" "$dracut_args"
The status should equal $3
The output should equal "$4"
End
End
Describe "is_dracut_mod_omitted()"
KDUMP_CONFIG_FILE=$(mktemp -t kdump_conf.XXXXXXXXXX)
cleanup() {
rm -f "$kdump_conf"
}
AfterAll 'cleanup'
Parameters:dynamic
for opt in '-o ' '--omit ' '--omit='; do
for val in \
'foo' \
'"foo"' \
'"foo bar baz"' \
'"bar foo baz"' \
'"bar baz foo"'; do
%data success foo "$opt$val"
%data success foo "-a x $opt$val -i y"
%data failure xyz "$opt$val"
%data failure xyz "-a x $opt$val -i y"
done
done
%data success foo "-o xxx -o foo"
%data failure foo "-a x -i y"
End
It "shall return $1 for module $2 and dracut_args '$3'"
echo "dracut_args $3" > $KDUMP_CONFIG_FILE
parse_config
When call is_dracut_mod_omitted $2
The status should be $1
End
End
Describe '_find_kernel_path_by_release()'
# When the array length changes, the Parameters:dynamic should change as well
kernel_paths=(/boot/vmlinuz-6.2.11-200.fc37.x86_64
/boot/vmlinuz-5.14.0-316.el9.aarch64+64k
/boot/vmlinuz-5.14.0-322.el9.aarch64
/boot/efi/36b54597c46383/6.4.0-0.rc0.20230427git6e98b09da931.5.fc39.aarch64/linux)
kernels=(vmlinuz-6.2.11-200.fc37.x86_64
vmlinuz-5.14.0-316.el9.aarch64+64k
vmlinuz-5.14.0-322.el9.aarch64
6.4.0-0.rc0.20230427git6e98b09da931.5.fc39.aarch64)
grubby() {
for key in "${!kernel_paths[@]}"; do
echo "kernel=\"${kernel_paths[$key]}\""
done
}
Parameters:dynamic
# Due to a bug [1] in shellspec, hardcode the loop number instead of using the
# array length
# [1] https://github.com/shellspec/shellspec/issues/259
for key in {0..3}; do
%data "${kernels[$key]}" "${kernel_paths[$key]}"
done
End
It 'returns the kernel path for the given release'
When call _find_kernel_path_by_release "$1"
The output should equal "$2"
End
End
Describe 'parse_config()'
KDUMP_CONFIG_FILE=$(mktemp -t kdump_conf.XXXXXXXXXX)
cleanup() {
rm -f "$KDUMP_CONFIG_FILE"
}
AfterAll 'cleanup'
It 'should not be happy with unkown option in kdump.conf'
echo blabla > "$KDUMP_CONFIG_FILE"
When call parse_config
The status should be failure
The stderr should include 'Invalid kdump config option blabla'
End
Parameters:value aarch64 ppc64le s390x x86_64
It 'should be happy with the default kdump.conf'
./gen-kdump-conf.sh "$1" > "$KDUMP_CONFIG_FILE"
When call parse_config
The status should be success
End
End
End

View file

@ -1,118 +0,0 @@
#!/bin/bash
Describe 'Management of the kernel crashkernel parameter.'
Include ./kdumpctl
kernel1=/boot/vmlinuz-5.15.6-100.fc34.x86_64
kernel2=/boot/vmlinuz-5.14.14-200.fc34.x86_64
old_ck=1G-4G:162M,4G-64G:256M,64G-:512M
new_ck=1G-4G:196M,4G-64G:256M,64G-:512M
KDUMP_SPEC_TEST_RUN_DIR=$(mktemp -u /tmp/spec_test.XXXXXXXXXX)
GRUB_CFG="$KDUMP_SPEC_TEST_RUN_DIR/grub.cfg"
uname() {
if [[ $1 == '-m' ]]; then
echo -n x86_64
elif [[ $1 == '-r' ]]; then
echo -n $current_kernel
fi
}
# dinfo is a bit complex for unit tets, simply mock it
dinfo() {
echo "$1"
}
kdump_get_arch_recommend_crashkernel() {
echo -n "$new_ck"
}
setup() {
mkdir -p "$KDUMP_SPEC_TEST_RUN_DIR"
cp -r spec/support/boot_load_entries "$KDUMP_SPEC_TEST_RUN_DIR"
cp spec/support/grub_env "$KDUMP_SPEC_TEST_RUN_DIR"/env_temp
touch "$GRUB_CFG"
grubby --args crashkernel=$old_ck --update-kernel=$kernel1
grubby --args crashkernel=$new_ck --update-kernel=$kernel2
grubby --remove-args fadump --update-kernel=ALL
}
cleanup() {
rm -rf "$KDUMP_SPEC_TEST_RUN_DIR"
}
# the boot loader entries are for a system without a boot partition, mock
# mountpoint to let grubby know it
Mock mountpoint
exit 1
End
grubby() {
# - --no-etc-grub-update, not update /etc/default/grub
# - --bad-image-okay, don't check the validity of the image
# - --env, specify custom grub2 environment block file to avoid modifying
# the default /boot/grub2/grubenv
# - --bls-directory, specify custom BootLoaderSpec config files to avoid
# modifying the default /boot/loader/entries
/usr/sbin/grubby --no-etc-grub-update --grub2 --config-file="$GRUB_CFG" --bad-image-okay --env="$KDUMP_SPEC_TEST_RUN_DIR"/env_temp -b "$KDUMP_SPEC_TEST_RUN_DIR"/boot_load_entries "$@"
}
# The mocking breaks has_command. Mock it as well to fix the tests.
has_command() {
[[ "$1" == grubby ]]
}
Describe "When kexec-tools have its default crashkernel updated, "
Context "if kexec-tools is updated alone, "
BeforeAll 'setup'
AfterAll 'cleanup'
Specify 'reset_crashkernel_after_update should report updated kernels and note that auto_reset_crashkernel=yes'
When call reset_crashkernel_after_update
The output should include "For kernel=$kernel1, crashkernel=$new_ck now."
The output should not include "For kernel=$kernel2, crashkernel=$new_ck now."
# A hint on how to turn off auto update of crashkernel
The output should include "auto_reset_crashkernel=no"
End
Specify 'kernel1 should have crashkernel updated'
When call grubby --info $kernel1
The line 3 of output should include crashkernel="$new_ck"
End
Specify 'kernel2 should also have crashkernel updated'
When call grubby --info $kernel2
The line 3 of output should include crashkernel="$new_ck"
End
End
Context "If kernel package is installed alone, "
BeforeAll 'setup'
AfterAll 'cleanup'
# BeforeAll somehow doesn't work as expected, manually call setup to bypass this issue.
setup
new_kernel_ver=new_kernel
new_kernel=/boot/vmlinuz-$new_kernel_ver
grubby --add-kernel=$new_kernel --initrd=/boot/initramfs-$new_kernel_ver.img --title=$new_kernel_ver
Specify 'reset_crashkernel_for_installed_kernel should report the new kernel has its crashkernel updated'
When call reset_crashkernel_for_installed_kernel $new_kernel_ver
The output should include "crashkernel=$new_ck"
End
Specify 'the new kernel should have crashkernel updated'
When call grubby --info $new_kernel
The output should include crashkernel="$new_ck"
End
Specify 'kernel1 keeps its crashkernel value'
When call grubby --info $kernel1
The output should include crashkernel="$old_ck"
End
End
End
End

View file

@ -1,225 +0,0 @@
#!/bin/bash
Describe 'kdumpctl reset-crashkernel [--kernel] [--fadump]'
Include ./kdumpctl
kernel1=/boot/vmlinuz-5.15.6-100.fc34.x86_64
kernel2=/boot/vmlinuz-5.14.14-200.fc34.x86_64
ck=222M
KDUMP_SPEC_TEST_RUN_DIR=$(mktemp -d /tmp/spec_test.XXXXXXXXXX)
current_kernel=5.15.6-100.fc34.x86_64
setup() {
cp -r spec/support/boot_load_entries "$KDUMP_SPEC_TEST_RUN_DIR"
cp spec/support/grub_env "$KDUMP_SPEC_TEST_RUN_DIR"/env_temp
}
cleanup() {
rm -rf "$KDUMP_SPEC_TEST_RUN_DIR"
}
BeforeAll 'setup'
AfterAll 'cleanup'
# the boot loader entries are for a system without a boot partition, mock
# mountpoint to let grubby know it
Mock mountpoint
exit 1
End
grubby() {
# - --no-etc-grub-update, not update /etc/default/grub
# - --bad-image-okay, don't check the validity of the image
# - --env, specify custom grub2 environment block file to avoid modifying
# the default /boot/grub2/grubenv
# - --bls-directory, specify custom BootLoaderSpec config files to avoid
# modifying the default /boot/loader/entries
/usr/sbin/grubby --no-etc-grub-update --grub2 --bad-image-okay --env="$KDUMP_SPEC_TEST_RUN_DIR"/env_temp -b "$KDUMP_SPEC_TEST_RUN_DIR"/boot_load_entries "$@"
}
# The mocking breaks has_command. Mock it as well to fix the tests.
has_command() {
[[ "$1" == grubby ]]
}
Describe "Test the kdump dump mode "
uname() {
if [[ $1 == '-m' ]]; then
echo -n x86_64
elif [[ $1 == '-r' ]]; then
echo -n $current_kernel
fi
}
kdump_crashkernel=$(get_default_crashkernel kdump)
Context "when --kernel not specified"
grubby --args crashkernel=$ck --update-kernel ALL
Specify 'kdumpctl should warn the user that crashkernel has been udpated'
When call reset_crashkernel
The error should include "Updated crashkernel=$kdump_crashkernel"
End
Specify 'Current running kernel should have crashkernel updated'
When call grubby --info $kernel1
The line 3 of output should include crashkernel="$kdump_crashkernel"
The line 3 of output should not include crashkernel=$ck
End
Specify 'Other kernel still use the old crashkernel value'
When call grubby --info $kernel2
The line 3 of output should include crashkernel=$ck
End
End
Context "--kernel=ALL"
grubby --args crashkernel=$ck --update-kernel ALL
Specify 'kdumpctl should warn the user that crashkernel has been udpated'
When call reset_crashkernel --kernel=ALL
The error should include "Updated crashkernel=$kdump_crashkernel for kernel=$kernel1"
The error should include "Updated crashkernel=$kdump_crashkernel for kernel=$kernel2"
End
Specify 'kernel1 should have crashkernel updated'
When call grubby --info $kernel1
The line 3 of output should include crashkernel="$kdump_crashkernel"
End
Specify 'kernel2 should have crashkernel updated'
When call grubby --info $kernel2
The line 3 of output should include crashkernel="$kdump_crashkernel"
End
End
Context "--kernel=/boot/one-kernel to update one specified kernel"
grubby --args crashkernel=$ck --update-kernel ALL
Specify 'kdumpctl should warn the user that crashkernel has been updated'
When call reset_crashkernel --kernel=$kernel1
The error should include "Updated crashkernel=$kdump_crashkernel for kernel=$kernel1"
End
Specify 'kernel1 should have crashkernel updated'
When call grubby --info $kernel1
The line 3 of output should include crashkernel="$kdump_crashkernel"
End
Specify 'kernel2 should have the old crashkernel'
When call grubby --info $kernel2
The line 3 of output should include crashkernel=$ck
End
End
End
Describe "FADump" fadump
uname() {
if [[ $1 == '-m' ]]; then
echo -n ppc64le
elif [[ $1 == '-r' ]]; then
echo -n $current_kernel
fi
}
kdump_crashkernel=$(get_default_crashkernel kdump)
fadump_crashkernel=$(get_default_crashkernel fadump)
Context "when no --kernel specified"
grubby --args crashkernel=$ck --update-kernel ALL
grubby --remove-args=fadump --update-kernel ALL
Specify 'kdumpctl should warn the user that crashkernel has been udpated'
When call reset_crashkernel
The error should include "Updated crashkernel=$kdump_crashkernel"
End
Specify 'Current running kernel should have crashkernel updated'
When call grubby --info $kernel1
The line 3 of output should include crashkernel="$kdump_crashkernel"
End
Specify 'Other kernel still use the old crashkernel value'
When call grubby --info $kernel2
The line 3 of output should include crashkernel=$ck
End
End
Context "--kernel=ALL --fadump=on"
grubby --args crashkernel=$ck --update-kernel ALL
Specify 'kdumpctl should warn the user that crashkernel has been udpated'
When call reset_crashkernel --kernel=ALL --fadump=on
The error should include "Updated crashkernel=$fadump_crashkernel for kernel=$kernel1"
The error should include "Updated crashkernel=$fadump_crashkernel for kernel=$kernel2"
End
Specify 'kernel1 should have crashkernel updated'
When call grubby --info $kernel1
The line 3 of output should include crashkernel="$fadump_crashkernel"
End
Specify 'kernel2 should have crashkernel updated'
When call get_grub_kernel_boot_parameter $kernel2 crashkernel
The output should equal "$fadump_crashkernel"
End
End
Context "--kernel=/boot/one-kernel to update one specified kernel"
grubby --args crashkernel=$ck --update-kernel ALL
grubby --args fadump=on --update-kernel $kernel1
Specify 'kdumpctl should warn the user that crashkernel has been updated'
When call reset_crashkernel --kernel=$kernel1
The error should include "Updated crashkernel=$fadump_crashkernel for kernel=$kernel1"
End
Specify 'kernel1 should have crashkernel updated'
When call grubby --info $kernel1
The line 3 of output should include crashkernel="$fadump_crashkernel"
End
Specify 'kernel2 should have the old crashkernel'
When call get_grub_kernel_boot_parameter $kernel2 crashkernel
The output should equal $ck
End
End
Context "Update all kernels but without --fadump specified"
grubby --args crashkernel=$ck --update-kernel ALL
grubby --args fadump=on --update-kernel $kernel1
Specify 'kdumpctl should warn the user that crashkernel has been updated'
When call reset_crashkernel --kernel=$kernel1
The error should include "Updated crashkernel=$fadump_crashkernel for kernel=$kernel1"
End
Specify 'kernel1 should have crashkernel updated'
When call get_grub_kernel_boot_parameter $kernel1 crashkernel
The output should equal "$fadump_crashkernel"
End
Specify 'kernel2 should have the old crashkernel'
When call get_grub_kernel_boot_parameter $kernel2 crashkernel
The output should equal $ck
End
End
Context 'Switch between fadump=on and fadump=nocma'
grubby --args crashkernel=$ck --update-kernel ALL
grubby --args fadump=on --update-kernel ALL
Specify 'fadump=on to fadump=nocma'
When call reset_crashkernel --kernel=ALL --fadump=nocma
The error should include "Updated crashkernel=$fadump_crashkernel for kernel=$kernel1"
The error should include "Updated crashkernel=$fadump_crashkernel for kernel=$kernel2"
End
Specify 'kernel1 should have fadump=nocma in cmdline'
When call get_grub_kernel_boot_parameter $kernel1 fadump
The output should equal nocma
End
Specify 'fadump=nocma to fadump=on'
When call reset_crashkernel --kernel=ALL --fadump=on
The error should include "Updated fadump=on for kernel=$kernel1"
End
Specify 'kernel2 should have fadump=on in cmdline'
When call get_grub_kernel_boot_parameter $kernel1 fadump
The output should equal on
End
End
End
End

View file

@ -1,8 +0,0 @@
title Fedora (0-rescue-e986846f63134c7295458cf36300ba5b) 33 (Workstation Edition)
version 0-rescue-e986846f63134c7295458cf36300ba5b
linux /boot/vmlinuz-0-rescue-e986846f63134c7295458cf36300ba5b
initrd /boot/initramfs-0-rescue-e986846f63134c7295458cf36300ba5b.img
options root=UUID=45fdf703-3966-401b-b8f7-cf056affd2b0 ro rd.driver.blacklist=nouveau modprobe.blacklist=nouveau nvidia-drm.modeset=1 rhgb quiet rd.driver.blacklist=nouveau modprobe.blacklist=nouveau nvidia-drm.modeset=1 crashkernel=4G-16G:768M,16G-64G:1G,64G-128G:2G,128G-1T:4G,1T-2T:6G,2T-4T:12G,4T-8T:20G,8T-16T:36G,16T-32T:64G,32T-64T:128G,64T-102400T:180G fadump=on
grub_users $grub_users
grub_arg --unrestricted
grub_class kernel

View file

@ -1,8 +0,0 @@
title Fedora (5.14.14-200.fc34.x86_64) 34 (Workstation Edition)
version 5.14.14-200.fc34.x86_64
linux /boot/vmlinuz-5.14.14-200.fc34.x86_64
initrd /boot/initramfs-5.14.14-200.fc34.x86_64.img
options root=UUID=45fdf703-3966-401b-b8f7-cf056affd2b0 ro rd.driver.blacklist=nouveau modprobe.blacklist=nouveau nvidia-drm.modeset=1 rhgb quiet rd.driver.blacklist=nouveau modprobe.blacklist=nouveau nvidia-drm.modeset=1 crashkernel=4G-16G:768M,16G-64G:1G,64G-128G:2G,128G-1T:4G,1T-2T:6G,2T-4T:12G,4T-8T:20G,8T-16T:36G,16T-32T:64G,32T-64T:128G,64T-102400T:180G fadump=on
grub_users $grub_users
grub_arg --unrestricted
grub_class kernel

View file

@ -1,8 +0,0 @@
title Fedora (5.15.6-100.fc34.x86_64) 34 (Workstation Edition)
version 5.15.6-100.fc34.x86_64
linux /boot/vmlinuz-5.15.6-100.fc34.x86_64
initrd /boot/initramfs-5.15.6-100.fc34.x86_64.img
options root=UUID=45fdf703-3966-401b-b8f7-cf056affd2b0 ro rd.driver.blacklist=nouveau modprobe.blacklist=nouveau nvidia-drm.modeset=1 rhgb quiet rd.driver.blacklist=nouveau modprobe.blacklist=nouveau nvidia-drm.modeset=1 crashkernel=4G-16G:768M,16G-64G:1G,64G-128G:2G,128G-1T:4G,1T-2T:6G,2T-4T:12G,4T-8T:20G,8T-16T:36G,16T-32T:64G,32T-64T:128G,64T-102400T:180G fadump=on
grub_users $grub_users
grub_arg --unrestricted
grub_class fedora

View file

@ -1,3 +0,0 @@
# GRUB Environment Block
# WARNING: Do not edit this file by tools other than grub-editenv!!!
##################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################

View file

@ -1,88 +0,0 @@
TEST_CASE ?=
BASE_IMAGE ?=
TEST_ROOT := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
BUILD_ROOT := $(TEST_ROOT)/build
REPO = $(shell realpath $(TEST_ROOT)/../)
ARCH ?= $(shell arch)
SPEC = kexec-tools.spec
DIST ?= fedora
DIST_ABR ?= f
DIST_ABRL ?= fc
DIST_UNSET ?= rhel
RELEASE ?= 33
DEFAULT_BASE_IMAGE_VER ?= 1.2
DEFAULT_BASE_IMAGE ?= Fedora-Cloud-Base-$(RELEASE)-$(DEFAULT_BASE_IMAGE_VER).$(ARCH).raw.xz
DEFAULT_BASE_IMAGE_URL ?= https://dl.fedoraproject.org/pub/fedora/linux/releases/$(RELEASE)/Cloud/$(ARCH)/images/$(DEFAULT_BASE_IMAGE)
BUILD_ROOT = $(TEST_ROOT)/build
RPMDEFINE = --define '_sourcedir $(REPO)'\
--define '_specdir $(REPO)'\
--define '_builddir $(BUILD_ROOT)'\
--define '_srcrpmdir $(BUILD_ROOT)'\
--define '_rpmdir $(BUILD_ROOT)'\
--define 'dist %{?distprefix}.$(DIST_ABRL)$(RELEASE)'\
--define '$(DIST) $(RELEASE)'\
--eval '%undefine $(DIST_UNSET)'\
--define '$(DIST_ABRL)$(RELEASE) 1'\
KEXEC_TOOLS_SRC = $(filter-out $(REPO)/tests,$(wildcard $(REPO)/*))
KEXEC_TOOLS_TEST_SRC = $(wildcard $(REPO)/tests/scripts/**/*)
KEXEC_TOOLS_NVR = $(shell rpm $(RPMDEFINE) -q --specfile $(REPO)/$(SPEC) 2>/dev/null | grep -m 1 . | sed -e 's#.src#.$(ARCH)#')
KEXEC_TOOLS_RPM = $(BUILD_ROOT)/$(ARCH)/$(KEXEC_TOOLS_NVR).rpm
all: $(TEST_ROOT)/output/test-base-image
# Use either:
# fedpkg --release $(DIST_ABR)$(RELEASE) --path ../../ local
# or
# rpmbuild $(RPMDEFINE) -ba $(REPO)/$(SPEC)
# to rebuild the rpm, currently use rpmbuild to have better control over the rpm building process
#
$(KEXEC_TOOLS_RPM): $(KEXEC_TOOLS_SRC)
sh -c "cd .. && fedpkg --release f$(RELEASE) sources"
@echo Rebuilding RPM due to modification of sources: $?
rpmbuild $(RPMDEFINE) -ba $(REPO)/$(SPEC)
$(BUILD_ROOT)/base-image:
mkdir -p $(BUILD_ROOT)
ifeq ($(strip $(BASE_IMAGE)),)
wget $(DEFAULT_BASE_IMAGE_URL) -O $(BUILD_ROOT)/$(DEFAULT_BASE_IMAGE)
$(TEST_ROOT)/scripts/build-image.sh \
$(BUILD_ROOT)/$(DEFAULT_BASE_IMAGE)\
$(BUILD_ROOT)/base-image
else
$(TEST_ROOT)/scripts/build-image.sh \
$(BASE_IMAGE)\
$(BUILD_ROOT)/base-image
endif
$(BUILD_ROOT)/inst-base-image: $(BUILD_ROOT)/base-image
@echo "Building installation base image"
echo $(KEXEC_TOOLS_NVR)
$(TEST_ROOT)/scripts/build-image.sh \
$(BUILD_ROOT)/base-image \
$(BUILD_ROOT)/inst-base-image \
$(TEST_ROOT)/scripts/build-scripts/base-image.sh
$(TEST_ROOT)/output/test-base-image: $(BUILD_ROOT)/inst-base-image $(KEXEC_TOOLS_RPM) $(KEXEC_TOOLS_TEST_SRC) $(EXTRA_RPMS)
@echo "Building test base image"
mkdir -p $(TEST_ROOT)/output
$(TEST_ROOT)/scripts/build-image.sh \
$(BUILD_ROOT)/inst-base-image \
$(TEST_ROOT)/output/test-base-image \
$(TEST_ROOT)/scripts/build-scripts/test-base-image.sh \
$(KEXEC_TOOLS_RPM) $(EXTRA_RPMS)
test-run: $(TEST_ROOT)/output/test-base-image
ifeq ($(strip $(TEST_CASE)),)
$(TEST_ROOT)/scripts/run-test.sh
else
$(TEST_ROOT)/scripts/run-test.sh --console $(TEST_CASE)
endif
clean:
rm -rf $(TEST_ROOT)/build
rm -rf $(TEST_ROOT)/output

View file

@ -1,65 +0,0 @@
=====================
Kexec Kdump Self-test
=====================
Introduction
============
The self-tests here are useful for quick sanity tests for new patches, and also helpful for debugging issues.
How it works
============
All tests are run within VMs using qemu. By default, VM images are based on Fedora Cloud image, and the image for each test run is a layered qcow2 snapshot on top of the base image.
Test images are managed by Makefile, so if there are any code change in the kexec-tools repository, `make` command will detect that and only rebuild the top image layer. This makes the test runs boot fast and each test run is clean.
Basic usage
===========
Before you start, you can make the self-tests use your own base image by running following command:
`make clean && make BASE_IMAGE=<path/to/your/image>`
This is helpful if you have a slow network, else self-test will try to download the cloud image from Fedora's official website using `wget`.
- Use the following command to run all tests:
$ make test-run
All available tests will be executed.
Test artifacts are stored in output/<testcase>
- For easier debugging, you can run only on test with the following command:
$ make TEST_CASE=<testcase> test-run
This way, VM's console is directly connected to stdin/out so debugging will be easier.
If there are multiple VMs used in a test case, the VM performing actual kdump/kexec operation will be connected to stdin/out.
Test Cases
==========
Each test case is a folder under scripts/testcases/, a test case folder will contain at least one executable shell script, and each script should contain two functions: "on_build" and "on_test".
"on_build" is called when building the test image, which can instruct the self-test framework to install packages or create files, etc.
"on_test" is called when VM finished booting, which can get the boot count by calling "get_test_boot_count" and determine what to do. It should call "test_passed" on success, and call "test_failed" on failure. "test_aborted" is called when unexpected behavior occurs.
When there are multiple scripts in a single test case folder, they will spawn VMs in lexical order, and the last VM is considered the VM performing the actual test. Other VMs could be hosting test required service. This is useful for the network dump test. However, "test_passed" or "test_failed" or "test_aborted" could be called in any of these VMs, so during network kdump test, the dump target can also terminate the test and mark it passed when a valid vmcore is detected.
Debugging
=========
- When the test VM boots, you can append "no_test" to kernel args in grub, which tells the test services to quit early.
- You can launch the VMs manually or inspect the image after ran a test.
Test images are located as:
output/<testcase>/<vm-name>.img
Test images' corresponding qemu command are located as:
output/<testcase>/<vm-name>.qemu_cmd
To repeat/debug a test manually, you should launch all VMs in output/<testcase> menu in lexical order, and append 'no_test' in the last VM's grub cmdline, then VM will hang on login prompt, login with root/fedora. Test script is located as /kexec-kdump-test/test.sh
- If you just want to inspect the images file content, you can also use scripts/spawn-image-shell.sh <test-image> to spawn a shell in the image quickly.

View file

@ -1,57 +0,0 @@
#!/usr/bin/env bash
if [ $# -lt 2 ]; then
echo "Usage: $(basename $0) <base-image> <output-image> <build-script> [<build-script-args>]
Build a new <output-image> on top of <base-image>, and install
contents defined in <build-script>. <args> are directly passed
to <build-script>.
If <base-image> is raw, will copy it and create <output-image>
in qcow2 format.
If <base-image> is qcow2, will create <output-image> as a snapshot
on top of <base-image>"
exit 1
fi
BASEDIR=$(realpath $(dirname "$0"))
. $BASEDIR/image-init-lib.sh
# Base image to build from
BASE_IMAGE=$1 && shift
if [[ ! -e $BASE_IMAGE ]]; then
perror_exit "Base image '$BASE_IMAGE' not found"
else
BASE_IMAGE=$(realpath "$BASE_IMAGE")
fi
OUTPUT_IMAGE=$1 && shift
if [[ ! -d $(dirname $OUTPUT_IMAGE) ]]; then
perror_exit "Path '$(dirname $OUTPUT_IMAGE)' doesn't exists"
fi
INST_SCRIPT=$1 && shift
create_image_from_base_image $BASE_IMAGE $OUTPUT_IMAGE.building
mount_image $OUTPUT_IMAGE.building
img_inst() {
inst_in_image $OUTPUT_IMAGE.building $@
}
img_inst_pkg() {
inst_pkg_in_image $OUTPUT_IMAGE.building $@
}
img_run_cmd() {
run_in_image $OUTPUT_IMAGE.building "$@"
}
img_add_qemu_cmd() {
QEMU_CMD+="$@"
}
[ -e "$INST_SCRIPT" ] && source $INST_SCRIPT
mv $OUTPUT_IMAGE.building $OUTPUT_IMAGE

View file

@ -1,9 +0,0 @@
#!/bin/sh
img_inst_pkg grubby\
dnsmasq\
openssh openssh-server\
dracut-network dracut-squash squashfs-tools ethtool snappy kernel-modules
img_run_cmd "grubby --args systemd.journald.forward_to_console=1 systemd.log_target=console --update-kernel ALL"
img_run_cmd "grubby --args selinux=0 --update-kernel ALL"

View file

@ -1,21 +0,0 @@
#!/bin/sh
# Test RPMs to be installed
TEST_RPMS=
for _rpm in $@; do
if [[ ! -e $_rpm ]]; then
perror_exit "'$_rpm' not found"
else
TEST_RPMS="$TEST_RPMS $(realpath "$_rpm")"
fi
done
img_run_cmd "mkdir -p /kexec-kdump-test"
img_inst $TESTDIR/scripts/kexec-kdump-test/init.sh /kexec-kdump-test/init.sh
img_inst $TESTDIR/scripts/kexec-kdump-test/test.sh /kexec-kdump-test/test.sh
img_inst $TESTDIR/scripts/kexec-kdump-test/kexec-kdump-test.service /etc/systemd/system/kexec-kdump-test.service
img_run_cmd "systemctl enable kexec-kdump-test.service"
img_inst_pkg $TEST_RPMS
# Test script should start kdump manually to save time
img_run_cmd "systemctl disable kdump.service"

View file

@ -1,21 +0,0 @@
#!/usr/bin/env bash
. $TESTDIR/scripts/test-lib.sh
TEST_SCRIPT=$1
QEMU_CMD="$DEFAULT_QEMU_CMD \
-serial stdio \
-serial file:$(get_test_output_file $TEST_SCRIPT) \
-monitor none \
-hda $OUTPUT_IMAGE"
img_add_qemu_cmd() {
QEMU_CMD+=" $@"
}
source $TEST_SCRIPT
on_build
img_inst $TEST_SCRIPT /kexec-kdump-test/test.sh
echo $QEMU_CMD > $(get_test_qemu_cmd_file $TEST_SCRIPT)

View file

@ -1,25 +0,0 @@
#!/usr/bin/env bash
BASEDIR=$(realpath $(dirname "$0"))
. $BASEDIR/image-init-lib.sh
# Base image to copy from
BOOT_IMAGE=$1 && shift
if [ ! -e "$BOOT_IMAGE" ]; then
perror_exit "Image '$BOOT_IMAGE' not found"
else
BOOT_IMAGE=$(realpath "$BOOT_IMAGE")
fi
mount_image $BOOT_IMAGE
IMAGE_MNT=$(get_image_mount_root $BOOT_IMAGE)
SRC=
while [ $# -gt 1 ]; do
SRC="$SRC $IMAGE_MNT/$1"
shift
done
DST=$1
cp -rv $SRC $DST

View file

@ -1,275 +0,0 @@
#!/usr/bin/env bash
[ -z "$TESTDIR" ] && TESTDIR=$(realpath $(dirname "$0")/../)
SUDO="sudo"
declare -A MNTS=()
declare -A DEVS=()
perror() {
echo $@>&2
}
perror_exit() {
echo $@>&2
exit 1
}
is_mounted()
{
findmnt -k -n $1 &>/dev/null
}
clean_up()
{
for _mnt in ${MNTS[@]}; do
is_mounted $_mnt && $SUDO umount -f -R $_mnt
done
for _dev in ${DEVS[@]}; do
[ ! -e "$_dev" ] && continue
[[ "$_dev" == "/dev/loop"* ]] && $SUDO losetup -d "$_dev"
[[ "$_dev" == "/dev/nbd"* ]] && $SUDO qemu-nbd --disconnect "$_dev"
done
[ -d "$TMPDIR" ] && $SUDO rm --one-file-system -rf -- "$TMPDIR";
sync
}
trap '
ret=$?;
clean_up
exit $ret;
' EXIT
# clean up after ourselves no matter how we die.
trap 'exit 1;' SIGINT
readonly TMPDIR="$(mktemp -d -t kexec-kdump-test.XXXXXX)"
[ -d "$TMPDIR" ] || perror_exit "mktemp failed."
get_image_fmt() {
local image=$1 fmt
[ ! -e "$image" ] && perror "image: $image doesn't exist" && return 1
fmt=$(qemu-img info $image | sed -n "s/file format:\s*\(.*\)/\1/p")
[ $? -eq 0 ] && echo $fmt && return 0
return 1
}
fmt_is_qcow2() {
[ "$1" == "qcow2" ] || [ "$1" == "qcow2 backing qcow2" ]
}
# If it's partitioned, return the mountable partition, else return the dev
get_mountable_dev() {
local dev=$1 parts
$SUDO partprobe $dev && sync
parts="$(ls -1 ${dev}p*)"
if [ -n "$parts" ]; then
if [ $(echo "$parts" | wc -l) -gt 1 ]; then
perror "It's a image with multiple partitions, using last partition as main partition"
fi
echo "$parts" | tail -1
else
echo "$dev"
fi
}
# get the separate boot partition
# return the 2nd partition as boot partition
get_mount_boot() {
local dev=$1 _second_part=${dev}p2
# it's better to check if the 2nd partition has the boot label using lsblk
# but somehow this doesn't work starting with Fedora37
echo $_second_part
}
prepare_loop() {
[ -n "$(lsmod | grep "^loop")" ] && return
$SUDO modprobe loop
[ ! -e "/dev/loop-control" ] && perror_exit "failed to load loop driver"
}
prepare_nbd() {
[ -n "$(lsmod | grep "^nbd")" ] && return
$SUDO modprobe nbd max_part=4
[ ! -e "/dev/nbd0" ] && perror_exit "failed to load nbd driver"
}
mount_nbd() {
local image=$1 size dev
for _dev in /sys/class/block/nbd* ; do
size=$(cat $_dev/size)
if [ "$size" -eq 0 ] ; then
dev=/dev/${_dev##*/}
$SUDO qemu-nbd --connect=$dev $image 1>&2
[ $? -eq 0 ] && echo $dev && break
fi
done
return 1
}
image_lock()
{
local image=$1 timeout=5 fd
eval "exec {fd}>$image.lock"
if [ $? -ne 0 ]; then
perror_exit "failed acquiring image lock"
exit 1
fi
flock -n $fd
rc=$?
while [ $rc -ne 0 ]; do
echo "Another instance is holding the image lock ..."
flock -w $timeout $fd
rc=$?
done
}
# Mount a device, will umount it automatially when shell exits
mount_image() {
local image=$1 fmt
local dev mnt mnt_dev boot root
# Lock the image just in case user run this script in parrel
image_lock $image
fmt=$(get_image_fmt $image)
[ $? -ne 0 ] || [ -z "$fmt" ] && perror_exit "failed to detect image format"
if [ "$fmt" == "raw" ]; then
prepare_loop
dev="$($SUDO losetup --show -f $image)"
[ $? -ne 0 ] || [ -z "$dev" ] && perror_exit "failed to setup loop device"
elif fmt_is_qcow2 "$fmt"; then
prepare_nbd
dev=$(mount_nbd $image)
[ $? -ne 0 ] || [ -z "$dev" ] perror_exit "failed to connect qemu to nbd device '$dev'"
else
perror_exit "Unrecognized image format '$fmt'"
fi
DEVS[$image]="$dev"
mnt="$(mktemp -d -p $TMPDIR -t mount.XXXXXX)"
[ $? -ne 0 ] || [ -z "$mnt" ] && perror_exit "failed to create tmp mount dir"
MNTS[$image]="$mnt"
mnt_dev=$(get_mountable_dev "$dev")
[ $? -ne 0 ] || [ -z "$mnt_dev" ] && perror_exit "failed to setup loop device"
$SUDO mount $mnt_dev $mnt
[ $? -ne 0 ] && perror_exit "failed to mount device '$mnt_dev'"
boot=$(get_mount_boot "$dev")
if [[ -n "$boot" ]]; then
root=$(get_image_mount_root $image)
$SUDO mount $boot $root/boot
[ $? -ne 0 ] && perror_exit "failed to mount the bootable partition for device '$mnt_dev'"
fi
}
get_image_mount_root() {
local image=$1
local root=${MNTS[$image]}
# Starting from Fedora 36, the root node is /root/root of the last partition
[ -d "$root/root/root" ] && root=$root/root
echo $root
if [ -z "$root" ]; then
return 1
fi
}
shell_in_image() {
local root=$(get_image_mount_root $1) && shift
pushd $root
$SHELL
popd
}
inst_pkg_in_image() {
local root=$(get_image_mount_root $1) && shift
# LSB not available
# release_info=$($SUDO chroot $root /bin/bash -c "lsb_release -a")
# release=$(echo "$release_info" | sed -n "s/Release:\s*\(.*\)/\1/p")
# distro=$(echo "$release_info" | sed -n "s/Distributor ID:\s*\(.*\)/\1/p")
# if [ "$distro" != "Fedora" ]; then
# perror_exit "only Fedora image is supported"
# fi
release=$(cat $root/etc/fedora-release | sed -n "s/.*[Rr]elease\s*\([0-9]*\).*/\1/p")
[ $? -ne 0 ] || [ -z "$release" ] && perror_exit "only Fedora image is supported"
$SUDO dnf --releasever=$release --installroot=$root install -y $@
}
run_in_image() {
local root=$(get_image_mount_root $1) && shift
$SUDO chroot $root /bin/bash -c "$@"
}
inst_in_image() {
local image=$1 src=$2 dst=$3
local root=$(get_image_mount_root $1)
$SUDO cp $src $root/$dst
}
# If source image is qcow2, create a snapshot
# If source image is raw, convert to raw
# If source image is xz, decompress then repeat the above logic
#
# Won't touch source image
create_image_from_base_image() {
local image=$1
local output=$2
local decompressed_image
local ext="${image##*.}"
if [[ "$ext" == 'xz' ]]; then
echo "Decompressing base image..."
xz -d -k $image
decompressed_image=${image%.xz}
image=$decompressed_image
fi
local image_fmt=$(get_image_fmt $image)
if [ "$image_fmt" != "raw" ]; then
if fmt_is_qcow2 "$image_fmt"; then
echo "Source image is qcow2, using snapshot..."
qemu-img create -f qcow2 -b $image -F qcow2 $output
else
perror_exit "Unrecognized base image format '$image_mnt'"
fi
else
echo "Source image is raw, converting to qcow2..."
qemu-img convert -f raw -O qcow2 $image $output
fi
# Clean up decompress temp image
if [ -n "$decompressed_image" ]; then
rm $decompressed_image
fi
}

View file

@ -1,122 +0,0 @@
#!/usr/bin/env sh
BOOT_ARG="test_boot_count"
_YELLOW='\033[1;33m'
_GREEN='\033[0;32m'
_RED='\033[0;31m'
_NC='\033[0m' # No Color
if [ -n "$(cat /proc/cmdline | grep "\bno_test\b")" ]; then
exit 0
fi
get_test_boot_count() {
local boot_count=$(cat /proc/cmdline | sed -n "s/.*$BOOT_ARG=\([0-9]*\).*/\1/p")
if [ -z "$boot_count" ]; then
boot_count=1
fi
echo $boot_count
}
test_output() {
echo $@ > /dev/ttyS1
echo $@ > /dev/ttyS0
sync
}
test_passed() {
echo -e "${_GREEN}TEST PASSED${_NC}" > /dev/ttyS1
echo -e "${_GREEN}kexec-kdump-test: TEST PASSED${_NC}" > /dev/ttyS0
echo $@ > /dev/ttyS1
echo $@ > /dev/ttyS0
sync
shutdown -h 0
exit 0
}
test_failed() {
echo -e "${_RED}TEST FAILED${_NC}" > /dev/ttyS1
echo -e "${_RED}kexec-kdump-test: TEST FAILED${_NC}" > /dev/ttyS0
echo $@ > /dev/ttyS1
echo $@ > /dev/ttyS0
sync
shutdown -h 0
exit 1
}
test_abort() {
echo -e "${_YELLOW}TEST ABORTED${_NC}" > /dev/ttyS1
echo -e "${_YELLOW}kexec-kdump-test: TEST ABORTED${_NC}" > /dev/ttyS0
echo $@ > /dev/ttyS1
echo $@ > /dev/ttyS0
sync
shutdown -h 0
exit 2
}
has_valid_vmcore_dir() {
local path=$1
local vmcore_dir=$path/$(ls -1 $path | tail -n 1)
local vmcore="<invalid>"
test_output "Found a vmcore dir \"$vmcore_dir\":"
# Checking with `crash` is slow and consume a lot of memory/disk,
# just do a sanity check by check if log are available.
if [ -e $vmcore_dir/vmcore ]; then
vmcore=$vmcore_dir/vmcore
makedumpfile --dump-dmesg $vmcore $vmcore_dir/vmcore-dmesg.txt.2 || {
test_output "Failed to retrive dmesg from vmcore!"
return 1
}
elif [ -e $vmcore_dir/vmcore.flat ]; then
vmcore=$vmcore_dir/vmcore.flat
makedumpfile -R $vmcore_dir/vmcore < $vmcore || return 1
makedumpfile --dump-dmesg $vmcore_dir/vmcore $vmcore_dir/vmcore-dmesg.txt.2 || {
test_output "Failed to retrive dmesg from vmcore!"
return 1
}
rm $vmcore_dir/vmcore
else
test_output "The vmcore dir is empty!"
return 1
fi
if ! diff -w $vmcore_dir/vmcore-dmesg.txt.2 $vmcore_dir/vmcore-dmesg.txt; then
test_output "Dmesg retrived from vmcore is different from dump version!"
return 1
fi
test_output "VMCORE: $vmcore"
test_output "KERNEL VERSION: $(rpm -q kernel-core)"
return 0
}
BOOT_COUNT=$(get_test_boot_count)
test_output "Kexec-Kdump-Test Boot #$BOOT_COUNT"
echo 'fedora' | passwd --stdin root
test_output "Updating kernel cmdline"
grubby --update-kernel ALL --args $BOOT_ARG=$(expr $BOOT_COUNT + 1) && sync
test_output "Executing test hook"
source /kexec-kdump-test/test.sh
on_test;
test_output "Test exited, system hang for inspect"

View file

@ -1,9 +0,0 @@
[Unit]
Description=Kexec Kdump Test Service
[Service]
ExecStart=/kexec-kdump-test/init.sh
Type=idle
[Install]
WantedBy=multi-user.target

View file

@ -1,15 +0,0 @@
#!/usr/bin/env sh
# A test example that do nothing
# Executed before VM starts
on_build() {
:
}
# Executed when VM boots
on_test() {
:
# call get_test_boot_count to get boot cound
# call test_passed if test passed
# call test_failed if test passed
}

View file

@ -1,23 +0,0 @@
#!/bin/bash
# Check which virtualization technology to use
# We prefer kvm, kqemu, userspace in that order.
# This script is based on https://github.com/dracutdevs/dracut/blob/master/test/run-qemu
export PATH=/sbin:/bin:/usr/sbin:/usr/bin
[[ -x /usr/bin/qemu ]] && BIN=/usr/bin/qemu && ARGS="-cpu max"
$(lsmod | grep -q '^kqemu ') && BIN=/usr/bin/qemu && ARGS="-kernel-kqemu -cpu host"
[[ -c /dev/kvm && -x /usr/bin/kvm ]] && BIN=/usr/bin/kvm && ARGS="-cpu host"
[[ -c /dev/kvm && -x /usr/bin/qemu-kvm ]] && BIN=/usr/bin/qemu-kvm && ARGS="-cpu host"
[[ -c /dev/kvm && -x /usr/libexec/qemu-kvm ]] && BIN=/usr/libexec/qemu-kvm && ARGS="-cpu host"
[[ -x /usr/bin/qemu-system-$(uname -i) ]] && BIN=/usr/bin/qemu-system-$(uname -i) && ARGS="-cpu max"
[[ -c /dev/kvm && -x /usr/bin/qemu-system-$(uname -i) ]] && BIN=/usr/bin/qemu-system-$(uname -i) && ARGS="-enable-kvm -cpu host"
[[ $BIN ]] || {
echo "Could not find a working KVM or QEMU to test with!" >&2
echo "Please install kvm or qemu." >&2
exit 1
}
exec $BIN $ARGS "$@"

View file

@ -1,176 +0,0 @@
#!/bin/bash
_kill_if_valid_pid() {
local _pid="$1"
if ps -p "$_pid" > /dev/null
then
kill "$_pid"
fi
}
_recursive_kill() {
local _pid="$1"
local _children _child
_children=$(pgrep -P "$_pid")
if [ -n "$_children" ]; then
for _child in $_children
do
_recursive_kill "$_child"
_kill_if_valid_pid "$_child"
done
fi
_kill_if_valid_pid "$_pid"
}
_kill_all_jobs() {
local _jobs=$(jobs -r -p)
local _job
if [ -n "$_jobs" ]; then
for _job in $_jobs
do
_recursive_kill "$_job"
done
fi
}
trap '
ret=$?;
_kill_all_jobs
exit $ret;
' EXIT
trap 'exit 1;' SIGINT
BASEDIR=$(realpath $(dirname "$0"))
. $BASEDIR/test-lib.sh
TESTCASEDIR="$BASEDIR/testcases"
console=0
testcases=""
while [ $# -gt 0 ]; do
case $1 in
'')
break
;;
--console )
console=1
;;
-*)
echo "Invalid option $1"
;;
*)
testcases+=" $1"
;;
esac
shift;
done
if [ -z "$testcases" ]; then
echo "==== Starting all tests: ===="
testcases=$(ls -1 $TESTCASEDIR)
else
echo "==== Starting specified tests: ===="
fi
echo ${testcases##*/}
echo
declare -A results
ret=0
for test_case in $testcases; do
echo "======== Running Test Case $test_case ========"
results[$test_case]="<Test Skipped>"
testdir=$TESTCASEDIR/$test_case
scripts=$(ls -r -1 $testdir | egrep "\.sh$" | tr '\n' ' ')
test_outputs=""
read main_script aux_script <<< "$scripts"
if [ -z "$main_script" ]; then
echo "ERROR: Empty testcase dir $testdir"
continue
fi
for script in $scripts; do
echo "---- Building image for: $script ----"
echo "-------- Output image is: $(get_test_image $testdir/$script)"
echo "-------- Building log is: $(get_test_image $testdir/$script).log"
mkdir -p $(dirname $(get_test_image $testdir/$script))
build_test_image $testdir/$script &> $(get_test_image $testdir/$script).log
if [ $? -ne 0 ]; then
echo "Failing building image!"
continue 2
fi
done
for script in $aux_script; do
echo "---- Starting VM: $script ----"
script="$testdir/$script"
echo "-------- Qemu cmdline: $(get_test_qemu_cmd_file $script)"
echo "-------- Console log: $(get_test_console_file $script)"
echo "-------- Test log: $(get_test_output_file $script)"
test_outputs+="$(get_test_output_file $script) "
rm -f $(get_test_console_file $script)
rm -f $(get_test_output_file $script)
$(run_test_sync $script > $(get_test_console_file $script)) &
sleep 5
done
script="$main_script"
echo "---- Starting test VM: $(basename $script) ----"
script="$testdir/$script"
echo "-------- Qemu cmdline: $(get_test_qemu_cmd_file $script)"
echo "-------- Console log: $(get_test_console_file $script)"
echo "-------- Test log: $(get_test_output_file $script)"
test_outputs+="$(get_test_output_file $script) "
rm -f $(get_test_console_file $script)
rm -f $(get_test_output_file $script)
if [ $console -eq 1 ]; then
run_test_sync $script | tee $(get_test_console_file $script)
[ -n "$(jobs -p)" ] && wait $(jobs -p)
else
$(run_test_sync $script > $(get_test_console_file $script)) &
watch_test_outputs $test_outputs
fi
res="$(gather_test_result $test_outputs)"
[ $? -ne 0 ] && ret=$(expr $ret + 1)
results[$test_case]="$res"
_kill_all_jobs
echo -e "-------- Test finished: $test_case $res --------"
for script in $scripts; do
script="$testdir/$script"
output="$(get_test_output_file $script) "
image="$(get_test_image $script)"
vmcore="$(sed -n 's/^VMCORE: \(\S*\).*/\1/p' $output)"
kernel="$(sed -n 's/^KERNEL VERSION: \(\S*\).*/\1/p' $output)"
if [ -n "$vmcore" ]; then
echo "You can retrive the verify the vmcore file using following command:"
echo "./scripts/copy-from-image.sh \\"
echo " $image \\"
echo " $vmcore ./"
echo "Kernel package verion is: $kernel"
fi
done
done
echo "======== Test results ========"
for i in ${!results[@]}; do
echo "----------------"
echo -e "$i:\t\t${results[$i]}"
done
exit $ret

View file

@ -1,16 +0,0 @@
#!/usr/bin/env bash
BASEDIR=$(realpath $(dirname "$0"))
. $BASEDIR/image-init-lib.sh
# Base image to build from
BOOT_IMAGE=$1
if [[ ! -e $BOOT_IMAGE ]]; then
perror_exit "Image '$BOOT_IMAGE' not found"
else
BOOT_IMAGE=$(realpath "$BOOT_IMAGE")
fi
mount_image $BOOT_IMAGE
shell_in_image $BOOT_IMAGE

View file

@ -1,176 +0,0 @@
#!/usr/bin/env sh
[ -z "$BASEDIR" ] && BASEDIR=$(realpath $(dirname "$0"))
[ -z "$TESTDIR" ] && TESTDIR=$(realpath $BASEDIR/../)
[ -z "$TEST_BASE_IMAGE" ] && TEST_BASE_IMAGE=$TESTDIR/output/test-base-image
[[ ! -e $TEST_BASE_IMAGE ]] && echo "Test base image not found." && exit 1
DEFAULT_QEMU_CMD="-nodefaults \
-nographic \
-smp 2 \
-m 1G \
-monitor none"
_YELLOW='\033[1;33m'
_GREEN='\033[0;32m'
_RED='\033[0;31m'
_NC='\033[0m' # No Color
get_test_path() {
local script=$1
local testname=$(basename $(dirname $script))
local output=$TESTDIR/output/$testname
echo $output
}
get_test_entry_name() {
echo $(basename ${1%.*})
}
get_test_image() {
local script=$1
local testout=$(get_test_path $script)
local entry=$(get_test_entry_name $script)
echo $testout/$entry.img
}
get_test_qemu_cmd_file() {
local script=$1
local testout=$(get_test_path $script)
local entry=$(get_test_entry_name $script)
echo $testout/$entry.qemu_cmd
}
get_test_qemu_cmd() {
cat $(get_test_qemu_cmd_file $1)
}
get_test_output_file() {
local script=$1
local testout=$(get_test_path $script)
local entry=$(get_test_entry_name $script)
echo $testout/$entry.output
}
get_test_console_file() {
local script=$1
local testout=$(get_test_path $script)
local entry=$(get_test_entry_name $script)
echo $testout/$entry.console
}
get_test_output() {
local output=$(get_test_output_file $1)
if [ -e "$output" ]; then
cat $(get_test_output_file $1)
else
echo "<No Output>"
fi
}
build_test_image() {
local script=$1
local test_image=$(get_test_image $script)
mkdir -p $(dirname $test_image)
$BASEDIR/build-image.sh \
$TEST_BASE_IMAGE \
$test_image \
$BASEDIR/build-scripts/test-image.sh \
$script
}
run_test_sync() {
local qemu_cmd=$(get_test_qemu_cmd $1)
if [ -n "$qemu_cmd" ]; then
timeout --foreground 10m $BASEDIR/run-qemu $(get_test_qemu_cmd $1)
else
echo "error: test qemu command line is not configured" > /dev/stderr
return 1
fi
}
_check_test_result() {
grep "TEST PASSED" $1 2>/dev/null
[ $? -eq 0 ] && return 0
grep "TEST FAILED" $1 2>/dev/null
[ $? -eq 0 ] && return 1
grep "TEST ABORTED" $1 2>/dev/null
[ $? -eq 0 ] && return 2
return 255
}
# Print test result and return below value:
# 0: Test passed
# 1: Test failed
# 2: Test aborted, test scripts errored out
# 3: Test exited unexpectely, VM got killed early, or time out
gather_test_result() {
local ret=255
local res=""
for i in $@; do
res=$(_check_test_result $i)
ret=$?
if [ $ret -ne 255 ]; then
echo $res
return $ret
fi
done
echo "${_RED}TEST RESULT NOT FOUND!${_NC}"
return 3
}
# Wait and watch for test result
watch_test_outputs() {
local ret=255
local res=""
# If VMs are still running, check for test result, if
# test finished, kill remaining VMs
while true; do
if [ -n "$(jobs -r)" ]; then
# VMs still running
for i in $@; do
res=$(_check_test_result $i)
ret=$?
if [ $ret -ne 255 ]; then
# Test finished
break 2
fi
done
else
# VMs exited
ret=255
for i in $@; do
res=$(_check_test_result $i)
ret=$?
if [ $ret -ne 255 ]; then
break 2
fi
done
if [ $ret -eq 255 ]; then
ret=3
break
fi
fi
sleep 1
done
return $ret
}

View file

@ -1,32 +0,0 @@
on_build() {
:
}
on_test() {
local boot_count=$(get_test_boot_count)
if [ $boot_count -eq 1 ]; then
cat << EOF > /etc/kdump.conf
path /var/crash
core_collector makedumpfile -l --message-level 7 -d 31
EOF
kdumpctl start || test_failed "Failed to start kdump"
sync
echo 1 > /proc/sys/kernel/sysrq
echo c > /proc/sysrq-trigger
elif [ $boot_count -eq 2 ]; then
if has_valid_vmcore_dir /var/crash; then
test_passed
else
test_failed "Vmcore missing"
fi
shutdown -h 0
else
test_failed "Unexpected reboot"
fi
}

View file

@ -1,59 +0,0 @@
on_build() {
TEST_DIR_PREFIX=/tmp/lvm_test.XXXXXX
# clear TEST_DIRs if any
rm -rf ${TEST_DIR_PREFIX%.*}.*
TEST_IMG="$(mktemp -d $TEST_DIR_PREFIX)/test.img"
img_inst_pkg "lvm2"
img_inst $TESTDIR/scripts/testcases/lvm2-thinp-kdump/lvm.conf /etc/lvm/
dd if=/dev/zero of=$TEST_IMG bs=300M count=1
# The test.img will be /dev/sdb
img_add_qemu_cmd "-hdb $TEST_IMG"
}
on_test() {
VG=vg00
LV_THINPOOL=thinpool
LV_VOLUME=thinlv
VMCORE_PATH=var/crash
local boot_count=$(get_test_boot_count)
if [ $boot_count -eq 1 ]; then
vgcreate $VG /dev/sdb
# Create a small thinpool which is definitely not enough for
# vmcore, then create a thin volume which is definitely enough
# for vmcore, so we can make sure thinpool should be autoextend
# during runtime.
lvcreate -L 10M -T $VG/$LV_THINPOOL
lvcreate -V 300M -T $VG/$LV_THINPOOL -n $LV_VOLUME
mkfs.ext4 /dev/$VG/$LV_VOLUME
mount /dev/$VG/$LV_VOLUME /mnt
mkdir -p /mnt/$VMCORE_PATH
cat << EOF > /etc/kdump.conf
ext4 /dev/$VG/$LV_VOLUME
path /$VMCORE_PATH
core_collector makedumpfile -l --message-level 7 -d 31
EOF
kdumpctl start || test_failed "Failed to start kdump"
sync
echo 1 > /proc/sys/kernel/sysrq
echo c > /proc/sysrq-trigger
elif [ $boot_count -eq 2 ]; then
mount /dev/$VG/$LV_VOLUME /mnt
if has_valid_vmcore_dir /mnt/$VMCORE_PATH; then
test_passed
else
test_failed "Vmcore missing"
fi
shutdown -h 0
else
test_failed "Unexpected reboot"
fi
}

View file

@ -1,5 +0,0 @@
activation {
thin_pool_autoextend_threshold = 70
thin_pool_autoextend_percent = 20
monitoring = 1
}

View file

@ -1 +0,0 @@
../nfs-kdump/0-server.sh

View file

@ -1,46 +0,0 @@
# Executed before VM starts
on_build() {
img_inst_pkg "nfs-utils"
img_add_qemu_cmd "-nic socket,connect=127.0.0.1:8010,mac=52:54:00:12:34:57"
}
on_test() {
local boot_count=$(get_test_boot_count)
local nfs_server=192.168.77.1
local earlykdump_path="/usr/lib/dracut/modules.d/99earlykdump/early-kdump.sh"
local tmp_file="/tmp/.tmp-file"
if [[ ! -f $earlykdump_path ]]; then
test_failed "early-kdump.sh not exist!"
fi
if [ $boot_count -eq 1 ]; then
cat << EOF > /etc/kdump.conf
nfs $nfs_server:/srv/nfs
core_collector makedumpfile -l --message-level 7 -d 31
final_action poweroff
EOF
while ! ping -c 1 $nfs_server -W 1; do
sleep 1
done
kdumpctl start \
|| test_failed "Failed to start kdump"
grubby --update-kernel=ALL --args=rd.earlykdump
cat << EOF > $tmp_file
echo 1 > /proc/sys/kernel/sysrq
echo c > /proc/sysrq-trigger
EOF
sed -i "/early_kdump_load$/r $tmp_file" $earlykdump_path
dracut -f --add earlykdump
kdumpctl restart \
|| test_failed "Failed to start earlykdump"
sync
reboot
else
test_failed "Unexpected reboot"
fi
}

View file

@ -1,42 +0,0 @@
#!/usr/bin/env sh
# Executed before VM starts
on_build() {
img_inst_pkg "nfs-utils dnsmasq"
img_run_cmd "mkdir -p /srv/nfs/var/crash"
img_run_cmd "echo /srv/nfs 192.168.77.1/24\(rw,async,insecure,no_root_squash\) > /etc/exports"
img_run_cmd "systemctl enable nfs-server"
img_run_cmd "touch /etc/systemd/resolved.conf"
img_run_cmd "echo DNSStubListener=no >> /etc/systemd/resolved.conf"
img_run_cmd "echo interface=eth0 > /etc/dnsmasq.conf"
img_run_cmd "echo dhcp-authoritative >> /etc/dnsmasq.conf"
img_run_cmd "echo dhcp-range=192.168.77.50,192.168.77.100,255.255.255.0,12h >> /etc/dnsmasq.conf"
img_run_cmd "systemctl enable dnsmasq"
img_run_cmd 'echo [connection] > /etc/NetworkManager/system-connections/eth0.nmconnection'
img_run_cmd 'echo type=ethernet >> /etc/NetworkManager/system-connections/eth0.nmconnection'
img_run_cmd 'echo interface-name=eth0 >> /etc/NetworkManager/system-connections/eth0.nmconnection'
img_run_cmd 'echo [ipv4] >> /etc/NetworkManager/system-connections/eth0.nmconnection'
img_run_cmd 'echo address1=192.168.77.1/24 >> /etc/NetworkManager/system-connections/eth0.nmconnection'
img_run_cmd 'echo method=manual >> /etc/NetworkManager/system-connections/eth0.nmconnection'
img_run_cmd 'chmod 600 /etc/NetworkManager/system-connections/eth0.nmconnection'
img_add_qemu_cmd "-nic socket,listen=:8010,mac=52:54:00:12:34:56"
}
# Executed when VM boots
on_test() {
while true; do
if has_valid_vmcore_dir /srv/nfs/var/crash; then
# Wait a few seconds so client finish it's work to generate a full log
sleep 5
test_passed
fi
sleep 1
done
}

View file

@ -1,30 +0,0 @@
# Executed before VM starts
on_build() {
img_inst_pkg "nfs-utils"
img_add_qemu_cmd "-nic socket,connect=127.0.0.1:8010,mac=52:54:00:12:34:57"
}
on_test() {
local boot_count=$(get_test_boot_count)
local nfs_server=192.168.77.1
if [ "$boot_count" -eq 1 ]; then
cat << EOF > /etc/kdump.conf
nfs $nfs_server:/srv/nfs
core_collector makedumpfile -l --message-level 7 -d 31
EOF
while ! ping -c 1 $nfs_server -W 1; do
sleep 1
done
kdumpctl start || test_failed "Failed to start kdump"
sync
echo 1 > /proc/sys/kernel/sysrq
echo c > /proc/sysrq-trigger
else
shutdown -h 0
fi
}

View file

@ -1,38 +0,0 @@
#!/usr/bin/env sh
# Executed before VM starts
on_build() {
img_add_qemu_cmd "-nic socket,listen=:8010,mac=52:54:00:12:34:56"
img_run_cmd "echo root:fedora | chpasswd"
img_run_cmd 'sed -i "s/^.*PasswordAuthentication .*\$/PasswordAuthentication yes/" /etc/ssh/sshd_config'
img_run_cmd 'sed -i "s/^.*PermitRootLogin .*\$/PermitRootLogin yes/" /etc/ssh/sshd_config'
img_run_cmd "systemctl enable sshd"
img_run_cmd "touch /etc/systemd/resolved.conf"
img_run_cmd "echo DNSStubListener=no >> /etc/systemd/resolved.conf"
img_run_cmd "echo interface=eth0 > /etc/dnsmasq.conf"
img_run_cmd "echo dhcp-authoritative >> /etc/dnsmasq.conf"
img_run_cmd "echo dhcp-range=192.168.77.50,192.168.77.100,255.255.255.0,12h >> /etc/dnsmasq.conf"
img_run_cmd "systemctl enable dnsmasq"
img_run_cmd 'echo [connection] > /etc/NetworkManager/system-connections/eth0.nmconnection'
img_run_cmd 'echo type=ethernet >> /etc/NetworkManager/system-connections/eth0.nmconnection'
img_run_cmd 'echo interface-name=eth0 >> /etc/NetworkManager/system-connections/eth0.nmconnection'
img_run_cmd 'echo [ipv4] >> /etc/NetworkManager/system-connections/eth0.nmconnection'
img_run_cmd 'echo address1=192.168.77.1/24 >> /etc/NetworkManager/system-connections/eth0.nmconnection'
img_run_cmd 'echo method=manual >> /etc/NetworkManager/system-connections/eth0.nmconnection'
img_run_cmd 'chmod 600 /etc/NetworkManager/system-connections/eth0.nmconnection'
}
# Executed when VM boots
on_test() {
while true; do
if has_valid_vmcore_dir /var/crash; then
test_passed
fi
sleep 1
done
}

View file

@ -1,42 +0,0 @@
# Executed before VM starts
on_build() {
img_inst_pkg "sshpass"
img_add_qemu_cmd "-nic socket,connect=127.0.0.1:8010,mac=52:54:00:12:34:57"
}
on_test() {
local boot_count=$(get_test_boot_count)
local ssh_server=192.168.77.1
if [ "$boot_count" -eq 1 ]; then
cat << EOF > /etc/kdump.conf
ssh root@192.168.77.1
core_collector makedumpfile -l --message-level 7 -d 31 -F
EOF
ssh-keygen -q -t rsa -N '' -f /root/.ssh/id_rsa <<< y
while ! ping -c 1 $ssh_server -W 1; do
sleep 1
done
while [ -z "$(cat /root/.ssh/known_hosts)" ]; do
ssh-keyscan -H 192.168.77.1 > /root/.ssh/known_hosts
done
sshpass -p fedora ssh $ssh_server "mkdir /root/.ssh"
cat /root/.ssh/id_rsa.pub | sshpass -p fedora ssh $ssh_server "cat >> /root/.ssh/authorized_keys"
sshpass -p fedora kdumpctl propagate
cat /root/.ssh/kdump_id_rsa.pub | sshpass -p fedora ssh $ssh_server "cat >> /root/.ssh/authorized_keys"
kdumpctl start || test_failed "Failed to start kdump"
sync
echo 1 > /proc/sys/kernel/sysrq
echo c > /proc/sysrq-trigger
else
shutdown -h 0
fi
}

79
zanata-notes.txt Normal file
View file

@ -0,0 +1,79 @@
Zanata is a web-based system for managing localisation projects.
For kexec-tools firstboot module, I created a zanata project with name of
"kexec-tools": https://translate.zanata.org/zanata/project/view/kexec-tools
There's several clients available for zanata translation management, such as
python client and Maven client. It's suggested to use maven client for latest
zanata issues
Firstly you need install mvn rpms, just do below for fedora 16 and beyond:
yum install maven
create zanata.ini in your home dir:
>~/.config/zanata.ini
There should be something need to change like below:
translate_zanata_org.url=https://translate.zanata.org/zanata/
translate_zanata_org.username=
translate_zanata_org.key=
Change username to your zanata username
Change the key to the "API key" of zanata which can be generate from
zanata web page.
Open user profile page of zanata.org, click "Generate API Key" to create it.
zanata is a plugin of maven, to activate it, you need do below configurations:
1. cd kexec-tools/po, (assume kexec-tools is the git repo)
2. add a pom.xml like below: (note: version 2.0.0 is better than 1.7.5
for performance improvement)
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.zanata</groupId>
<artifactId>zanata-maven-plugin</artifactId>
<version>1.7.5</version>
</plugin>
</plugins>
</build>
...
</project>
3. add zanata.xml for your project with content like below:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<config xmlns="http://zanata.org/namespace/config/">
<url>https://translate.zanata.org/zanata/</url>
<project>kexec-tools</project>
<project-version>F18</project-version>
<project-type>gettext</project-type>
<locales>
<locale>ar</locale>
...
</config>
You can get mostly-complete zanata.xml from the project version page on zanata
Things need to be modified is:
a) project-type, please use gettext
b) for locales which are diffrent between local name and zanata server name,
for example for kexec-tools we have bn_IN but zanata server accept bn-IN,
so we need to add below line:
<locale map-from="bn_IN">bn-IN</locale>
The first running of "mvn zanata:help" will download and activate the new
version of zanata plugin for you.
I use below command to upload both pot file and translated po files:
mvn zanata:push -Dzanata.pushType=both
If you only need to upload po files, you can use:
mvn zanata:push -Dzanata.pushType=trans
You can use mvn zanata:help to lookup the detail help content of param names
The other thing to be careful is specifying the correct source and
translation directories.
They are relative path. You can also put the pom.xml and zanata.xml under toplevel directory and run:
mvn zanata:push -Dzanata.pushType=both -Dzanata.srcDir=po -Dzanata.transDir=po
--
[1] https://github.com/zanata/zanata/wiki/Zanata-Maven-Integration
[2] https://github.com/zanata/zanata/wiki/client-configuration