diff --git a/dracut-kdump.sh b/dracut-kdump.sh index f4456a1..6708924 100755 --- a/dracut-kdump.sh +++ b/dracut-kdump.sh @@ -478,25 +478,28 @@ save_vmcore_dmesg_ssh() get_host_ip() { - if is_nfs_dump_target || is_ssh_dump_target; then - kdumpnic=$(getarg kdumpnic=) - if [ -z "$kdumpnic" ]; then - derror "failed to get kdumpnic!" - return 1 - fi - if ! kdumphost=$(ip addr show dev "$kdumpnic" | grep '[ ]*inet'); then - derror "wrong kdumpnic: $kdumpnic" - return 1 - fi - kdumphost=$(echo "$kdumphost" | head -n 1 | awk '{print $2}') - kdumphost="${kdumphost%%/*}" - if [ -z "$kdumphost" ]; then - derror "wrong kdumpnic: $kdumpnic" - return 1 - fi - HOST_IP=$kdumphost + + if ! is_nfs_dump_target && ! is_ssh_dump_target; then + return 0 fi - return 0 + + _kdump_remote_ip=$(getarg kdump_remote_ip=) + + if [ -z "$_kdump_remote_ip" ]; then + derror "failed to get remote IP address!" + return 1 + fi + _route=$(kdump_get_ip_route "$_kdump_remote_ip") + _netdev=$(kdump_get_ip_route_field "$_route" "dev") + + if ! _kdumpip=$(ip addr show dev "$_netdev" | grep '[ ]*inet'); then + derror "Failed to get IP of $_netdev" + return 1 + fi + + _kdumpip=$(echo "$_kdumpip" | head -n 1 | awk '{print $2}') + _kdumpip="${_kdumpip%%/*}" + HOST_IP=$_kdumpip } read_kdump_confs() diff --git a/dracut-module-setup.sh b/dracut-module-setup.sh index 4c6096a..5338dbb 100755 --- a/dracut-module-setup.sh +++ b/dracut-module-setup.sh @@ -1,10 +1,29 @@ #!/bin/bash +_DRACUT_KDUMP_NM_TMP_DIR="/tmp/$$-DRACUT_KDUMP_NM" +_TMP_KDUMP_NETIFS="$_DRACUT_KDUMP_NM_TMP_DIR/kdump_netifs" +_TMP_KDUMP_NETIFS_IPv46="$_DRACUT_KDUMP_NM_TMP_DIR/kdump_netifs_ipv46" + +_save_kdump_netifs() { + echo -n " $1" >> "$_TMP_KDUMP_NETIFS" +} + +cleanup() { + rm -rf "$_DRACUT_KDUMP_NM_TMP_DIR" +} + +# shellcheck disable=SC2154 # known issue of shellcheck https://github.com/koalaman/shellcheck/issues/1299 +trap 'ret=$?; cleanup; exit $ret;' EXIT + kdump_module_init() { if ! [[ -d "${initdir}/tmp" ]]; then mkdir -p "${initdir}/tmp" fi + mkdir -p "$_DRACUT_KDUMP_NM_TMP_DIR" + echo -n > "$_TMP_KDUMP_NETIFS" + echo -n > "$_TMP_KDUMP_NETIFS_IPv46" + . /lib/kdump/kdump-lib.sh } @@ -84,39 +103,6 @@ source_ifcfg_file() { fi } -kdump_setup_dns() { - local _netdev="$1" - local _conpath="$2" - local _nameserver _dns _tmp array - local _dnsfile=${initdir}/etc/cmdline.d/42dns.conf - - _tmp=$(get_nmcli_field_by_conpath "IP4.DNS" "$_conpath") - # shellcheck disable=SC2206 - array=(${_tmp//|/ }) - if [[ ${array[*]} ]]; then - for _dns in "${array[@]}"; do - echo "nameserver=$_dns" >> "$_dnsfile" - done - else - dwarning "Failed to get DNS info via nmcli output. Now try sourcing ifcfg script" - source_ifcfg_file "$_netdev" - [[ -n $DNS1 ]] && echo "nameserver=$DNS1" > "$_dnsfile" - [[ -n $DNS2 ]] && echo "nameserver=$DNS2" >> "$_dnsfile" - fi - - while read -r content; do - _nameserver=$(echo "$content" | grep ^nameserver) - [[ -z $_nameserver ]] && continue - - _dns=$(echo "$_nameserver" | awk '{print $2}') - [[ -z $_dns ]] && continue - - if [[ ! -f $_dnsfile ]] || ! grep -q "$_dns" "$_dnsfile"; then - echo "nameserver=$_dns" >> "$_dnsfile" - fi - done < "/etc/resolv.conf" -} - # $1: repeat times # $2: string to be repeated # $3: separator @@ -227,89 +213,6 @@ cal_netmask_by_prefix() { fi } -#$1: netdev name -#$2: srcaddr -#if it use static ip echo it, or echo null -kdump_static_ip() { - local _netdev="$1" _srcaddr="$2" kdumpnic="$3" _ipv6_flag - local _netmask _gateway _ipaddr _target _nexthop _prefix - - _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 - _prefix=$(cut -d'/' -f2 <<< "$_ipaddr") - if ! _netmask=$(cal_netmask_by_prefix "$_prefix" "$_ipv6_flag"); then - derror "Failed to calculate netmask for $_ipaddr" - exit 1 - fi - 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 -r _route; do - _target=$(echo "$_route" | awk '{print $1}') - _nexthop=$(echo "$_route" | awk '{print $3}') - if [[ "x" != "x"$_ipv6_flag ]]; then - _target="[$_target]" - _nexthop="[$_nexthop]" - fi - echo "rd.route=$_target:$_nexthop:$kdumpnic" - done >> "${initdir}/etc/cmdline.d/45route-static.conf" - - kdump_handle_mulitpath_route "$_netdev" "$_srcaddr" "$kdumpnic" -} - -kdump_handle_mulitpath_route() { - local _netdev="$1" _srcaddr="$2" kdumpnic="$3" _ipv6_flag - local _target _nexthop _route _weight _max_weight _rule - - if is_ipv6_address "$_srcaddr"; then - _ipv6_flag="-6" - fi - - while IFS="" read -r _route; do - if [[ $_route =~ [[:space:]]+nexthop ]]; then - _route=${_route##[[: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]:$kdumpnic" - else - _rule="rd.route=$_target:$_nexthop:$kdumpnic" - 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" } @@ -326,121 +229,242 @@ kdump_get_perm_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 +use_ipv4_or_ipv6() { + local _netif=$1 _uuid=$2 - # 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" + if [[ -v "ipv4_usage[$_netif]" ]]; then + nmcli connection modify --temporary "$_uuid" ipv4.may-fail no &> >(ddebug) fi - echo "$_ifname" + if [[ -v "ipv6_usage[$_netif]" ]]; then + nmcli connection modify --temporary "$_uuid" ipv6.may-fail no &> >(ddebug) + fi + + if [[ -v "ipv4_usage[$_netif]" ]] && [[ ! -v "ipv6_usage[$_netif]" ]]; then + nmcli connection modify --temporary "$_uuid" ipv4.method disabled &> >(ddebug) + elif [[ ! -v "ipv4_usage[$_netif]" ]] && [[ -v "ipv6_usage[$_netif]" ]]; then + nmcli connection modify --temporary "$_uuid" ipv6.method disabled &> >(ddebug) + fi +} + +# nm-wait-online-initrd.service installed by dracut's 35-networkmanager +# module call nm-online with "-s" thus it doesn't wait for network connectivity +# to be established. Remove "-s" to avoid this undesirable effect. +wait_for_network_connectivity() { + local _nm_wait_online_service_file + + _nm_wait_online_service_file="$initdir/usr/lib/systemd/system/nm-wait-online-initrd.service" + [[ ! -f $_nm_wait_online_service_file ]] && return + + sed -i -E "/^ExecStart=\/usr\/bin\/nm-online/ { + s/ -s / /;}" "$_nm_wait_online_service_file" +} + +_clone_nmconnection() { + local _clone_output _name _unique_id + + _unique_id=$1 + _name=$(nmcli --get-values connection.id connection show "$_unique_id") + if _clone_output=$(nmcli connection clone --temporary "$_unique_id" "$_name"); then + sed -E -n "s/.* \(.*\) cloned as.*\((.*)\)\.$/\1/p" <<< "$_clone_output" + return 0 + fi + + return 1 +} + +_match_nmconnection_by_mac() { + local _unique_id _dev _mac _mac_field + + _unique_id=$1 + _dev=$2 + + _mac=$(kdump_get_perm_addr "$_dev") + if [[ $_mac != 'not set' ]]; then + _mac_field=$(nmcli --get-values connection.type connection show "$_unique_id").mac-address + nmcli connection modify --temporary "$_unique_id" "$_mac_field" "$_mac" &> >(ddebug) + nmcli connection modify --temporary "$_unique_id" "connection.interface-name" "" &> >(ddebug) + fi +} + +# Clone NM connection profiles +# +# This function makes use of "nmcli clone" to automatically convert ifcfg-* +# files to Networkmanager .nmconnection connection profiles and also modify the +# properties of .nmconnection if necessary. +clone_nmconnections() { + local _dev _cloned_nmconnection_file_path _tmp_nmconnection_file_path _old_uuid _uuid + + for _dev in "${!nmconnection_map[@]}"; do + _nmconnection_file_path=${nmconnection_map[$_dev]} + _old_uuid=$(nmcli --get-values connection.uuid connection show "$_nmconnection_file_path") + + if ! _uuid=$(_clone_nmconnection "$_old_uuid"); then + derror "Failed to clone $_old_uuid" + exit 1 + fi + + use_ipv4_or_ipv6 "$_uuid" "$_dev" + + # For physical NIC i.e. non-user created NIC, ask NM to match a + # connection profile based on MAC address + _match_nmconnection_by_mac "$_uuid" "$_dev" + + _cloned_nmconnection_file_path=$(nmcli --get-values UUID,FILENAME connection show | sed -n "s/^${_uuid}://p") + _tmp_nmconnection_file_path=$_DRACUT_KDUMP_NM_TMP_DIR/$(basename "$_nmconnection_file_path") + cp "$_cloned_nmconnection_file_path" "$_tmp_nmconnection_file_path" + # change uuid back to old value in case it's refered by other connection + # profile e.g. connection.master could be interface name of the master + # device or UUID of the master connection. + sed -i -E "s/(^uuid=).*$/\1${_old_uuid}/g" "$_tmp_nmconnection_file_path" + nmconnection_map[$_dev]=$_tmp_nmconnection_file_path + nmcli connection del "$_uuid" &> >(ddebug) + done +} + +_install_nmconnections() { + local _dev _nmconnection_file_path _nmconnection_name _initrd_nmconnection_file_path + + for _dev in "${!nmconnection_map[@]}"; do + _nmconnection_file_path=${nmconnection_map[$_dev]} + _nmconnection_name=$(basename "$_nmconnection_file_path") + _initrd_nmconnection_file_path="/etc/NetworkManager/system-connections/$_nmconnection_name" + inst "$_nmconnection_file_path" "$_initrd_nmconnection_file_path" + done +} + +kdump_install_nmconnections() { + declare -A nmconnection_map ipv4_usage ipv6_usage + local _netifs _netif + + _netifs=$1 + + for _netif in $_netifs; do + nmconnection_map[$_netif]=$_netif + done + + while IFS=: read -r _netif _nmconn; do + if [[ -v "nmconnection_map[$_netif]" ]] ; then + nmconnection_map[$_netif]="$_nmconn" + fi + done <<< "$(nmcli -t -f device,filename connection show --active)" + + while IFS=: read -r _ifname _ip_proc; do + if [[ $_ip_proc == 6 ]]; then + ipv6_usage[$_ifname]=1 + elif [[ $_ip_proc == 4 ]]; then + ipv4_usage[$_ifname]=1 + fi + done < $_TMP_KDUMP_NETIFS_IPv46 + + clone_nmconnections + _install_nmconnections +} + +kdump_install_nm_netif_allowlist() { + local _netif _except_netif _netif_allowlist _netif_allowlist_nm_conf + + for _netif in $1; do + _per_mac=$(kdump_get_perm_addr "$_netif") + if [[ "$_per_mac" != 'not set' ]]; then + _except_netif="mac:$_per_mac" + else + _except_netif="interface-name:$_netif" + fi + _netif_allowlist="${_netif_allowlist}except:${_except_netif};" + done + + _netif_allowlist_nm_conf=$_DRACUT_KDUMP_NM_TMP_DIR/netif_allowlist_nm_conf + cat <<- EOF > "$_netif_allowlist_nm_conf" + [device-others] + match-device=${_netif_allowlist} + managed=false + EOF + + inst "$_netif_allowlist_nm_conf" "/etc/NetworkManager/conf.d/10-kdump-netif.conf" +} + +_get_nic_driver() { + ethtool -i "$1" | sed -n -E "s/driver: (.*)/\1/p" +} + +kdump_install_nic_driver() { + local _netif _driver _drivers + + _drivers=() + + for _netif in $1; do + _driver=$(_get_nic_driver "$_netif") + if [[ -z $_driver ]]; then + derror "Failed to get the driver of $_netif" + exit 1 + fi + + if [[ $_driver == "802.1Q VLAN Support" ]]; then + # ethtool somehow doesn't return the driver name for a VLAN NIC + _driver=8021q + elif [[ $_driver == "team" ]]; then + # install the team mode drivers like team_mode_roundrobin.ko as well + _driver='=drivers/net/team' + fi + + _drivers+=("$_driver") + done + + instmods "${_drivers[@]}" } kdump_setup_bridge() { local _netdev=$1 - local _brif _dev _mac _kdumpdev + local _dev for _dev in "/sys/class/net/$_netdev/brif/"*; do [[ -e $_dev ]] || continue _dev=${_dev##*/} - _kdumpdev=$_dev if kdump_is_bond "$_dev"; then - (kdump_setup_bond "$_dev" "$(get_nmcli_connection_apath_by_ifname "$_dev")") || exit 1 + (kdump_setup_bond "$_dev") || exit 1 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," + _save_kdump_netifs "$_dev" done - echo " bridge=$_netdev:${_brif%,}" >> "${initdir}/etc/cmdline.d/41bridge.conf" } -# drauct takes bond=[::[:]] syntax to parse -# bond. For example: -# bond=bond0:eth0,eth1:mode=balance-rr kdump_setup_bond() { local _netdev="$1" - local _conpath="$2" - local _dev _mac _slaves _kdumpdev _bondoptions - 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," + local _dev + + for _dev in $(< "/sys/class/net/$_netdev/bonding/slaves"); do + _save_kdump_netifs "$_dev" done - echo -n " bond=$_netdev:${_slaves%,}" >> "${initdir}/etc/cmdline.d/42bond.conf" - - _bondoptions=$(get_nmcli_field_by_conpath "bond.options" "$_conpath") - - if [[ -z $_bondoptions ]]; then - dwarning "Failed to get bond configuration via nmlci output. Now try sourcing ifcfg script." - source_ifcfg_file "$_netdev" - _bondoptions="$(echo "$BONDING_OPTS" | xargs echo | tr " " ",")" - fi - - if [[ -z $_bondoptions ]]; then - derror "Get empty bond options" - exit 1 - fi - - echo ":$_bondoptions" >> "${initdir}/etc/cmdline.d/42bond.conf" } kdump_setup_team() { local _netdev=$1 - local _dev _mac _slaves _kdumpdev + local _dev 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," + _save_kdump_netifs "$_dev" done - echo " team=$_netdev:${_slaves%,}" >> "${initdir}/etc/cmdline.d/44team.conf" - #Buggy version teamdctl outputs to stderr! - #Try to use the latest version of teamd. - if ! teamdctl "$_netdev" config dump > "${initdir}/tmp/$$-$_netdev.conf"; 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 - local _netmac - local _kdumpdev + local _parent_netif - _phydev="$(awk '/^Device:/{print $2}' /proc/net/vlan/"$_netdev")" - _netmac="$(kdump_get_mac_addr "$_phydev")" + _parent_netif="$(awk '/^Device:/{print $2}' /proc/net/vlan/"$_netdev")" #Just support vlan over bond and team - if kdump_is_bridge "$_phydev"; then + if kdump_is_bridge "$_parent_netif"; then derror "Vlan over bridge is not supported!" exit 1 - elif kdump_is_bond "$_phydev"; then - (kdump_setup_bond "$_phydev" "$(get_nmcli_connection_apath_by_ifname "$_phydev")") || exit 1 - echo " vlan=$(kdump_setup_ifname "$_netdev"):$_phydev" > "${initdir}/etc/cmdline.d/43vlan.conf" - else - _kdumpdev="$(kdump_setup_ifname "$_phydev")" - echo " vlan=$(kdump_setup_ifname "$_netdev"):$_kdumpdev ifname=$_kdumpdev:$_netmac" > "${initdir}/etc/cmdline.d/43vlan.conf" + elif kdump_is_bond "$_parent_netif"; then + (kdump_setup_bond "$_parent_netif") || exit 1 + elif kdump_is_team "$_parent_netif"; then + (kdump_setup_team "$_parent_netif") || exit 1 fi + + _save_kdump_netifs "$_parent_netif" } # find online znet device @@ -471,47 +495,46 @@ find_online_znet_device() { echo -n "$ifname" } -# setup s390 znet cmdline -# $1: netdev (ifname) -# $2: nmcli connection path +_find_znet_nmconnection() { + LANG=C grep -s -E -i -l \ + "^s390-subchannels=([0-9]\.[0-9]\.[a-f0-9]+;){0,2}" \ + "$1"/*.nmconnection | LC_ALL=C sed -e "$2" +} + +# setup s390 znet +# +# Note part of code is extracted from ccw_init provided by s390utils kdump_setup_znet() { - local _netdev="$1" - local _conpath="$2" - local s390_prefix="802-3-ethernet.s390-" - local _options="" - local NETTYPE - local SUBCHANNELS + local _config_file _unique_name _NM_conf_dir + local __sed_discard_ignored_files='/\(~\|\.bak\|\.old\|\.orig\|\.rpmnew\|\.rpmorig\|\.rpmsave\)$/d' - NETTYPE=$(get_nmcli_field_by_conpath "${s390_prefix}nettype" "$_conpath") - SUBCHANNELS=$(get_nmcli_field_by_conpath "${s390_prefix}subchannels" "$_conpath") - _options=$(get_nmcli_field_by_conpath "${s390_prefix}options" "$_conpath") + _NM_conf_dir="/etc/NetworkManager/system-connections" - if [[ -z $NETTYPE || -z $SUBCHANNELS || -z $_options ]]; then - dwarning "Failed to get znet configuration via nmlci output. Now try sourcing ifcfg script." - source_ifcfg_file "$_netdev" - for i in $OPTIONS; do - _options=${_options},$i - done + _config_file=$(_find_znet_nmconnection "$initdir/$_NM_conf_dir" "$__sed_discard_ignored_files") + if [[ -n "$_config_file" ]]; then + ddebug "$_config_file has already contained the znet config" + return fi - if [[ -z $NETTYPE || -z $SUBCHANNELS || -z $_options ]]; then - exit 1 + _config_file=$(LANG=C grep -s -E -i -l \ + "^[[:space:]]*SUBCHANNELS=['\"]?([0-9]\.[0-9]\.[a-f0-9]+,){0,2}" \ + /etc/sysconfig/network-scripts/ifcfg-* \ + | LC_ALL=C sed -e "$__sed_discard_ignored_files") + + if [[ -n "$_config_file" ]]; then + LANG=c grep 'SUBCHANNELS\|NETTYPE\|OPTIONS' "$_config_file" > "$initdir/$_config_file" + else + _config_file=$(_find_znet_nmconnection "$_NM_conf_dir" "$__sed_discard_ignored_files") fi - echo "rd.znet=${NETTYPE},${SUBCHANNELS},${_options} rd.znet_ifname=$_netdev:${SUBCHANNELS}" > "${initdir}/etc/cmdline.d/30znet.conf" -} - -kdump_get_ip_route() { - local _route - if ! _route=$(/sbin/ip -o route get to "$1" 2>&1); then - derror "Bad kdump network destination: $1" - exit 1 + if [[ -n "$_config_file" ]]; then + _unique_name=$(cat /proc/sys/kernel/random/uuid) + nmcli connection clone --temporary "$_config_file" "$_unique_name" &> >(ddebug) + nmcli connection modify --temporary "$_unique_name" connection.autoconnect false + inst "/run/NetworkManager/system-connections/${_unique_name}.nmconnection" "${_NM_conf_dir}/${_unique_name}.nmconnection" + nmcli connection del "$_unique_name" &> >(ddebug) fi - echo "$_route" -} -kdump_get_ip_route_field() { - echo "$1" | sed -n -e "s/^.*\<$2\>\s\+\(\S\+\).*$/\1/p" } kdump_get_remote_ip() { @@ -531,80 +554,45 @@ kdump_get_remote_ip() { # initramfs accessing giving destination # $1: destination host kdump_install_net() { - local _destaddr _srcaddr _route _netdev _conpath kdumpnic - local _static _proto _ip_conf _ip_opts _ifname_opts - local _znet_netdev _znet_conpath + local _destaddr _srcaddr _route _netdev _ip_proc _destaddr=$(kdump_get_remote_ip "$1") _route=$(kdump_get_ip_route "$_destaddr") _srcaddr=$(kdump_get_ip_route_field "$_route" "src") _netdev=$(kdump_get_ip_route_field "$_route" "dev") - _conpath=$(get_nmcli_connection_apath_by_ifname "$_netdev") - _netmac=$(kdump_get_mac_addr "$_netdev") - kdumpnic=$(kdump_setup_ifname "$_netdev") - - _znet_netdev=$(find_online_znet_device) - if [[ -n $_znet_netdev ]]; then - _znet_conpath=$(get_nmcli_connection_apath_by_ifname "$_znet_netdev") - if ! (kdump_setup_znet "$_znet_netdev" "$_znet_conpath"); then - derror "Failed to set up znet" - exit 1 - fi - fi - - _static=$(kdump_static_ip "$_netdev" "$_srcaddr" "$kdumpnic") - if [[ -n $_static ]]; then - _proto=none - elif is_ipv6_address "$_srcaddr"; then - _proto=auto6 - else - _proto=dhcp - fi - - _ip_conf="${initdir}/etc/cmdline.d/40ip.conf" - _ip_opts=" ip=${_static}$kdumpnic:${_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" "$_conpath") || exit 1 + (kdump_setup_bond "$_netdev") || exit 1 elif kdump_is_team "$_netdev"; then kdump_setup_team "$_netdev" elif kdump_is_vlan "$_netdev"; then kdump_setup_vlan "$_netdev" - else - _ifname_opts=" ifname=$kdumpnic:$_netmac" - echo "$_ifname_opts" >> "$_ip_conf" fi - - kdump_setup_dns "$_netdev" "$_conpath" + _save_kdump_netifs "$_netdev" if [[ ! -f ${initdir}/etc/cmdline.d/50neednet.conf ]]; then # network-manager module needs this parameter echo "rd.neednet" >> "${initdir}/etc/cmdline.d/50neednet.conf" fi - # 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=$kdumpnic" > "${initdir}/etc/cmdline.d/60kdumpnic.conf" - echo "bootdev=$kdumpnic" > "${initdir}/etc/cmdline.d/70bootdev.conf" + # Stop dracut 35network-manger to calling nm-initrd-generator. + # Note this line of code can be removed after NetworkManager >= 1.35.2 + # gets released. + echo > "${initdir}/usr/libexec/nm-initrd-generator" + + if [[ ! -f ${initdir}/etc/cmdline.d/60kdumpip.conf ]]; then + echo "kdump_remote_ip=$_destaddr" > "${initdir}/etc/cmdline.d/60kdumpip.conf" fi + + if is_ipv6_address "$_srcaddr"; then + _ip_proc=6 + else + _ip_proc=4 + fi + + echo "$_netdev" "$_ip_proc" >> "$_TMP_KDUMP_NETIFS_IPv46" } # install etc/kdump/pre.d and /etc/kdump/post.d @@ -1019,7 +1007,7 @@ remove_cpu_online_rule() { } install() { - local arch + local arch _netifs kdump_module_init kdump_install_conf @@ -1078,6 +1066,16 @@ install() { inst "ip" fi + wait_for_network_connectivity + + _netifs=$(cat "$_TMP_KDUMP_NETIFS") + if [[ -n "$_netifs" ]]; then + kdump_install_nmconnections "$_netifs" + [[ -n "$(find_online_znet_device)" ]] && kdump_setup_znet + kdump_install_nm_netif_allowlist "$_netifs" + kdump_install_nic_driver "$_netifs" + fi + # 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 diff --git a/kdump-lib-initramfs.sh b/kdump-lib-initramfs.sh index 84e6bf7..74bd9ec 100755 --- a/kdump-lib-initramfs.sh +++ b/kdump-lib-initramfs.sh @@ -131,3 +131,17 @@ is_fs_dump_target() { [ -n "$(kdump_get_conf_val "ext[234]\|xfs\|btrfs\|minix")" ] } + +kdump_get_ip_route() +{ + if ! _route=$(/sbin/ip -o route get to "$1" 2>&1); then + derror "Bad kdump network destination: $1" + exit 1 + fi + echo "$_route" +} + +kdump_get_ip_route_field() +{ + echo "$1" | sed -n -e "s/^.*\<$2\>\s\+\(\S\+\).*$/\1/p" +} diff --git a/mkdumprd b/mkdumprd index 3e250e0..4a40f86 100644 --- a/mkdumprd +++ b/mkdumprd @@ -27,7 +27,7 @@ SAVE_PATH=$(get_save_path) OVERRIDE_RESETTABLE=0 extra_modules="" -dracut_args=(--add kdumpbase --quiet --hostonly --hostonly-cmdline --hostonly-i18n --hostonly-mode strict -o "plymouth resume ifcfg earlykdump") +dracut_args=(--add kdumpbase --quiet --hostonly --hostonly-cmdline --hostonly-i18n --hostonly-mode strict --hostonly-nics '' -o "plymouth resume ifcfg earlykdump") MKDUMPRD_TMPDIR="$(mktemp -d -t mkdumprd.XXXXXX)" [ -d "$MKDUMPRD_TMPDIR" ] || perror_exit "dracut: mktemp -p -d -t dracut.XXXXXX failed."