a56a5e
From 4c88c2859e3f974b2dc3c7726409c83076df8985 Mon Sep 17 00:00:00 2001
a56a5e
From: Harald Hoyer <harald@redhat.com>
a56a5e
Date: Tue, 13 Jan 2015 15:06:48 +0100
a56a5e
Subject: [PATCH] network: enhance team support
a56a5e
a56a5e
Install ifcfg-* files with team configuration in the initramfs.
a56a5e
a56a5e
Improve the slave configuration of the team interface, by looking up
a56a5e
ifcfg files in the initramfs.
a56a5e
a56a5e
Create a default loadbalance team config, if none present in the
a56a5e
initramfs.
a56a5e
---
49e6a8
 modules.d/40network/ifup.sh         | 38 ++++++++++++++++++++++-------
49e6a8
 modules.d/40network/module-setup.sh | 37 ++++++++++++++++++++++++++++
49e6a8
 modules.d/40network/net-genrules.sh |  9 ++++---
49e6a8
 modules.d/40network/net-lib.sh      | 18 ++++++++++++++
49e6a8
 modules.d/40network/parse-team.sh   | 30 +++++++++++++++--------
49e6a8
 modules.d/45ifcfg/write-ifcfg.sh    | 10 +++++++-
a56a5e
 6 files changed, 119 insertions(+), 23 deletions(-)
a56a5e
a56a5e
diff --git a/modules.d/40network/ifup.sh b/modules.d/40network/ifup.sh
1755ca
index 8749c4c2..7836a6b3 100755
a56a5e
--- a/modules.d/40network/ifup.sh
a56a5e
+++ b/modules.d/40network/ifup.sh
a56a5e
@@ -34,14 +34,16 @@ for i in /tmp/bond.*.info; do
a56a5e
     done
a56a5e
 done
a56a5e
 
a56a5e
-if [ -e /tmp/team.info ]; then
a56a5e
-    . /tmp/team.info
a56a5e
+for i in /tmp/team.*.info; do
a56a5e
+    [ -e "$i" ] || continue
a56a5e
+    unset teamslaves
a56a5e
+    unset teammaster
a56a5e
     for slave in $teamslaves ; do
a56a5e
         if [ "$netif" = "$slave" ] ; then
a56a5e
             netif=$teammaster
a56a5e
         fi
a56a5e
     done
a56a5e
-fi
a56a5e
+done
a56a5e
 
a56a5e
 if [ -e /tmp/vlan.info ]; then
a56a5e
     . /tmp/vlan.info
a56a5e
@@ -205,26 +207,44 @@ if [ -e /tmp/bond.${netif}.info ]; then
a56a5e
     fi
a56a5e
 fi
a56a5e
 
a56a5e
-if [ -e /tmp/team.info ]; then
a56a5e
-    . /tmp/team.info
a56a5e
+if [ -e /tmp/team.${netif}.info ]; then
a56a5e
+    . /tmp/team.${netif}.info
a56a5e
     if [ "$netif" = "$teammaster" ] && [ ! -e /tmp/net.$teammaster.up ] ; then
a56a5e
         # We shall only bring up those _can_ come up
a56a5e
         # in case of some slave is gone in active-backup mode
a56a5e
         working_slaves=""
a56a5e
         for slave in $teamslaves ; do
a56a5e
-            ip link set $slave up 2>/dev/null
a56a5e
+            teamdctl ${teammaster} port present ${slave} 2>/dev/null \
a56a5e
+                     && continue
a56a5e
+            ip link set dev $slave up 2>/dev/null
a56a5e
             if wait_for_if_up $slave; then
a56a5e
                 working_slaves+="$slave "
a56a5e
             fi
a56a5e
         done
a56a5e
         # Do not add slaves now
a56a5e
-        teamd -d -U -n -t $teammaster -f /etc/teamd/$teammaster.conf
a56a5e
+        teamd -d -U -n -t $teammaster -f /etc/teamd/${teammaster}.conf
a56a5e
         for slave in $working_slaves; do
a56a5e
             # team requires the slaves to be down before joining team
