410 lines
12 KiB
Bash
Executable File
410 lines
12 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=
|
|
|
|
# This function parse the NICEXTRAPARAMS into an array.
|
|
# Each arry element contains all the extra params for an ip
|
|
# For example:
|
|
# NICEXTRAPARAMS="eth0!MTU=1500 sonething=x|MTU=1460,ib0!MTU=65520 CONNECTED_MODE=yes".
|
|
# After calling this function with eth0:
|
|
# array_extra_param[0]="MTU=1500 sonething=x"
|
|
# array_extra_param[1]="MTU=1460"
|
|
function get_nic_extra_params() {
|
|
nic=$1
|
|
if [ ! "$NICEXTRAPARAMS" ];then
|
|
return
|
|
fi
|
|
old_ifs=$IFS
|
|
IFS=$','
|
|
array_conf_temp=($NICEXTRAPARAMS)
|
|
IFS=$old_ifs
|
|
#echo "NICEXTRA=$NICEXTRAPARAMS"
|
|
|
|
i=0
|
|
while [ $i -lt ${#array_conf_temp[@]} ]
|
|
do
|
|
token="${array_conf_temp[$i]}"
|
|
D=
|
|
if echo "$token" | grep "!"; then
|
|
D="!"
|
|
else
|
|
D=":"
|
|
fi
|
|
key=`echo "$token" | cut -d"$D" -f 1`
|
|
#echo "key=$key nic=$nic"
|
|
if [ "$key" == "$nic" ]; then
|
|
str_temp_value=`echo "$token" | cut -d"$D" -f 2`
|
|
#echo "token=$token, str_temp_value=$str_temp_value"
|
|
old_ifs=$IFS
|
|
IFS=$'|'
|
|
array_nic_params=($str_temp_value)
|
|
IFS=$old_ifs
|
|
return
|
|
fi
|
|
i=$((i+1))
|
|
done
|
|
}
|
|
|
|
# This functions parse the extra parameters for an ip address of a nic
|
|
# Input is like this:
|
|
# MTU=65520 something=yes
|
|
# After the function is called:
|
|
# array_extra_param_names[0]="MTU"
|
|
# array_extra_param_values[0]="65520"
|
|
# array_extra_param_names[1]="something"
|
|
# array_extra_param_values[1]="yes"
|
|
#
|
|
function parse_nic_extra_params() {
|
|
str_extra=$1
|
|
|
|
unset array_extra_param_names
|
|
unset array_extra_param_values
|
|
|
|
echo $str_extra
|
|
|
|
old_ifs=$IFS
|
|
IFS=$' '
|
|
params_temp=($str_extra)
|
|
IFS=$old_ifs
|
|
k=0
|
|
while [ $k -lt ${#params_temp[@]} ]
|
|
do
|
|
token2="${params_temp[$k]}"
|
|
array_extra_param_names[$k]=`echo "$token2" | cut -d'=' -f 1`
|
|
array_extra_param_values[$k]=`echo "$token2" | cut -d'=' -f 2`
|
|
k=$((k+1))
|
|
done
|
|
}
|
|
|
|
# load library for network caculation
|
|
if [ "$(uname -s|tr 'A-Z' 'a-z')" = "linux" ];then
|
|
str_dir_name=`dirname $0`
|
|
. $str_dir_name/xcatlib.sh
|
|
fi
|
|
|
|
# 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
|
|
}
|
|
|
|
declare -a array_nic_params
|
|
declare -a array_extra_param_names
|
|
declare -a array_extra_param_values
|
|
|
|
# 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
|
|
|
|
get_nic_extra_params $str_bond_name
|
|
|
|
if [ ${#array_nic_params[@]} -gt 0 ]; then
|
|
str_extra_params=${array_nic_params[0]}
|
|
parse_nic_extra_params "$str_extra_params"
|
|
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[*]}"
|
|
NM_CONTROLLED=no
|
|
EOF
|
|
|
|
|
|
#add extra params
|
|
i=0
|
|
while [ $i -lt ${#array_extra_param_names[@]} ]
|
|
do
|
|
name="${array_extra_param_names[$i]}"
|
|
value="${array_extra_param_values[$i]}"
|
|
echo " $i: name=$name value=$value"
|
|
echo "${name}=${value}" >> $str_master_file
|
|
i=$((i+1))
|
|
done
|
|
|
|
if [[ ${str_bond_name} == [a-zA-Z0-9]*.[0-9]* ]]; then
|
|
echo "VLAN=yes" >> $str_master_file
|
|
|
|
str_parent_device=`echo ${str_bond_name} | sed -e 's/\([a-zA-Z0-9]*\)\.[0-9]*/\1/g'`
|
|
str_parent_file=`echo ${str_cfg_dir}/ifcfg-${str_bond_name} | sed -e 's/\([a-zA-Z0-9]*\)\.[0-9]*/\1/g'`
|
|
|
|
if [[ ! -e ${str_parent_file} ]] ; then
|
|
|
|
get_nic_extra_params $str_parent_device
|
|
if [ ${#array_nic_params[@]} -gt 0 ]; then
|
|
str_extra_params=${array_nic_params[0]}
|
|
parse_nic_extra_params "$str_extra_params"
|
|
fi
|
|
|
|
cat > $str_parent_file <<EOF
|
|
DEVICE=${str_parent_device}
|
|
BOOTPROTO=none
|
|
ONBOOT=yes
|
|
USERCTL=no
|
|
BONDING_OPTS="${array_bond_opts[*]}"
|
|
NM_CONTROLLED=no
|
|
EOF
|
|
#add extra params
|
|
i=0
|
|
while [ $i -lt ${#array_extra_param_names[@]} ]
|
|
do
|
|
name="${array_extra_param_names[$i]}"
|
|
value="${array_extra_param_values[$i]}"
|
|
echo " $i: name=$name value=$value"
|
|
echo "${name}=${value}" >> $str_parent_file
|
|
i=$((i+1))
|
|
done
|
|
|
|
fi
|
|
|
|
str_bond_name_old=${str_bond_name}
|
|
str_bond_name=${str_parent_device}
|
|
fi
|
|
|
|
# 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
|
|
NM_CONTROLLED=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
|
|
|
|
#add extra params
|
|
i=0
|
|
while [ $i -lt ${#array_extra_param_names[@]} ]
|
|
do
|
|
name="${array_extra_param_names[$i]}"
|
|
value="${array_extra_param_values[$i]}"
|
|
echo " $i: name=$name value=$value"
|
|
echo "${name}=${value}" >> $str_master_file
|
|
i=$((i+1))
|
|
done
|
|
|
|
# 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
|
|
[[ -n ${str_bond_name_old} ]] && $(ifup ${str_bond_name_old} &>/dev/null)
|
|
$(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
|
|
|
|
|