Browse Source

multinic support: Add bootdev cmdline argument

This introduces a new cmdline argument bootdev, to support the case
where multiple nics need to be up before the netroot handler is called.
Cases involved might be bonding, iscsi multipathing, bonding, ...
This argument is required to decide which interface is the primary to
use for dhcp root-path, default gw, etc.

When multiple ip= items are present on the cmdline, the ip= parser
now enforces the presence of <dev> further demands that the new argument
bootdev contains the name of the primary interface. Configurtion if of
course still delegated to netroot but in is enhance to ensure that netroot
"waits" for all required interfaces to be up.

Example: root=dhcp ip=eth0:dhcp ip=client-ip:::netmask::eth1:off bootdev=eth0

First, the ip= cmdline parser ensures that all ip items contain a <dev> then
checks the ip items and checks as well that an ip= item for the given bootdev
was found.

When the first netroot starts, probably for eth1, it checks wheter interface
configuration for all interfaces is available. If not it exits. The second
start of netroot (eth0, which was a bit delayed because of dhcp) sees that
all interfaces are present, configures them and continues.
master
Philippe Seewer 16 years ago
parent
commit
8ecd9d010a
  1. 10
      modules.d/40network/net-genrules.sh
  2. 34
      modules.d/40network/netroot
  3. 63
      modules.d/40network/parse-ip-opts.sh
  4. 24
      modules.d/40network/write-ifcfg.sh

10
modules.d/40network/net-genrules.sh