a56a5e
-            ip link set $slave down
a56a5e
+            ip link set dev $slave down
a56a5e
+            (
a56a5e
+                unset TEAM_PORT_CONFIG
a56a5e
+                _hwaddr=$(cat /sys/class/net/$slave/address)
a56a5e
+                _subchannels=$(iface_get_subchannels "$slave")
a56a5e
+                if [ -n "$_hwaddr" ] && [ -e "/etc/sysconfig/network-scripts/mac-${_hwaddr}.conf" ]; then
a56a5e
+                    . "/etc/sysconfig/network-scripts/mac-${_hwaddr}.conf"
a56a5e
+                elif [ -n "$_subchannels" ] && [ -e "/etc/sysconfig/network-scripts/ccw-${_subchannels}.conf" ]; then
a56a5e
+                    . "/etc/sysconfig/network-scripts/ccw-${_subchannels}.conf"
a56a5e
+                elif [ -e "/etc/sysconfig/network-scripts/ifcfg-${slave}" ]; then
a56a5e
+                    . "/etc/sysconfig/network-scripts/ifcfg-${slave}"
a56a5e
+                fi
a56a5e
+
a56a5e
+                if [ -n "${TEAM_PORT_CONFIG}" ]; then
a56a5e
+                    /usr/bin/teamdctl ${teammaster} port config update ${slave} "${TEAM_PORT_CONFIG}"
a56a5e
+                fi
a56a5e
+            )
a56a5e
             teamdctl $teammaster port add $slave
a56a5e
         done
a56a5e
-        ip link set $teammaster up
a56a5e
+        ip link set dev $teammaster up
a56a5e
     fi
a56a5e
 fi
a56a5e
 
a56a5e
diff --git a/modules.d/40network/module-setup.sh b/modules.d/40network/module-setup.sh
1755ca
index a5e796f4..a52e881b 100755
a56a5e
--- a/modules.d/40network/module-setup.sh
a56a5e
+++ b/modules.d/40network/module-setup.sh
a56a5e
@@ -95,6 +95,43 @@ install() {
a56a5e
     inst_hook cmdline 99 "$moddir/parse-ifname.sh"
a56a5e
     inst_hook cleanup 10 "$moddir/kill-dhclient.sh"
a56a5e
 
a56a5e
+    # install all config files for teaming
a56a5e
+    unset TEAM_MASTER
a56a5e
+    unset TEAM_CONFIG
a56a5e
+    unset TEAM_PORT_CONFIG
a56a5e
+    unset HWADDR
a56a5e
+    unset SUBCHANNELS
a56a5e
+    for i in /etc/sysconfig/network-scripts/ifcfg-*; do
a56a5e
+        [ -e "$i" ] || continue
a56a5e
+        case "$i" in
a56a5e
+            *~ | *.bak | *.orig | *.rpmnew | *.rpmorig | *.rpmsave)
a56a5e
+                continue
a56a5e
+                ;;
a56a5e
+        esac
a56a5e
+        (
a56a5e
+            . "$i"
a56a5e
+            if ! [ "${ONBOOT}" = "no" -o "${ONBOOT}" = "NO" ] \
a56a5e
+                    && [ -n "${TEAM_MASTER}${TEAM_CONFIG}${TEAM_PORT_CONFIG}" ]; then
a56a5e
+                if [ -n "$TEAM_CONFIG" ] && [ -n "$DEVICE" ]; then
a56a5e
+                    mkdir -p $initdir/etc/teamd
a56a5e
+                    printf -- "%s" "$TEAM_CONFIG" > "$initdir/etc/teamd/${DEVICE}.conf"
a56a5e
+                elif [ -n "$TEAM_PORT_CONFIG" ]; then
a56a5e
+                    inst_simple "$i"
a56a5e
+
a56a5e
+                    HWADDR="$(echo $HWADDR | sed 'y/ABCDEF/abcdef/')"
a56a5e
+                    if [ -n "$HWADDR" ]; then
a56a5e
+                        ln_r "$i" "/etc/sysconfig/network-scripts/mac-${HWADDR}.conf"
a56a5e
+                    fi
a56a5e
+
a56a5e
+                    SUBCHANNELS="$(echo $SUBCHANNELS | sed 'y/ABCDEF/abcdef/')"
a56a5e
+                    if [ -n "$SUBCHANNELS" ]; then
a56a5e
+                        ln_r "$i" "/etc/sysconfig/network-scripts/ccw-${SUBCHANNELS}.conf"
a56a5e
+                    fi
a56a5e
+                fi
a56a5e
+            fi
a56a5e
+        )
a56a5e
+    done
a56a5e
+
a56a5e
     _arch=$(uname -m)
