258 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			258 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
#! /bin/bash
 | 
						|
# IBM(c) 2014 EPL license http://www.eclipse.org/legal/epl-v10.html
 | 
						|
 | 
						|
# Usage:
 | 
						|
# configbond bondname nic1@nic2@... [opt1@opt2@...]
 | 
						|
#
 | 
						|
# Description:
 | 
						|
#   This script is used to configure bond interface base on the arguments from the 
 | 
						|
#   command line and the network information from nics and networks tables.
 | 
						|
#
 | 
						|
#   This script will create bond interface named <bondname> with 'nic1','nic2'... as slave
 | 
						|
#   devices. The bonding options 'opt1','opt2'... will be configured to bond interface.
 | 
						|
#   
 | 
						|
#   The network information for the bond interface will be gotten from the nics.nicsip and
 | 
						|
#   nics.nicnetworks for interface <bondname>. If cannot get for <bondname>, try to 
 | 
						|
#   search for nic1. If failed too, then nic2 ...
 | 
						|
#   
 | 
						|
#   It only supports to configure one bond device at each run. If you want to create
 | 
						|
#   multiple bond devices, call it multiple times.
 | 
						|
#
 | 
						|
# Note:
 | 
						|
#   This script only works for IPv4 so far.
 | 
						|
 | 
						|
 | 
						|
# Following are examples of variables which are exported from mypostscript. Mostly, we need the nics and 
 | 
						|
# networks related varirables which are exported from xcat nics and networks tables.
 | 
						|
#   NICIPS=bond0!10.0.0.12
 | 
						|
#   NICTYPES=bond0!Ethernet
 | 
						|
#   NICHOSTNAMESUFFIXES=bond0!-bond0
 | 
						|
#   NICNETWORKS=bond0!10_0_0_0-255_255_255_0
 | 
						|
#   NICCUSTOMSCRIPTS=bond0!configbond 
 | 
						|
#   NETWORKS_LINES=2
 | 
						|
#   NETWORKS_LINE1=netname=10_0_0_0-255_255_255_0||net=10.0.0.0||mask=255.255.255.0||mgtifname=eth1||gateway=<xcatmaster>||dhcpserver=||tftpserver=10.0.0.10||nameservers=||ntpservers=||logservers=||dynamicrange=||staticrange=||staticrangeincrement=||nodehostname=||ddnsdomain=||vlanid=||domain=||disable=||comments=
 | 
						|
#   NETWORKS_LINE2=netname=10_0_2_0-255_255_255_0||net=10.0.2.0||mask=255.255.255.0||mgtifname=eth0||gateway=10.0.2.2||dhcpserver=||tftpserver=10.0.2.15||nameservers=||ntpservers=||logservers=||dynamicrange=||staticrange=||staticrangeincrement=||nodehostname=||ddnsdomain=||vlanid=||domain=||disable=||comments=
 | 
						|
 | 
						|
 | 
						|
# locd library for network caculation
 | 
						|
str_dir_name=`dirname $0`
 | 
						|
. $str_dir_name/xcatlib.sh
 | 
						|
 | 
						|
# Subroutine to display message and pass it to syslog
 | 
						|
# Usage: showmsg "message to putput" ["error"]
 | 
						|
function showmsg() {
 | 
						|
    msg="configbond: $1"
 | 
						|
    error=$2
 | 
						|
 | 
						|
    if [ -n "$error" ]; then
 | 
						|
        $(logger -t xcat -p local4.err $msg)
 | 
						|
    else
 | 
						|
        $(logger -t xcat -p local4.info $msg)
 | 
						|
    fi
 | 
						|
    
 | 
						|
    echo $msg
 | 
						|
}
 | 
						|
 | 
						|
# Check OS version and get the directory of network configuration file
 | 
						|
str_bond_name=''
 | 
						|
str_os_type=`uname | tr 'A-Z' 'a-z'`
 | 
						|
str_cfg_dir=''
 | 
						|
str_temp=''
 | 
						|
if [ "$str_os_type" = "linux" ];then
 | 
						|
    str_temp=`echo $OSVER | grep -E '(sles|suse)'`
 | 
						|
    if [ -f "/etc/redhat-release" ];then
 | 
						|
        str_os_type="redhat"
 | 
						|
        str_cfg_dir="/etc/sysconfig/network-scripts"
 | 
						|
    elif [ -f "/etc/SuSE-release" -o -n "$str_temp" ];then
 | 
						|
        str_os_type="sles"
 | 
						|
        str_cfg_dir="/etc/sysconfig/network"
 | 
						|
    else
 | 
						|
        showmsg "Only supports RHEL and SLES" "error"
 | 
						|
        exit -1
 | 
						|
    fi
 | 
						|
else
 | 
						|
    showmsg "Does NOT support non-Linux Operating System" "error"
 | 
						|
    exit -1 
 | 
						|