@ -15,11 +15,19 @@ fix_bootif() {
# Write udev rules # Write udev rules
{ {


# BOOTIF says everything, use only that one # BOOTIF says everything, use only that one
BOOTIF=$(getarg 'BOOTIF=') BOOTIF=$(getarg 'BOOTIF=')
if [ -n "$BOOTIF" ] ; then if [ -n "$BOOTIF" ] ; then
BOOTIF=$(fix_bootif "$BOOTIF") BOOTIF=$(fix_bootif "$BOOTIF")
printf 'ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="%s", RUN+="/sbin/ifup $env{INTERFACE}"\n' "$BOOTIF" printf 'ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="%s", RUN+="/sbin/ifup $env{INTERFACE}"\n' "$BOOTIF"

# If we have to handle multiple interfaces, handle only them.
elif [ -n "$IFACES" ] ; then
for iface in $IFACES ; do
printf 'ACTION=="add", SUBSYSTEM=="net", KERNEL=="%s", RUN+="/sbin/ifup $env{INTERFACE}"\n' "$iface"
done

# Default: We don't know the interface to use, handle all
else else
printf 'ACTION=="add", SUBSYSTEM=="net", RUN+="/sbin/ifup $env{INTERFACE}"\n' printf 'ACTION=="add", SUBSYSTEM=="net", RUN+="/sbin/ifup $env{INTERFACE}"\n'
fi fi

34
modules.d/40network/netroot

@ -30,7 +30,17 @@ fi
[ -d $NEWROOT/proc ] && exit 0 [ -d $NEWROOT/proc ] && exit 0
[ -z "$netroot" ] && exit 1 [ -z "$netroot" ] && exit 1


# Let's see if we have to wait for other interfaces
# Note: exit works just fine, since the last interface to be
# online'd should see all files
[ -e "/tmp/net.ifaces" ] && read IFACES < /tmp/net.ifaces
for iface in $IFACES ; do
[ -e /tmp/net.$iface.up ] || exit 1
done

# Set or override primary interface
netif=$1 netif=$1
[ -e "/tmp/net.bootdev" ] && read netif < /tmp/net.bootdev


# Figure out the handler for root=dhcp by recalling all netroot cmdline # Figure out the handler for root=dhcp by recalling all netroot cmdline
# handlers # handlers
@ -41,6 +51,14 @@ if [ "$netroot" = "dhcp" ] ; then
# Load dhcp options # Load dhcp options
[ -e /tmp/dhclient.$netif.dhcpopts ] && . /tmp/dhclient.$netif.dhcpopts [ -e /tmp/dhclient.$netif.dhcpopts ] && . /tmp/dhclient.$netif.dhcpopts


# If we have a specific bootdev with no dhcpoptions or empty root-path,
# we die. Otherwise we just warn
if [ -z "$new_root_path" ] ; then
[ -n "$BOOTDEV" ] && die "No dhcp root-path received for '$BOOTDEV'"
warn "No dhcp root-path received for '$BOOTDEV' trying other interfaces if available"
exit 1
fi

# Set netroot to new_root_path, so cmdline parsers don't call # Set netroot to new_root_path, so cmdline parsers don't call
netroot=$new_root_path netroot=$new_root_path


@ -63,7 +81,11 @@ if [ -z "$netroot" ] || [ ! -e "$handler" ] ; then
fi fi


# We're here, so we can assume that upping interfaces is now ok # We're here, so we can assume that upping interfaces is now ok
. /tmp/net.$netif.up [ -z "$IFACES" ] && IFACES="$netif"
for iface in $IFACES ; do
. /tmp/net.$iface.up
done

[ -e /tmp/net.$netif.gw ] && . /tmp/net.$netif.gw [ -e /tmp/net.$netif.gw ] && . /tmp/net.$netif.gw
[ -e /tmp/net.$netif.hostname ] && . /tmp/net.$netif.hostname [ -e /tmp/net.$netif.hostname ] && . /tmp/net.$netif.hostname
[ -e /tmp/net.$netif.resolv.conf ] && cp -f /tmp/net.$netif.resolv.conf /etc/resolv.conf [ -e /tmp/net.$netif.resolv.conf ] && cp -f /tmp/net.$netif.resolv.conf /etc/resolv.conf
@ -75,17 +97,21 @@ source_all netroot
# XXX other variables to export? # XXX other variables to export?
if $handler $netif $netroot $NEWROOT; then if $handler $netif $netroot $NEWROOT; then
# Network rootfs mount successful # Network rootfs mount successful
[ -f /tmp/dhclient.$netif.lease ] && cp /tmp/dhclient.$netif.lease /tmp/net.$netif.lease for iface in $IFACES ; do
[ -f /tmp/dhclient.$netif.dhcpopts ] && cp /tmp/dhclient.$netif.dhcpopts /tmp/net.$netif.dhcpopts [ -f /tmp/dhclient.$iface.lease ] && cp /tmp/dhclient.$iface.lease /tmp/net.$iface.lease
[ -f /tmp/dhclient.$iface.dhcpopts ] && cp /tmp/dhclient.$iface.dhcpopts /tmp/net.$iface.dhcpopts
done


# Save used netif for later use # Save used netif for later use
echo $netif > /tmp/net.bootdev [ ! -f /tmp/net.ifaces ] && echo $netif > /tmp/net.ifaces
else else
warn "Mounting root via '$netif' failed" warn "Mounting root via '$netif' failed"
# If we're trying with multiple interfaces, put that one down. # If we're trying with multiple interfaces, put that one down.
# ip down/flush ensures that routeing info goes away as well # ip down/flush ensures that routeing info goes away as well
if [ -z "$BOOTDEV" ] ; then
ip link set $netif down ip link set $netif down
ip addr flush dev $netif ip addr flush dev $netif
echo "#empty" > /etc/resolv.conf echo "#empty" > /etc/resolv.conf
fi
fi fi
exit 0 exit 0

63
modules.d/40network/parse-ip-opts.sh

@ -7,6 +7,10 @@
# #
# ip=<client-IP-number>:<server-id>:<gateway-IP-number>:<netmask>:<client-hostname>:<interface>:[dhcp|on|any|none|off] # ip=<client-IP-number>:<server-id>:<gateway-IP-number>:<netmask>:<client-hostname>:<interface>:[dhcp|on|any|none|off]
# #
# When supplying more than only ip= line, <interface> is mandatory and
# bootdev= must contain the name of the primary interface to use for
# routing,dns,dhcp-options,etc.
#


# Sadly there's no easy way to split ':' separated lines into variables # Sadly there's no easy way to split ':' separated lines into variables
ip_to_var() { ip_to_var() {
@ -47,6 +51,22 @@ if [ -n "$netroot" ] && [ -z "$(getarg ip=)" ] ; then
return; return;
fi fi


# Count ip= lines to decide whether we need bootdev= or not
if [ -z "$NEEDBOOTDEV" ] ; then
[ "$CMDLINE" ] || read CMDLINE < /proc/cmdline
local count=0
for p in $CMDLINE; do
[ "${p%%=*}" = "ip" ] && count=$(( $count + 1 ))
done
[ $count -gt 1 ] && NEEDBOOTDEV=1
fi

# If needed, check if bootdev= contains anything usable
if [ -n "$NEEDBOOTDEV" ] ; then
BOOTDEV=$(getarg bootdev=) || die "Please supply bootdev argument for multiple ip= lines"
[ -z "$BOOTDEV" ] && die "Bootdev argument is empty"
fi

# Check ip= lines # Check ip= lines
# XXX Would be nice if we could errorcheck ip addresses here as well # XXX Would be nice if we could errorcheck ip addresses here as well
[ "$CMDLINE" ] || read CMDLINE < /proc/cmdline [ "$CMDLINE" ] || read CMDLINE < /proc/cmdline
@ -55,6 +75,9 @@ for p in $CMDLINE; do


ip_to_var ${p#ip=} ip_to_var ${p#ip=}


# We need to have an ip= line for the specified bootdev
[ -n "$NEEDBOOTDEV" ] && [ "$dev" = "$BOOTDEV" ] && BOOTDEVOK=1

# Empty autoconf defaults to 'dhcp' # Empty autoconf defaults to 'dhcp'
if [ -z "$autoconf" ] ; then if [ -z "$autoconf" ] ; then
warn "Empty autoconf values default to dhcp" warn "Empty autoconf values default to dhcp"
@ -72,34 +95,52 @@ for p in $CMDLINE; do
die "Sorry, automatic calculation of netmask is not yet supported" die "Sorry, automatic calculation of netmask is not yet supported"
;; ;;
dhcp|on|any) \ dhcp|on|any) \
[ -n "$NEEDBOOTDEV" ] && [ -z "$dev" ] && \
die "Sorry, '$p' does not make sense for multiple interface configurations"
[ -n "$ip" ] && \ [ -n "$ip" ] && \
die "For argument '$p'\nSorry, setting client-ip does not make sense for '$autoconf'" die "For argument '$p'\nSorry, setting client-ip does not make sense for '$autoconf'"
;; ;;
*) die "For argument '$p'\nSorry, unknown value '$autoconf'";; *) die "For argument '$p'\nSorry, unknown value '$autoconf'";;
esac esac


# We don't like duplicate device configs
if [ -n "$dev" ] ; then if [ -n "$dev" ] ; then
# We don't like duplicate device configs
if [ -n "$IFACES" ] ; then if [ -n "$IFACES" ] ; then
for i in $IFACES ; do for i in $IFACES ; do
[ "$dev" = "$i" ] && die "For argument '$p'\nDuplication configurations for '$dev'" [ "$dev" = "$i" ] && die "For argument '$p'\nDuplication configurations for '$dev'"
done done
fi fi
# IFACES list for later use
IFACES="$IFACES $dev" IFACES="$IFACES $dev"
fi fi


# Do we need DHCP? (It's simpler to check for a set ip. Checks above ensure that if # Small optimization for udev rules
# ip is there, we're static) [ -z "$NEEDBOOTDEV" ] && [ -n "$dev" ] && BOOTDEV=$dev
[ -n "$NEEDDHCP" ] && [ -z "$ip" ] && DHCPOK="1"

# Do we need to check for specific options?
# Do we need srv OR dhcp? if [ -n "$NEEDDHCP" ] || [ -n "$DHCPORSERVER" ] ; then
if [ -n "$DHCPORSERVER" ] ; then # Correct device? (Empty is ok as well)
[ -n "$DHCPOK" ] && SRVOK="1" [ "$dev" = "$BOOTDEV" ] || continue
[ -n "$srv" ] && SRVOK="1" # Server-ip is there?
[ -n "$DHCPORSERVER" ] && [ -n "$srv" ] && continue
# dhcp? (It's simpler to check for a set ip. Checks above ensure that if
# ip is there, we're static
[ -z "$ip" ] && continue
# Not good!
die "Server-ip or dhcp for netboot needed, but current arguments say otherwise"
fi fi


done done


[ -n "$NEEDDHCP" ] && [ -z "$DHCPOK" ] && die "Server-ip or dhcp for netboot needed, but current arguments say otherwise" # This ensures that BOOTDEV is always first in IFACES
if [ -n "$BOOTDEV" ] && [ -n "$IFACES" ] ; then
IFACES="${IFACES%$BOOTDEV*} ${IFACES#*$BOOTDEV}"
IFACES="$BOOTDEV $IFACES"
fi

# Store BOOTDEV and IFACES for later use
[ -n "$BOOTDEV" ] && echo $BOOTDEV > /tmp/net.bootdev
[ -n "$IFACES" ] && echo $IFACES > /tmp/net.ifaces


[ -n "$DHCPORSERVER" ] && [ -z "$SRVOK" ] && die "Server-ip or dhcp for netboot needed, but current arguments say otherwise" # We need a ip= line for the configured bootdev=
[ -n "$NEEDBOOTDEV" ] && [ -z "$BOOTDEVOK" ] && die "Bootdev Argument '$BOOTDEV' not found"

24
modules.d/40network/write-ifcfg.sh

@ -1,23 +1,25 @@
#!/bin/sh #!/bin/sh


# Don't write anything if we don't know our bootdev # Don't write anything if we don't know our bootdev
[ -f /tmp/net.bootdev ] || return 1 [ -f /tmp/net.ifaces ] || return 1


read netif < /tmp/net.bootdev read IFACES < /tmp/net.ifaces


cat /sys/class/net/$netif/address > /tmp/net.$netif.hwaddr for netif in $IFACES ; do
echo "# Generated by dracut initrd" > /tmp/net.$netif.ifcfg cat /sys/class/net/$netif/address > /tmp/net.$netif.hwaddr
echo "DEVICE=$netif" >> /tmp/net.$netif.ifcfg echo "# Generated by dracut initrd" > /tmp/net.$netif.ifcfg
echo "HWADDR=$(cat /sys/class/net/$netif/address)" >> /tmp/net.$netif.ifcfg echo "DEVICE=$netif" >> /tmp/net.$netif.ifcfg
echo "TYPE=Ethernet" >> /tmp/net.$netif.ifcfg echo "HWADDR=$(cat /sys/class/net/$netif/address)" >> /tmp/net.$netif.ifcfg
echo "ONBOOT=yes" >> /tmp/net.$netif.ifcfg echo "TYPE=Ethernet" >> /tmp/net.$netif.ifcfg
if [ -f /tmp/net.$netif.lease ]; then echo "ONBOOT=yes" >> /tmp/net.$netif.ifcfg
if [ -f /tmp/net.$netif.lease ]; then
echo "BOOTPROTO=dhcp" >> /tmp/net.$netif.ifcfg echo "BOOTPROTO=dhcp" >> /tmp/net.$netif.ifcfg
else else
echo "BOOTPROTO=none" >> /tmp/net.$netif.ifcfg echo "BOOTPROTO=none" >> /tmp/net.$netif.ifcfg
# If we've booted with static ip= lines, the override file is there # If we've booted with static ip= lines, the override file is there
. /tmp/net.$netif.override . /tmp/net.$netif.override
echo "IPADDR=$ip" >> /tmp/net.$netif.ifcfg echo "IPADDR=$ip" >> /tmp/net.$netif.ifcfg
echo "NETMASK=$mask" >> /tmp/net.$netif.ifcfg echo "NETMASK=$mask" >> /tmp/net.$netif.ifcfg
[ -n "$gw" ] && echo "GATEWAY=$gw" >> /tmp/net.$netif.ifcfg [ -n "$gw" ] && echo "GATEWAY=$gw" >> /tmp/net.$netif.ifcfg
fi fi
done

Loading…
Cancel
Save