a56a5e
 
a56a5e
     inst_libdir_file {"tls/$_arch/",tls/,"$_arch/",}"libnss_dns.so.*" \
a56a5e
diff --git a/modules.d/40network/net-genrules.sh b/modules.d/40network/net-genrules.sh
1755ca
index a43e3df1..3664984f 100755
a56a5e
--- a/modules.d/40network/net-genrules.sh
a56a5e
+++ b/modules.d/40network/net-genrules.sh
a56a5e
@@ -31,11 +31,14 @@ command -v fix_bootif >/dev/null || . /lib/net-lib.sh
a56a5e
         MASTER_IFACES="$MASTER_IFACES ${bondname}"
a56a5e
     done
a56a5e
 
a56a5e
-    if [ -e /tmp/team.info ]; then
a56a5e
-        . /tmp/team.info
a56a5e
+    for i in /tmp/team.*.info; do
a56a5e
+        [ -e "$i" ] || continue
a56a5e
+        unset teamslaves
a56a5e
+        unset teammaster
a56a5e
+        . "$i"
a56a5e
         IFACES="$IFACES ${teamslaves}"
a56a5e
         MASTER_IFACES="$MASTER_IFACES ${teammaster}"
a56a5e
-    fi
a56a5e
+    done
a56a5e
 
a56a5e
     if [ -e /tmp/vlan.info ]; then
a56a5e
         . /tmp/vlan.info
a56a5e
diff --git a/modules.d/40network/net-lib.sh b/modules.d/40network/net-lib.sh
1755ca
index 9c6b9dae..82827b6d 100755
a56a5e
--- a/modules.d/40network/net-lib.sh
a56a5e
+++ b/modules.d/40network/net-lib.sh
a56a5e
@@ -643,3 +643,21 @@ is_kernel_ethernet_name() {
a56a5e
     esac
a56a5e
 
a56a5e
 }
a56a5e
+
a56a5e
+iface_get_subchannels() {
a56a5e
+    local _netif
a56a5e
+    local _subchannels
a56a5e
+
a56a5e
+    _netif="$1"
a56a5e
+
a56a5e
+    _subchannels=$({
a56a5e
+        for i in /sys/class/net/$_netif/device/cdev[0-9]*; do
a56a5e
+            [ -e $i ] || continue
a56a5e
+            channel=$(readlink -f $i)
a56a5e
+            printf -- "%s" "${channel##*/},"
a56a5e
+        done
a56a5e
+    })
a56a5e
+    [ -n "$_subchannels" ] || return 1
a56a5e
+
a56a5e
+    printf -- "%s" ${_subchannels%,}
a56a5e
+}
a56a5e
diff --git a/modules.d/40network/parse-team.sh b/modules.d/40network/parse-team.sh
1755ca
index 318c0e1e..a836d688 100755
a56a5e
--- a/modules.d/40network/parse-team.sh
a56a5e
+++ b/modules.d/40network/parse-team.sh
a56a5e
@@ -24,21 +24,31 @@ parseteam() {
a56a5e
 
a56a5e
     unset teammaster teamslaves
a56a5e
     case $# in
a56a5e
-    2)  teammaster=$1; teamslaves=$(str_replace "$2" "," " ") ;;
a56a5e
-    *)  die "team= requires two parameters" ;;
a56a5e
+        2)  teammaster=$1; teamslaves=$(str_replace "$2" "," " ") ;;
a56a5e
+        *)  warn "team= requires two parameters"; return 1;;
a56a5e
     esac
a56a5e
+    return 0
a56a5e
 }
a56a5e
 
a56a5e
 unset teammaster teamslaves
a56a5e
 
a56a5e
 if getarg team>/dev/null; then
a56a5e
     # Read team= parameters if they exist