fi
 | 
						|
 | 
						|
 | 
						|
# Parse arguments
 | 
						|
old_ifs=$IFS
 | 
						|
IFS=$'@'
 | 
						|
 | 
						|
if [ $# -eq 2 ];then
 | 
						|
    array_bond_opts="mode=4 miimon=100 downdelay=0 updelay=0 lacp_rate=fast xmit_hash_policy=1"
 | 
						|
elif [ $# -eq 3 ]; then
 | 
						|
    array_bond_opts=($3)
 | 
						|
else
 | 
						|
    showmsg "Only supports 2 or 3 arguments. Usage: configbond bondname nic1@nic2@... [opt1@opt2@...]"
 | 
						|
    exit -1
 | 
						|
fi
 | 
						|
 | 
						|
str_bond_name=$1
 | 
						|
array_bond_slaves=($2)
 | 
						|
IFS=$old_ifs
 | 
						|
 | 
						|
# examples of variables
 | 
						|
#   str_bond_name=bond0
 | 
						|
#   array_bond_slaves=(eth1 eth2)
 | 
						|
#   array_bond_opts=(mode=1 miimon=100)
 | 
						|
 | 
						|
# Check the existence of slave devices and remove the inactive ones
 | 
						|
realdevs=$(ip addr show 2>&1 | grep -E '^[1-9]' | cut -d: -f2)
 | 
						|
for slave in ${array_bond_slaves[*]}; do
 | 
						|
    active=0
 | 
						|
    for rdev in $realdevs; do
 | 
						|
        if [ $rdev = $slave ]; then
 | 
						|
            active=1
 | 
						|
        fi
 | 
						|
    done
 | 
						|
    if [ $active -eq 0 ]; then
 | 
						|
        showmsg "Warning: device $slave does not exist. It will not be configured as a slave device."
 | 
						|
        # remove the device from slave list
 | 
						|
        allslaves=${array_bond_slaves[*]}
 | 
						|
        allslaves=${allslaves/$slave/}
 | 
						|
        array_bond_slaves=($allslaves)
 | 
						|
    fi
 | 
						|
done
 | 
						|
 | 
						|
if [ ${#array_bond_slaves[*]} -eq 0 ]; then
 | 
						|
    showmsg "No available slave devices to use." "error"
 | 
						|
    exit -1
 | 
						|
fi
 | 
						|
 | 
						|
showmsg "Create bond interface $str_bond_name with slaves=\"${array_bond_slaves[*]}\" opts=\"${array_bond_opts[*]}\""
 | 
						|
 | 
						|
# Get bond device's IP address
 | 
						|
str_bond_ip=""
 | 
						|
if [ -z "$NICIPS" ]; then
 | 
						|
    showmsg "Failed to get IP for bond interface: $str_bond_name. No IP is set in nics.nicips table."
 | 
						|
    exit 1
 | 
						|
else
 | 
						|
    for devname in $str_bond_name ${array_bond_slaves[*]}; do    # for each "bondname nic1 nic2 ..."
 | 
						|
        for ifipinfo in ${NICIPS//,/ }; do    # for each "ifname!ifip"
 | 
						|
            old_ifs=$IFS
 | 
						|
            IFS=$'!'
 | 
						|
            arrayifinfo=($ifipinfo)    # [0] - ifname; [1] - if ip address
 | 
						|
            IFS=$old_ifs
 | 
						|
 | 
						|
            if [ "$devname" = "${arrayifinfo[0]}" ]; then
 | 
						|
                str_bond_ip=${arrayifinfo[1]}
 | 
						|
                break 2
 | 
						|
            fi
 | 
						|
        done
 | 
						|
    done
 | 
						|
fi
 | 
						|
 | 
						|
# remove the left part from |. that means only keeping the first ip in the interface if there are alias ip
 | 
						|
str_bond_ip=${str_bond_ip%%|*}
 | 
						|
 | 
						|
if [ -z "str_bond_ip" ]; then
 | 
						|
    showmsg "Failed to get IP for $str_bond_name ${array_bond_slaves[*]} from $NICIPS"
 | 
						|
    exit 1
 | 
						|
fi
 | 
						|
 | 
						|
# Get the network and netmask info for the $str_bond_ip from networks table
 | 
						|
str_bond_net=
 | 
						|
str_bond_mask=
 | 
						|
num_i=1
 | 
						|
while [ $num_i -le $NETWORKS_LINES ];do
 | 
						|
    eval str_bond_network=\$NETWORKS_LINE$num_i
 | 
						|
    str_temp_net=${str_bond_network#*net=}    # remove the left part from 'net='
 | 
						|
    str_temp_net=${str_temp_net%%|*}             # remove the right part from first '|'
 | 
						|
    str_temp_mask=${str_bond_network#*mask=}    # remove the left part from 'mask='
 | 
						|
    str_temp_mask=${str_temp_mask%%|*}             # remove the right part from first '|'
 | 
						|
    
 | 
						|
    str_temp_net1=$(v4calcnet $str_bond_ip $str_temp_mask)
 | 
						|
    str_temp_net2=$(v4calcnet $str_temp_net $str_temp_mask)
 | 
						|
    if [ "$str_temp_net1" = "$str_temp_net2" ];then
 | 
						|
        str_bond_net=$str_temp_net
 | 
						|
        str_bond_mask=$str_temp_mask
 | 
						|
        break
 | 
						|
    fi
 | 
						|
    num_i=$((num_i+1))
 | 
						|
done
 | 
						|
 | 
						|
if [ -z "$str_bond_net" ] || [ -z "$str_bond_mask" ]; then
 | 
						|
    showmsg "Cannot find network information for bond IP $str_bond_ip from networks table." "error"
 | 
						|
    exit 1
 | 
						|
fi
 | 
						|
 | 
						|
showmsg "IP information for $str_bond_name: IP=$str_bond_ip; network=$str_bond_net; netmask=$str_bond_mask"
 | 
						|
 | 
						|
# Create bond config file
 | 
						|
 | 
						|
str_master_file="${str_cfg_dir}/ifcfg-${str_bond_name}"
 | 
						|
 | 
						|
if [ "$str_os_type" = "redhat" ];then
 | 
						|
    # Create the master file
 | 
						|
    cat > $str_master_file <<EOF
 | 
						|
DEVICE=${str_bond_name}
 | 
						|
BOOTPROTO=none
 | 
						|
IPADDR=${str_bond_ip}
 | 
						|
NETMASK=${str_bond_mask}
 | 
						|
ONBOOT=yes
 | 
						|
USERCTL=no
 | 
						|
BONDING_OPTS="${array_bond_opts[*]}"
 | 
						|
EOF
 | 
						|
 | 
						|
    # Create the slave files
 | 
						|
    for slave in ${array_bond_slaves[*]}; do
 | 
						|
        str_slave_file="${str_cfg_dir}/ifcfg-${slave}"
 | 
						|
        cat > $str_slave_file <<EOF
 | 
						|
DEVICE=${slave}
 | 
						|
MASTER=${str_bond_name}
 | 
						|
SLAVE=yes
 | 
						|
BOOTPROTO=none
 | 
						|
ONBOOT=yes
 | 
						|
USERCTL=no
 | 
						|
EOF
 | 
						|
    done
 | 
						|
 | 
						|
elif [ "$str_os_type" = "sles" ];then
 | 
						|
    # Create the master file
 | 
						|
    cat > $str_master_file <<EOF
 | 
						|
NAME='Bonded Interface'
 | 
						|
BOOTPROTO=static
 | 
						|
BONDING_MASTER=yes
 | 
						|
IPADDR=${str_bond_ip}
 | 
						|
NETMASK=${str_bond_mask}
 | 
						|
STARTMODE=onboot
 | 
						|
USERCONTROL=no
 | 
						|
BONDING_MODULE_OPTS="${array_bond_opts[*]}"
 | 
						|
EOF
 | 
						|
 | 
						|
   # Create the slave entries and files
 | 
						|
   num_index=0
 | 
						|
   for slave in ${array_bond_slaves[*]}; do
 | 
						|
       # this is a special part to inject each slave device to master cfg
 | 
						|
       echo "BONDING_SLAVE_${num_index}=$slave" >> $str_master_file
 | 
						|
       num_index=$((num_index+1))
 | 
						|
 | 
						|
       str_slave_file="${str_cfg_dir}/ifcfg-${slave}"
 | 
						|
       echo "BOOTPROTO=none" > $str_slave_file
 | 
						|
       echo "STARTMODE=hotplug" >> $str_slave_file
 | 
						|
   done
 | 
						|
fi
 | 
						|
 | 
						|
# add bonding driver alias for <bondname>
 | 
						|
echo "alias $str_bond_name bonding" > /etc/modprobe.d/$str_bond_name.conf
 | 
						|
 | 
						|
# Bring down the salve devices first
 | 
						|
for slave in ${str_bond_name} ${array_bond_slaves[*]}; do
 | 
						|
    $(ifdown $slave &>/dev/null)
 | 
						|
done
 | 
						|
 | 
						|
# Bring up bond device
 | 
						|
$(ifup ${str_bond_name} &>/dev/null)
 | 
						|
 | 
						|
if [ $? -ne 0 ]; then
 | 
						|
    showmsg "Failed to bring up $str_bond_name" "error"
 | 
						|
    exit 1
 | 
						|
fi
 | 
						|
 | 
						|
showmsg "Finished the configuration for bond interface $str_bond_name"
 | 
						|
exit 0
 | 
						|
 | 
						|
 |