kexec-tools/dracut-module-setup.sh
WANG Chao 671e18f43b dracut-module-setup.sh: use perm addr of slaves to setup bonding network
Currently we use runtime mac addr to 2nd kernel to setup bonding
interface. But Bonding master will modify its slaves' mac addr and
incorrect mac addr is passed to 2nd kernel. Thus dracut in 2nd kernel
can't find expected slaves and bonding will fail.

Fix this issue by using perm address.

Tested in Fedora 19 KVM guest configured bonding with two slaves.

Signed-off-by: WANG Chao <chaowang@redhat.com>
Acked-by: Baoquan He <bhe@redhat.com>
2013-06-18 13:08:40 +08:00

420 lines
12 KiB
Bash
Executable File

#!/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() {
local _dep="base shutdown"
if sestatus 2>/dev/null | grep -q "SELinux status.*enabled"; then
_dep="$_dep selinux"
fi
if [ -d /sys/module/drm/drivers ]; then
_dep="$_dep drm"
fi
echo $_dep
return 0
}
is_ssh_dump_target()
{
grep -q "^ssh[[:blank:]].*@" /etc/kdump.conf
}
kdump_to_udev_name() {
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
kdump_setup_dns() {
_dnsfile=${initdir}/etc/cmdline.d/42dns.conf
. /etc/sysconfig/network-scripts/ifcfg-$1
[ -n "$DNS1" ] && echo "nameserver=$DNS1" > "$_dnsfile"
[ -n "$DNS2" ] && echo "nameserver=$DNS2" >> "$_dnsfile"
}
#$1: netdev name
#checking /etc/sysconfig/network-scripts/ifcfg-$1,
#if it use static ip echo it, or echo null
kdump_static_ip() {
. /etc/sysconfig/network-scripts/ifcfg-$1
if [ -n "$IPADDR" ]; then
[ -z "$NETMASK" -a -n "$PREFIX" ] && \
NETMASK=$(ipcalc -m $IPADDR/$PREFIX | cut -d'=' -f2)
echo -n "${IPADDR}::${GATEWAY}:${NETMASK}::"
fi
}
kdump_get_mac_addr() {
echo `ip addr show $1 2>/dev/null|awk '/ether/{ print $2 }'`
}
#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
}
kdump_setup_bridge() {
local _netdev=$1
for _dev in `ls /sys/class/net/$_netdev/brif/`; do
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
echo -n " ifname=$_dev:$(kdump_get_mac_addr $_dev)" >> ${initdir}/etc/cmdline.d/41bridge.conf
fi
done
echo " bridge=$_netdev:$(cd /sys/class/net/$_netdev/brif/; echo * | sed -e 's/ /,/g')" >> ${initdir}/etc/cmdline.d/41bridge.conf
}
kdump_setup_bond() {
local _netdev=$1
for _dev in `cat /sys/class/net/$_netdev/bonding/slaves`; do
echo -n " ifname=$_dev:$(kdump_get_perm_addr $_dev)" >> ${initdir}/etc/cmdline.d/42bond.conf
done
echo -n " bond=$_netdev:$(sed -e 's/ /,/g' /sys/class/net/$_netdev/bonding/slaves)" >> ${initdir}/etc/cmdline.d/42bond.conf
# Get bond options specified in ifcfg
. /etc/sysconfig/network-scripts/ifcfg-$_netdev
bondoptions="$(echo :$BONDING_OPTS | sed 's/\s\+/,/')"
echo "$bondoptions" >> ${initdir}/etc/cmdline.d/42bond.conf
}
kdump_setup_team() {
local _netdev=$1
local slaves=""
for _dev in `teamnl $_netdev ports | awk -F':' '{print $2}'`; do
echo -n " ifname=$_dev:$(kdump_get_perm_addr $_dev)" >> ${initdir}/etc/cmdline.d/44team.conf
slaves+="$_dev,"
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 > /tmp/$$-$_netdev.conf
if [ $? -ne 0 ]
then
derror "teamdctl failed."
exit 1
fi
inst_dir /etc/teamd
inst_simple /tmp/$$-$_netdev.conf "/etc/teamd/$_netdev.conf"
rm -f /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)"
echo " vlan=$_netdev:$_phydev" > ${initdir}/etc/cmdline.d/43vlan.conf
#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"
else
echo " vlan=$_netdev:$_phydev ifname=$_phydev:$_netmac" > ${initdir}/etc/cmdline.d/43vlan.conf
fi
}
# setup s390 znet cmdline
# $1: netdev name
kdump_setup_znet() {
local _options=""
. /etc/sysconfig/network-scripts/ifcfg-$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
local _static _proto
if [ "$(uname -m)" = "s390x" ]; then
kdump_setup_znet $_netdev
fi
_netmac=`ip addr show $_netdev 2>/dev/null|awk '/ether/{ print $2 }'`
_static=$(kdump_static_ip $_netdev)
if [ -n "$_static" ]; then
_proto=none
else
_proto=dhcp
fi
echo " ip=${_static}$_netdev:${_proto}" > ${initdir}/etc/cmdline.d/40ip.conf
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
echo " ifname=$_netdev:$(kdump_get_mac_addr $_netdev)" >> ${initdir}/etc/cmdline.d/40ip.conf
fi
kdump_setup_dns "$_netdev"
}
#Function:kdump_install_net
#$1: config values of net line in kdump.conf
kdump_install_net() {
local _server _netdev
local config_val="$1"
_server=`echo $config_val | sed 's/.*@//' | cut -d':' -f1`
_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
kdump_setup_netdev "${_netdev}"
#save netdev used for kdump as cmdline
echo "kdumpnic=${_netdev}" > ${initdir}/etc/cmdline.d/60kdumpnic.conf
echo "bootdev=${_netdev}" > ${initdir}/etc/cmdline.d/70bootdev.conf
}
#install kdump.conf and what user specifies in kdump.conf
kdump_install_conf() {
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#$(kdump_to_udev_name $config_val)#" /tmp/$$-kdump.conf
;;
ssh|nfs)
kdump_install_net "$config_val"
;;
kdump_pre|kdump_post|extra_bins)
dracut_install $config_val
;;
core_collector)
dracut_install "${config_val%%[[:blank:]]*}"
;;
esac
done < /etc/kdump.conf
inst "/tmp/$$-kdump.conf" "/etc/kdump.conf"
rm -f /tmp/$$-kdump.conf
}
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
}
# No ibft handling yet.
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 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 output a decent
# error message.
if ! /sbin/iscsiadm -m session -r ${path} >/dev/null ; then
derror "Unable to find iscsi record for $path"
return 1
fi
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' | awk '{ print $1; exit }')
kdump_setup_netdev $netdev
# prepare netroot= command line
# FIXME: IPV6 addresses require explicit [] around $tgt_ipaddr
# FIXME: Do we need to parse and set other parameters like protocol, port
# iscsi_iface_name, netdev_name, LUN etc.
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
}
}
install() {
kdump_install_conf
if is_ssh_dump_target; then
dracut_install /var/lib/random-seed || exit $?
fi
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 "/sbin/vmcore-dmesg" "/sbin/vmcore-dmesg"
inst_hook pre-pivot 9999 "$moddir/kdump.sh"
# 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
}