a56a5e
-    team="$(getarg team=)"
a56a5e
-    if [ ! "$team" = "team" ]; then
a56a5e
-        parseteam "$(getarg team=)"
a56a5e
-    fi
a56a5e
-
a56a5e
-    echo "teammaster=$teammaster" > /tmp/team.info
a56a5e
-    echo "teamslaves=\"$teamslaves\"" >> /tmp/team.info
a56a5e
-    return
a56a5e
+    for team in $(getargs team); do
a56a5e
+        [ "$team" = "team" ] && continue
a56a5e
+
a56a5e
+        unset teammaster
a56a5e
+        unset teamslaves
a56a5e
+
a56a5e
+        parseteam "$team" || continue
a56a5e
+
a56a5e
+        echo "teammaster=$teammaster" > /tmp/team.${teammaster}.info
a56a5e
+        echo "teamslaves=\"$teamslaves\"" >> /tmp/team.${teammaster}.info
a56a5e
+
a56a5e
+        if ! [ -e /etc/teamd/${teammaster}.conf ]; then
a56a5e
+            warn "Team master $teammaster specified, but no /etc/teamd/$teammaster.conf present. Using activebackup."
a56a5e
+            mkdir -p /etc/teamd
a56a5e
+            printf -- "%s" '{"runner": {"name": "activebackup"}, "link_watch": {"name": "ethtool"}}' > "/etc/teamd/${teammaster}.conf"
a56a5e
+        fi
a56a5e
+    done
a56a5e
 fi
a56a5e
diff --git a/modules.d/45ifcfg/write-ifcfg.sh b/modules.d/45ifcfg/write-ifcfg.sh
1755ca
index a1bae72f..b2462dae 100755
a56a5e
--- a/modules.d/45ifcfg/write-ifcfg.sh
a56a5e
+++ b/modules.d/45ifcfg/write-ifcfg.sh
a56a5e
@@ -128,6 +128,7 @@ for netup in /tmp/net.*.did-setup ; do
a56a5e
     [ -e /tmp/ifcfg/ifcfg-$netif ] && continue
a56a5e
     unset bridge
a56a5e
     unset bond
a56a5e
+    unset team
a56a5e
     unset bondslaves
a56a5e
     unset bondname
a56a5e
     unset bondoptions
a56a5e
@@ -140,10 +141,13 @@ for netup in /tmp/net.*.did-setup ; do
a56a5e
     unset slave
a56a5e
     unset ethname
a56a5e
     [ -e /tmp/bond.${netif}.info ] && . /tmp/bond.${netif}.info
a56a5e
+    [ -e /tmp/team.${netif}.info ] && . /tmp/team.${netif}.info
a56a5e
 
a56a5e
     uuid=$(cat /proc/sys/kernel/random/uuid)
a56a5e
     if [ "$netif" = "$bridgename" ]; then
a56a5e
         bridge=yes
a56a5e
+    elif [ "$netif" = "$teammaster" ]; then
a56a5e
+        team=yes
a56a5e
     elif [ "$netif" = "$bondname" ]; then
a56a5e
     # $netif can't be bridge and bond at the same time
a56a5e
         bond=yes
a56a5e
@@ -152,6 +156,9 @@ for netup in /tmp/net.*.did-setup ; do
a56a5e
         vlan=yes
a56a5e
     fi
a56a5e
 
a56a5e
+    # skip team interfaces for now, the host config must be in sync
a56a5e
+    [ "$netif" = "$teammaster" ] && continue
a56a5e
+
a56a5e
     {
a56a5e
         echo "# Generated by dracut initrd"
a56a5e
         echo "NAME=\"$netif\""
a56a5e
@@ -198,7 +205,7 @@ for netup in /tmp/net.*.did-setup ; do
a56a5e
     } > /tmp/ifcfg/ifcfg-$netif
a56a5e
 
a56a5e
     # bridge needs different things written to ifcfg
a56a5e
-    if [ -z "$bridge" ] && [ -z "$bond" ] && [ -z "$vlan" ]; then
a56a5e
+    if [ -z "$bridge" ] && [ -z "$bond" ] && [ -z "$vlan" ] && [ -z "$team" ]; then
a56a5e
         # standard interface
a56a5e
         {
a56a5e
             echo "TYPE=Ethernet"
a56a5e
@@ -264,6 +271,7 @@ for netup in /tmp/net.*.did-setup ; do
a56a5e
             ) >> /tmp/ifcfg/ifcfg-$slave
a56a5e
         done
a56a5e
     fi
a56a5e
+
a56a5e
     i=1
a56a5e
     for ns in $(getargs nameserver); do
a56a5e
         echo "DNS${i}=\"${ns}\"" >> /tmp/ifcfg/ifcfg-$netif