diff --git a/dracut-kdump.sh b/dracut-kdump.sh new file mode 100755 index 0000000..ca9ab43 --- /dev/null +++ b/dracut-kdump.sh @@ -0,0 +1,195 @@ +#!/bin/sh + +. /lib/dracut-lib.sh + +set -x +KDUMP_PATH="/var/crash" +CORE_COLLECTOR="makedumpfile -c --message-level 1 -d 31" +DEFAULT_ACTION="dump_rootfs" +DATEDIR=`date +%d.%m.%y-%T` +DUMP_INSTRUCTION="" +SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa" +KDUMP_SCRIPT_DIR="/kdumpscripts" +DD_BLKSIZE=512 + +export PATH=$PATH:$KDUMP_SCRIPT_DIR + +# we use manual setup nics in udev rules, +# so we need to test network is really ok +wait_for_net_ok() { + local ip=$(getarg ip) + local iface=`echo $ip|cut -d':' -f1` + return $(wait_for_route_ok $iface) +} + +do_default_action() +{ + wait_for_loginit + $DEFAULT_ACTION +} + +add_dump_code() +{ + DUMP_INSTRUCTION="$1" +} + +get_mp() +{ + local _mp + local dev mp fs opts rest + while read dev mp fs opts rest; do + if [ "$dev" = "$1" ]; then + _mp="$mp" + break + fi + done < /proc/mounts + echo "$_mp" +} + +to_dev_name() +{ + local dev="$1" + + case "$dev" in + UUID=*) + dev=`blkid -U "${dev#UUID=}"` + ;; + LABEL=*) + dev=`blkid -L "${dev#LABEL=}"` + ;; + esac + echo $dev +} + +dump_localfs() +{ + local _dev=`to_dev_name $1` + local _mp=`get_mp $_dev` + if [ "$_mp" = "$NEWROOT/" ] || [ "$_mp" = "$NEWROOT" ] + then + mount -o remount,rw $_mp || return 1 + fi + mkdir -p $_mp/$KDUMP_PATH/$DATEDIR + $CORE_COLLECTOR /proc/vmcore $_mp/$KDUMP_PATH/$DATEDIR/vmcore || return 1 + umount $_mp || return 1 + return 0 +} + +dump_raw() +{ + [ -b "$1" ] || return 1 + + echo "Saving to raw disk $1" + if $(echo -n $CORE_COLLECTOR|grep -q makedumpfile); then + _src_size_mb="Unknown" + else + _src_size=`ls -l /proc/vmcore | cut -d' ' -f5` + _src_size_mb=$(($_src_size / 1048576)) + fi + + monitor_dd_progress $_src_size_mb & + + CORE_COLLECTOR=`echo $CORE_COLLECTOR | sed -e's/\(^makedumpfile\)\(.*$\)/\1 -F \2/'` + $CORE_COLLECTOR /proc/vmcore | dd of=$1 bs=$DD_BLKSIZE >> /tmp/dd_progress_file 2>&1 || return 1 + return 0 +} + +dump_rootfs() +{ + mount -o remount,rw $NEWROOT/ || return 1 + mkdir -p $NEWROOT/$KDUMP_PATH/$DATEDIR + $CORE_COLLECTOR /proc/vmcore $NEWROOT/$KDUMP_PATH/$DATEDIR/vmcore || return 1 + sync + reboot -f + return 0 +} + +dump_nfs() +{ + mount -o remount,rw $NEWROOT/ || return 1 + [ -d $NEWROOT/mnt ] || mkdir -p $NEWROOT/mnt + mount -o nolock -o tcp -t nfs $1 $NEWROOT/mnt/ || return 1 + mkdir -p $NEWROOT/mnt/$KDUMP_PATH/$DATEDIR || return 1 + $CORE_COLLECTOR /proc/vmcore $NEWROOT/mnt/$KDUMP_PATH/$DATEDIR/vmcore || return 1 + umount $NEWROOT/mnt/ || return 1 + return 0 +} + +dump_ssh() +{ + ssh -q -i $1 -o BatchMode=yes -o StrictHostKeyChecking=yes $2 mkdir -p $KDUMP_PATH/$DATEDIR || return 1 + scp -q -i $1 -o BatchMode=yes -o StrictHostKeyChecking=yes /proc/vmcore "$2:$KDUMP_PATH/$DATEDIR" || return 1 + return 0 +} + +read_kdump_conf() +{ + local conf_file="/etc/kdump.conf" + if [ -f "$conf_file" ]; then + # first get the necessary variables + while read config_opt config_val; + do + 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 + ;; + default) + case $config_val in + shell) + DEFAULT_ACTION="sh -i -l" + ;; + reboot) + DEFAULT_ACTION="reboot -f" + ;; + halt) + DEFAULT_ACTION="halt -f" + ;; + poweroff) + DEFAULT_ACTION="poweroff -f" + ;; + esac + ;; + esac + done < $conf_file + + # rescan for add code for dump target + while read config_opt config_val; + do + case "$config_opt" in + ext[234]|xfs|btrfs|minix) + add_dump_code "dump_localfs $config_val || do_default_action" + ;; + raw) + add_dump_code "dump_raw $config_val || do_default_action" + ;; + net) + wait_for_net_ok + if [[ "$config_val" =~ "@" ]]; then + add_dump_code "dump_ssh $SSH_KEY_LOCATION $config_val || do_default_action" + else + add_dump_code "dump_nfs $config_val || do_default_action" + fi + ;; + esac + done < $conf_file + fi +} + +read_kdump_conf + +if [ -n "$DUMP_INSTRUCTION" ] +then + eval "$DUMP_INSTRUCTION && reboot -f" +else + dump_rootfs +fi + + diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh new file mode 100755 index 0000000..03e3894 --- /dev/null +++ b/dracut-module-setup.sh @@ -0,0 +1,99 @@ +#!/bin/bash + +. $dracutfunctions + +check() { + [[ $debug ]] && set -x + #kdumpctl sets this explicitly + if [ -z "$IN_KDUMP" ] || [ ! -f /etc/kdump.conf ] + then + return 1 + fi + return 0 +} + +depends() { + echo "base shutdown" + return 0 +} + +to_udev_name() { + local dev="$1" + + case "$dev" in + UUID=*) + dev=`blkid -U "${dev#UUID=}"` + ;; + LABEL=*) + dev=`blkid -L "${dev#LABEL=}"` + ;; + esac + echo ${dev#/dev/} +} + +is_bridge() { + [ -d /sys/class/net/"$1"/bridge ] +} + +is_bond() { + [ -d /sys/class/net/"$1"/bonding ] +} + +install() { + local _server + local _netdev + + sed -ne '/^#/!p' /etc/kdump.conf > /tmp/$$-kdump.conf + while read config_opt config_val; + do + case "$config_opt" in + ext[234]|xfs|btrfs|minix|raw) + sed -i -e "s#$config_val#/dev/$(to_udev_name $config_val)#" /tmp/$$-kdump.conf + ;; + net) + if strstr "$config_val" "@"; then + _server=`echo $config_val | sed 's/.*@//' | cut -d':' -f1` + else + _server=$(echo $config_val | sed -e 's#\(.*\):.*#\1#') + fi + + _need_dns=`echo $_server|grep "[a-zA-Z]"` + [ -n "$_need_dns" ] && _server=`getent hosts $_server|cut -d' ' -f1` + + _netdev=`/sbin/ip 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 + if [ -n "`echo $_netdev | grep via`" ] + then + # we are going to a different subnet + _netdev=`echo $_netdev|awk '{print $5;}'|head -n 1` + else + # we are on the same subnet + _netdev=`echo $_netdev|awk '{print $3}'|head -n 1` + fi + _netmac=`ip addr show $_netdev 2>/dev/null|awk '/ether/{ print $2 }'` + echo " ip=$_netdev:dhcp ifname=$_netdev:$_netmac rd.neednet=1" > ${initdir}/etc/cmdline.d/40ip.conf + if is_bridge "$_netdev"; then + echo " bridge=$_netdev:$(cd /sys/class/net/$_netdev/brif/; echo *)" > ${initdir}/etc/cmdline.d/41bridge.conf + elif is_bond "$_netdev"; then + echo " bond=$_netdev:\"$(cat /sys/class/net/$_netdev/bonding/slaves)\"" > ${initdir}/etc/cmdline.d/42bond.conf + #TODO + #echo "bondoptions=\"$bondoptions\"" >> /tmp/$$-bond + else + : + fi + ;; + esac + done < /etc/kdump.conf + + 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 "/sbin/makedumpfile" "/sbin/makedumpfile" + inst "/tmp/$$-kdump.conf" "/etc/kdump.conf" + inst_hook pre-pivot 9999 "$moddir/kdump.sh" +} diff --git a/dracut-monitor_dd_progress b/dracut-monitor_dd_progress new file mode 100644 index 0000000..01a1567 --- /dev/null +++ b/dracut-monitor_dd_progress @@ -0,0 +1,26 @@ +#!/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"` + CURRENT_MB=$(($CURRENT_SIZE / 1048576)) + echo -n -e "Copied $CURRENT_MB MB / $SRC_FILE_MB MB\r" +done + +rm -f /tmp/dd_progress_file diff --git a/kdump_dracut_modules/99kdumpbase/kdump.sh b/kdump_dracut_modules/99kdumpbase/kdump.sh deleted file mode 100755 index ca9ab43..0000000 --- a/kdump_dracut_modules/99kdumpbase/kdump.sh +++ /dev/null @@ -1,195 +0,0 @@ -#!/bin/sh - -. /lib/dracut-lib.sh - -set -x -KDUMP_PATH="/var/crash" -CORE_COLLECTOR="makedumpfile -c --message-level 1 -d 31" -DEFAULT_ACTION="dump_rootfs" -DATEDIR=`date +%d.%m.%y-%T` -DUMP_INSTRUCTION="" -SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa" -KDUMP_SCRIPT_DIR="/kdumpscripts" -DD_BLKSIZE=512 - -export PATH=$PATH:$KDUMP_SCRIPT_DIR - -# we use manual setup nics in udev rules, -# so we need to test network is really ok -wait_for_net_ok() { - local ip=$(getarg ip) - local iface=`echo $ip|cut -d':' -f1` - return $(wait_for_route_ok $iface) -} - -do_default_action() -{ - wait_for_loginit - $DEFAULT_ACTION -} - -add_dump_code() -{ - DUMP_INSTRUCTION="$1" -} - -get_mp() -{ - local _mp - local dev mp fs opts rest - while read dev mp fs opts rest; do - if [ "$dev" = "$1" ]; then - _mp="$mp" - break - fi - done < /proc/mounts - echo "$_mp" -} - -to_dev_name() -{ - local dev="$1" - - case "$dev" in - UUID=*) - dev=`blkid -U "${dev#UUID=}"` - ;; - LABEL=*) - dev=`blkid -L "${dev#LABEL=}"` - ;; - esac - echo $dev -} - -dump_localfs() -{ - local _dev=`to_dev_name $1` - local _mp=`get_mp $_dev` - if [ "$_mp" = "$NEWROOT/" ] || [ "$_mp" = "$NEWROOT" ] - then - mount -o remount,rw $_mp || return 1 - fi - mkdir -p $_mp/$KDUMP_PATH/$DATEDIR - $CORE_COLLECTOR /proc/vmcore $_mp/$KDUMP_PATH/$DATEDIR/vmcore || return 1 - umount $_mp || return 1 - return 0 -} - -dump_raw() -{ - [ -b "$1" ] || return 1 - - echo "Saving to raw disk $1" - if $(echo -n $CORE_COLLECTOR|grep -q makedumpfile); then - _src_size_mb="Unknown" - else - _src_size=`ls -l /proc/vmcore | cut -d' ' -f5` - _src_size_mb=$(($_src_size / 1048576)) - fi - - monitor_dd_progress $_src_size_mb & - - CORE_COLLECTOR=`echo $CORE_COLLECTOR | sed -e's/\(^makedumpfile\)\(.*$\)/\1 -F \2/'` - $CORE_COLLECTOR /proc/vmcore | dd of=$1 bs=$DD_BLKSIZE >> /tmp/dd_progress_file 2>&1 || return 1 - return 0 -} - -dump_rootfs() -{ - mount -o remount,rw $NEWROOT/ || return 1 - mkdir -p $NEWROOT/$KDUMP_PATH/$DATEDIR - $CORE_COLLECTOR /proc/vmcore $NEWROOT/$KDUMP_PATH/$DATEDIR/vmcore || return 1 - sync - reboot -f - return 0 -} - -dump_nfs() -{ - mount -o remount,rw $NEWROOT/ || return 1 - [ -d $NEWROOT/mnt ] || mkdir -p $NEWROOT/mnt - mount -o nolock -o tcp -t nfs $1 $NEWROOT/mnt/ || return 1 - mkdir -p $NEWROOT/mnt/$KDUMP_PATH/$DATEDIR || return 1 - $CORE_COLLECTOR /proc/vmcore $NEWROOT/mnt/$KDUMP_PATH/$DATEDIR/vmcore || return 1 - umount $NEWROOT/mnt/ || return 1 - return 0 -} - -dump_ssh() -{ - ssh -q -i $1 -o BatchMode=yes -o StrictHostKeyChecking=yes $2 mkdir -p $KDUMP_PATH/$DATEDIR || return 1 - scp -q -i $1 -o BatchMode=yes -o StrictHostKeyChecking=yes /proc/vmcore "$2:$KDUMP_PATH/$DATEDIR" || return 1 - return 0 -} - -read_kdump_conf() -{ - local conf_file="/etc/kdump.conf" - if [ -f "$conf_file" ]; then - # first get the necessary variables - while read config_opt config_val; - do - 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 - ;; - default) - case $config_val in - shell) - DEFAULT_ACTION="sh -i -l" - ;; - reboot) - DEFAULT_ACTION="reboot -f" - ;; - halt) - DEFAULT_ACTION="halt -f" - ;; - poweroff) - DEFAULT_ACTION="poweroff -f" - ;; - esac - ;; - esac - done < $conf_file - - # rescan for add code for dump target - while read config_opt config_val; - do - case "$config_opt" in - ext[234]|xfs|btrfs|minix) - add_dump_code "dump_localfs $config_val || do_default_action" - ;; - raw) - add_dump_code "dump_raw $config_val || do_default_action" - ;; - net) - wait_for_net_ok - if [[ "$config_val" =~ "@" ]]; then - add_dump_code "dump_ssh $SSH_KEY_LOCATION $config_val || do_default_action" - else - add_dump_code "dump_nfs $config_val || do_default_action" - fi - ;; - esac - done < $conf_file - fi -} - -read_kdump_conf - -if [ -n "$DUMP_INSTRUCTION" ] -then - eval "$DUMP_INSTRUCTION && reboot -f" -else - dump_rootfs -fi - - diff --git a/kdump_dracut_modules/99kdumpbase/module-setup.sh b/kdump_dracut_modules/99kdumpbase/module-setup.sh deleted file mode 100755 index 03e3894..0000000 --- a/kdump_dracut_modules/99kdumpbase/module-setup.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/bin/bash - -. $dracutfunctions - -check() { - [[ $debug ]] && set -x - #kdumpctl sets this explicitly - if [ -z "$IN_KDUMP" ] || [ ! -f /etc/kdump.conf ] - then - return 1 - fi - return 0 -} - -depends() { - echo "base shutdown" - return 0 -} - -to_udev_name() { - local dev="$1" - - case "$dev" in - UUID=*) - dev=`blkid -U "${dev#UUID=}"` - ;; - LABEL=*) - dev=`blkid -L "${dev#LABEL=}"` - ;; - esac - echo ${dev#/dev/} -} - -is_bridge() { - [ -d /sys/class/net/"$1"/bridge ] -} - -is_bond() { - [ -d /sys/class/net/"$1"/bonding ] -} - -install() { - local _server - local _netdev - - sed -ne '/^#/!p' /etc/kdump.conf > /tmp/$$-kdump.conf - while read config_opt config_val; - do - case "$config_opt" in - ext[234]|xfs|btrfs|minix|raw) - sed -i -e "s#$config_val#/dev/$(to_udev_name $config_val)#" /tmp/$$-kdump.conf - ;; - net) - if strstr "$config_val" "@"; then - _server=`echo $config_val | sed 's/.*@//' | cut -d':' -f1` - else - _server=$(echo $config_val | sed -e 's#\(.*\):.*#\1#') - fi - - _need_dns=`echo $_server|grep "[a-zA-Z]"` - [ -n "$_need_dns" ] && _server=`getent hosts $_server|cut -d' ' -f1` - - _netdev=`/sbin/ip 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 - if [ -n "`echo $_netdev | grep via`" ] - then - # we are going to a different subnet - _netdev=`echo $_netdev|awk '{print $5;}'|head -n 1` - else - # we are on the same subnet - _netdev=`echo $_netdev|awk '{print $3}'|head -n 1` - fi - _netmac=`ip addr show $_netdev 2>/dev/null|awk '/ether/{ print $2 }'` - echo " ip=$_netdev:dhcp ifname=$_netdev:$_netmac rd.neednet=1" > ${initdir}/etc/cmdline.d/40ip.conf - if is_bridge "$_netdev"; then - echo " bridge=$_netdev:$(cd /sys/class/net/$_netdev/brif/; echo *)" > ${initdir}/etc/cmdline.d/41bridge.conf - elif is_bond "$_netdev"; then - echo " bond=$_netdev:\"$(cat /sys/class/net/$_netdev/bonding/slaves)\"" > ${initdir}/etc/cmdline.d/42bond.conf - #TODO - #echo "bondoptions=\"$bondoptions\"" >> /tmp/$$-bond - else - : - fi - ;; - esac - done < /etc/kdump.conf - - 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 "/sbin/makedumpfile" "/sbin/makedumpfile" - inst "/tmp/$$-kdump.conf" "/etc/kdump.conf" - inst_hook pre-pivot 9999 "$moddir/kdump.sh" -} diff --git a/kdump_dracut_modules/99kdumpbase/monitor_dd_progress b/kdump_dracut_modules/99kdumpbase/monitor_dd_progress deleted file mode 100644 index 01a1567..0000000 --- a/kdump_dracut_modules/99kdumpbase/monitor_dd_progress +++ /dev/null @@ -1,26 +0,0 @@ -#!/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"` - CURRENT_MB=$(($CURRENT_SIZE / 1048576)) - echo -n -e "Copied $CURRENT_MB MB / $SRC_FILE_MB MB\r" -done - -rm -f /tmp/dd_progress_file diff --git a/kexec-tools.spec b/kexec-tools.spec index d89d2b9..bfdc537 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -26,7 +26,9 @@ Source16: kdump.service # These are sources for mkdumpramfs # Which is currently in development ####################################### -Source100: dracut-files.tbz2 +Source100: dracut-kdump.sh +Source101: dracut-module-setup.sh +Source102: dracut-monitor_dd_progress Requires(post): systemd-units Requires(preun): systemd-units @@ -155,12 +157,16 @@ install -m 644 makedumpfile-1.4.2/makedumpfile.8.gz $RPM_BUILD_ROOT/%{_mandir}/m make -C kexec-tools-po install DESTDIR=$RPM_BUILD_ROOT %find_lang %{name} +%define remove_dracut_prefix() %(echo -n %1|sed 's/.*dracut-//g') -# untar the dracut package -mkdir -p -m755 $RPM_BUILD_ROOT/etc/kdump-adv-conf -tar -C $RPM_BUILD_ROOT/etc/kdump-adv-conf -jxvf %{SOURCE100} -chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/module-setup.sh -chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/kdump.sh +# deal with dracut modules +mkdir -p -m755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase +cp %{SOURCE100} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE100}} +cp %{SOURCE101} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE101}} +cp %{SOURCE102} $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE102}} + +chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE100}} +chmod 755 $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/99kdumpbase/%{remove_dracut_prefix %{SOURCE101}} %define dracutlibdir %{_prefix}/lib/dracut diff --git a/sources b/sources index 74e4225..5188ce0 100644 --- a/sources +++ b/sources @@ -1,4 +1,3 @@ 3e802d638dce0080b910f15908c04a24 kexec-tools-po.tar.gz b3ced2097ce3981abba38ceedc84f939 kexec-tools-2.0.3.tar.bz2 a98917a8dab5e590549bff9fe7b3a5c2 makedumpfile-1.4.2.tar.gz -14d710b19f1fa254dae77ec184b6a7c1 dracut-files.tbz2