晋太元中,武陵人捕鱼为业。缘溪行,忘路之远近。忽逢桃花林,夹岸数百步,中无杂树,芳草鲜美,落英缤纷。渔人甚异之,复前行,欲穷其林。 林尽水源,便得一山,山有小口,仿佛若有光。便舍船,从口入。初极狭,才通人。复行数十步,豁然开朗。土地平旷,屋舍俨然,有良田、美池、桑竹之属。阡陌交通,鸡犬相闻。其中往来种作,男女衣着,悉如外人。黄发垂髫,并怡然自乐。 见渔人,乃大惊,问所从来。具答之。便要还家,设酒杀鸡作食。村中闻有此人,咸来问讯。自云先世避秦时乱,率妻子邑人来此绝境,不复出焉,遂与外人间隔。问今是何世,乃不知有汉,无论魏晋。此人一一为具言所闻,皆叹惋。余人各复延至其家,皆出酒食。停数日,辞去。此中人语云:“不足为外人道也。”(间隔 一作:隔绝) 既出,得其船,便扶向路,处处志之。及郡下,诣太守,说如此。太守即遣人随其往,寻向所志,遂迷,不复得路。 南阳刘子骥,高尚士也,闻之,欣然规往。未果,寻病终。后遂无问津者。
|
Server : Apache System : Linux srv.rainic.com 4.18.0-553.47.1.el8_10.x86_64 #1 SMP Wed Apr 2 05:45:37 EDT 2025 x86_64 User : rainic ( 1014) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /usr/bin/ |
Upload File : |
#!/bin/bash
#
# Translate tool from bonding configuration to team.
#
# Copyright (C) 2013 Flavio Leitner <fbl@redhat.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2,
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
#
VERSION="0.97"
PR_QUIET=0
PR_ERR=1
PR_WARN=2
PR_INFO=3
PR_DBG=4
#defaults
ARGC=$#
FORMAT_IFCFG=0
FORMAT_JANSSON=1
OUTPUT_FORMAT=${FORMAT_IFCFG}
MODE_IFCFG=0
MODE_NOIFCFG=1
MODE=${MODE_IFCFG}
OUTPUT_FILE=
RENAME=
DEVICE=
BOND_MASTER=
STDOUT=1
BONDING_OPTS=
CONFIGDIR="/etc/sysconfig/network-scripts"
PR_LVL=3
OUTPUT_DIR=
OUTPUT_TMP_DIR=
TMP_FILES=()
RUNNER_OPTS=()
LWATCH_OPTS=()
# array: ( 'port ifname', 'opt1', 'opt2', 'optn', 'opt4', 'port ifname', ... )
PORT_LIST=
PORTS_OPTS=()
PRIMARY=
PRIMARY_RESELECT=
# building file scratch memory area
VFILE=
show_examples()
{
cat << EOF
The following commands will deliver the ifcfg files into a temporary
directory. You can review the files and copy to the right location.
Add the following argument to the commands below to print the output
to the screen instead of writing to files.
--stdout
Add the following arguments to the commands below to set the
destination directory for the output files.
--outputdir </path/to/dir>
Add the following argument to the commands below to output the
files in teamd format (JSON) instead of the default ifcfg format.
--json
To convert the current "bond0" ifcfg configuration to team ifcfg:
# $0 --master bond0
To convert the current "bond0" ifcfg configuration out of the
standard ifcfg-:
# $0 --master bond0 --configdir </path/to/ifcfg>
To convert the current "bond0" ifcfg configuration to team ifcfg
renaming the interface name to "team0". (carefull: firewall rules,
aliases interfaces, etc., will break after the renaming because the
tool will only change the ifcfg file, nothing else)
# $0 --master bond0 --rename team0
To convert given bonding parameters without any ifcfg:
# $0 --bonding_opts "mode=1 miimon=500"
To convert given bonding parameters without any ifcfg with ports:
# $0 --bonding_opts "mode=1 miimon=500 primary=eth1 primary_reselect-0" \\
--port eth1 --port eth2 --port eth3 --port eth4
EOF
}
usage()
{
cat << EOF
usage: $0 [options]
This tool translates bonding configuration to team.
See bond2team(1) for detailed information.
OPTIONS:
--master <interface> set the master interface name or ifcfg
--rename <iface> rename the master interface to <iface>
--ifcfg set the output format to ifcfg style
--json set the output format to teamd style
--bonding_opts pass the bonding options instead of reading
from the ifcfg- file
--port <iface> add the interface to the port's list
--configdir <dir> set where the ifcfg- files are
default: /etc/sysconfig/network-scripts
--outputdir <dir> set the output diretory
default: temporary diretory
--stdout print to stdout instead of
modify the system's files.
--debug increase debug level
--quiet no messages
--version show the tool version
--help this screen
--examples show command examples
EOF
}
# Output Functions
pr()
{
if [ $1 -le $PR_LVL ]; then
shift;
echo "$*" > /dev/stderr
fi
}
pr_error()
{
pr ${PR_ERR} "ERROR: " $*
}
pr_warn()
{
pr ${PR_WARN} "WARNING: " $*
}
pr_info()
{
pr ${PR_INFO} "INFO: " $*
}
pr_dbg()
{
pr ${PR_DBG} "DEBUG: " $*
}
to_stdout()
{
return ${STDOUT}
}
create_output_file()
{
local f=$1
if [ ! -d "${OUTPUT_TMP_DIR}" ]; then
OUTPUT_TMP_DIR=$(LANG=C mktemp -d /tmp/bond2team.XXXXXX)
fi
if [ ! -d "${OUTPUT_TMP_DIR}" ]; then
pr_error "${FUNCNAME} can't create dir ${OUTPUT_TMP_DIR}"
return 1
fi
local tmpfile=${OUTPUT_TMP_DIR}/${f}
touch ${tmpfile}
if [ ! -f ${tmpfile} ]; then
pr_error "${FUNCNAME} can't create file ${tmpfile}"
return 1
fi
local pos=${#TMP_FILES[*]}
TMP_FILES[${pos}]="${tmpfile}"
OUTPUT_FILE=${tmpfile}
}
show_output_files()
{
echo ""
echo "Resulted files:"
for tmpf in $(seq 0 $((${#TMP_FILES[@]} - 1)))
do
echo " ${TMP_FILES[$tmpf]}"
done
}
clean_up()
{
pr_dbg "${FUNCNAME} $*"
for tmpf in $(seq 0 $((${#TMP_FILES[@]} - 1)))
do
pr_dbg "rm -f ${TMP_FILES[$tmpf]}"
rm -f ${TMP_FILES[$tmpf]}
done
if [ -d "{OUTPUT_TMP_DIR}" ]; then
rmdir ${OUTPUT_TMP_DIR}
fi
}
ifcfg_get_device()
{
local ifcfg=$1
if [ ! -f ${ifcfg} ]; then
pr_error "file not found: ${ifcfg}"
return 1
fi
DEVICE=`LANG=C sed -n \
"s@^[[:space:]]*DEVICE=[\"]*\(.*\)\([[:space:]#]\|\"\|$\)@\1@p" \
$ifcfg`
if [ -z "${DEVICE}" ]; then
pr_error "ifcfg file not supported: ${ifcfg}"
return 1
fi
}
ifcfg_get_master_file()
{
local dev=${1}
MASTER="${dev}"
if [ "${MODE}" -eq "${MODE_NOIFCFG}" ]; then
return 0
fi
if [ ! -f ${MASTER} ]; then
MASTER="${CONFIGDIR}/ifcfg-${dev}"
if [ -f ${MASTER} ]; then
return 0
fi
if [ -n "${BONDING_OPTS}" ]; then
# options provided, set noifcfg
MODE=${MODE_NOIFCFG}
MASTER=${dev}
return 0
fi
pr_error "Can't find ifcfg file for ${dev}"
return 1
fi
return 0
}
ifcfg_overwrite_files()
{
pr_dbg "${FUNCNAME} $*"
/bin/cp -f ${OUTPUT_TMP_DIR}/ifcfg* ${OUTPUT_DIR}
}
ifcfg_get_bond_opts()
{
pr_dbg "${FUNCNAME} $*"
local ifcfg=$1
if [ -n "${BONDING_OPTS}" ]; then
pr_dbg "${FUNCNAME} bonding_opts=${BONDING_OPTS}"
return 0
fi
if [ ! -f ${ifcfg} ]; then
pr_error "File not found: ${ifcfg}"
return 1
fi
BONDING_OPTS=`LANG=C sed -n \
"s@^[[:space:]]*BONDING_OPTS=[\"]*\(.*\)\([[:space:]#]\|\"\|$\)@\1@p" \
$ifcfg`
if [ -z "${BONDING_OPTS}" ]; then
pr_error "ifcfg file not supported: ${MASTER}"
return 1
fi
pr_dbg "${FUNCNAME} bonding_opts=${BONDING_OPTS}"
return 0
}
vfile_reset()
{
VFILE=()
}
vfile_load_ifcfg()
{
pr_dbg "${FUNCNAME} $*"
local ifcfg=$1
vfile_reset
if [ ${MODE} -eq ${MODE_NOIFCFG} ]; then
return 0
fi
# filter out bonding and team options and
# don't break lines with spaces
oIFS="$IFS"
IFS=$'\n'
VFILE=( $(LANG=C \
grep -iv 'BONDING_OPTS\|SLAVE\|MASTER\|TYPE\|DEVICETYPE\|TEAM' \
$ifcfg ))
IFS="$oIFS"
}
vfile_write_to_file()
{
pr_dbg "${FUNCNAME} $*"
local output=$1
for ln in $(seq 0 $((${#VFILE[@]} - 1)))
do
echo "${VFILE[$ln]}" >> $output
done
return 0
}
ifcfg_dump_stdout()
{
local dev="${1}"
local ifcfg="ifcfg-${dev}"
if [ -z "${dev}" ]; then
ifcfg="ifcfg-<interface name>"
fi
for ln in $(seq 0 $((${#VFILE[@]} - 1)))
do
[ $ln -eq 0 ] && echo "---8<--- ${ifcfg} ---8<---"
echo "${VFILE[$ln]}"
done
echo "---8<--- ${ifcfg} ---8<---"
echo ""
return 0
}
vfile_get_device()
{
pr_dbg "${FUNCNAME} $*"
if [ ${MODE} -eq ${MODE_NOIFCFG} ]; then
pr_dbg "${FUNCNAME} using DEVICE=${MASTER}"
DEVICE=${MASTER}
return 0
fi
for ln in $(seq 0 $((${#VFILE[@]} - 1)))
do
local line=${VFILE[$ln]}
if [ "${line%%=*}" = "DEVICE" ]; then
local name_line="${line##*=}"
local name="${name_line%%[ # ]*}"
DEVICE=${name}
pr_dbg "${FUNCNAME} from file: DEVICE=${DEVICE}"
return 0
fi
done
pr_error "Failed to find the device's name"
return 1
}
vfile_get_ipaddr()
{
for ln in $(seq 0 $((${#VFILE[@]} - 1)))
do
local line=${VFILE[$ln]}
if [ "${line%%=*}" = "IPADDR" ]; then
local ipaddr_line="${line##*=}"
local ipaddr="${ipaddr_line%%[ # ]*}"
echo "${ipaddr}"
fi
done
}
vfile_add_line()
{
pr_dbg "${FUNCNAME} $*"
local pos=${#VFILE[*]}
VFILE[${pos}]="$1"
}
ifcfg_device_rename()
{
local device=$1
local rename=$2
# neither device nor rename was provided
if [ -z "${rename}" ]; then
return 0
fi
# renaming with no ifcfg?
if [ ${MODE} -eq ${MODE_NOIFCFG} ]; then
return 0
fi
for ln in $(seq 0 $((${#VFILE[@]} - 1)))
do
local line=${VFILE[$ln]}
if [ "${line%%=*}" = "DEVICE" ]; then
newdev="${line/${device}/${rename}}"
VFILE[$ln]="$newdev"
TEAM_MASTER=${rename}
return 0
fi
done
pr_error "Failed to rename $device to $rename"
return 1
}
team_port_set_devtype()
{
pr_dbg "${FUNCNAME} $*"
local master=$1
vfile_add_line "DEVICETYPE=\"TeamPort\""
vfile_add_line "TEAM_MASTER=\"$master\""
}
team_port_set_config()
{
pr_dbg "${FUNCNAME} $*"
local port=$1
local team_port_config=""
if [ "${PRIMARY}" == "$port" ]; then
team_port_config="'{ \"prio\" : -10"
else
team_port_config="'{ \"prio\" : -100"
fi
if [ -n "${PRIMARY_RESELECT}" ]; then
if [ "${PRIMARY}" == "$port" ]; then
if [ -z "${team_port_config}" ]; then
team_port_config="'{ \"sticky\" : true }'"
else
team_port_config="${team_port_config}, \"sticky\" : true }'"
fi
else
if [ -z "${team_port_config}" ]; then
team_port_config="{ \"sticky\" : false }'"
else
team_port_config="${team_port_config}, \"sticky\" : false }'"
fi
fi
else
if [ -n "${team_port_config}" ]; then
team_port_config="${team_port_config} }'"
fi
fi
if [ -n "$team_port_config" ]; then
vfile_add_line "TEAM_PORT_CONFIG=$team_port_config"
fi
}
team_port_ifcfg_create()
{
local dev=$1
vfile_load_ifcfg $dev
if ! vfile_get_device; then
return 1
fi
team_port_set_devtype ${TEAM_MASTER}
team_port_set_config ${DEVICE}
return 0
}
team_master_set_devtype()
{
pr_dbg "${FUNCNAME} $*"
vfile_add_line "DEVICETYPE=\"Team\""
}
team_master_set_config()
{
pr_dbg "${FUNCNAME} $*"
local team_config="'{ \"runner\" : { "
local nr_opt=0
nr_opt=${#RUNNER_OPTS[@]}
if [ $nr_opt -eq 0 ]; then
# default to miimon/ethtool
team_config="${team_config} \"name\" : \"roundrobin\" }"
else
# add runner options
for pos in $(seq 0 $((${#RUNNER_OPTS[@]} - 1)))
do
if [ $pos -ne 0 ]; then
team_config="${team_config}, "
fi
team_config="${team_config} ${RUNNER_OPTS[$pos]}"
done
team_config="${team_config} }"
fi
nr_opt=${#LWATCH_OPTS[@]}
if [ $nr_opt -eq 0 ]; then
# default to miimon/ethtool
team_config="${team_config}, \"link_watch\" : { \"name\" : \"ethtool\" }"
else
team_config="${team_config}, \"link_watch\" : { "
# add linkwatch options
for pos in $(seq 0 $(($nr_opt - 1)))
do
if [ $pos -ne 0 ]; then
team_config="${team_config}, "
fi
team_config="${team_config} ${LWATCH_OPTS[$pos]}"
done
team_config="${team_config} }"
fi
team_config="${team_config} }'"
pr_dbg "built team_config=${team_config}"
vfile_add_line "TEAM_CONFIG=${team_config}"
return 0
}
team_ifcfg_dump_stdout()
{
pr_dbg "${FUNCNAME} $*"
local dev=$1
if ! ifcfg_dump_stdout ${dev}; then
return 1
fi
return 0
}
team_ifcfg_write_file()
{
pr_dbg "${FUNCNAME} $*"
local dev=$1
OUTPUT_FILE=
local filenm="ifcfg-${dev}"
if [ -z "${dev}" ]; then
filenm="ifcfg"
fi
create_output_file ${filenm}
if [ ! -f "${OUTPUT_FILE}" ]; then
return 1
fi
if ! vfile_write_to_file ${OUTPUT_FILE}; then
return 1
fi
return 0
}
team_master_ifcfg_create()
{
pr_dbg "${FUNCNAME} $*"
if ! team_master_set_devtype; then
return 1
fi
if ! team_master_set_config; then
return 1
fi
return 0
}
team_ifcfg_write()
{
pr_dbg "${FUNCNAME} $*"
local dev=${1}
if to_stdout; then
team_ifcfg_dump_stdout ${dev} || return 1
else
team_ifcfg_write_file ${dev} || return 1
fi
return 0
}
team_ifcfg_deliver()
{
pr_dbg "${FUNCNAME} $*"
if to_stdout; then
return 0
fi
if [ -z "${OUTPUT_DIR}" ]; then
show_output_files
else
ifcfg_overwrite_files
clean_up
fi
return 0
}
teamd_config_create()
{
vfile_reset
vfile_add_line "{"
# add runner options
vfile_add_line " \"device\" : \"${DEVICE}\","
vfile_add_line " \"runner\" : {"
local runner_nr=${#RUNNER_OPTS[@]}
if [ ${runner_nr} -eq 0 ]; then
# default roundrobin
vfile_add_line " \"runner\" : \"roundrobin\" "
else
local last_pos=$((${runner_nr} - 1))
for pos in $(seq 0 ${last_pos})
do
if [ $pos -eq ${last_pos} ]; then
vfile_add_line " ${RUNNER_OPTS[$pos]}"
else
vfile_add_line " ${RUNNER_OPTS[$pos]},"
fi
done
fi
vfile_add_line " },"
vfile_add_line " \"link_watch\" : {"
local lwatch_nr=${#LWATCH_OPTS[@]}
if [ ${lwatch_nr} -eq 0 ]; then
# default to miimon
lwatch_add_opt "\"name\" : \"ethtool\""
else
for pos in $(seq 0 ${last_pos})
do
last_pos=$((${lwatch_nr} - 1))
if [ $pos -eq ${last_pos} ]; then
vfile_add_line " ${LWATCH_OPTS[$pos]}"
else
vfile_add_line " ${LWATCH_OPTS[$pos]},"
fi
done
fi
vfile_add_line " },"
return 0
}
teamd_config_close()
{
vfile_add_line "}"
return 0
}
teamd_dump_stdout()
{
for ln in $(seq 0 $((${#VFILE[@]} - 1)))
do
[ $ln -eq 0 ] && echo "---8<--- teamd.conf ---8<---"
echo "${VFILE[$ln]}"
done
echo "---8<--- teamd.conf ---8<---"
echo ""
return 0
}
teamd_write_file()
{
pr_dbg "${FUNCNAME} $*"
local dev=$1
OUTPUT_FILE=
create_output_file "teamd.conf"
if [ ! -f "${OUTPUT_FILE}" ]; then
return 1
fi
if ! vfile_write_to_file ${OUTPUT_FILE}; then
return 1
fi
return 0
}
teamd_config_write()
{
pr_dbg "${FUNCNAME} $*"
if to_stdout; then
teamd_dump_stdout || return 1
else
teamd_write_file ${dev} || return 1
show_output_files
fi
return 0
}
teamd_port_create()
{
vfile_add_line " \"ports\" : {"
return 0
}
teamd_port_close()
{
vfile_add_line " }"
return 0
}
teamd_port_add()
{
pr_dbg "${FUNCNAME} $*"
local dev=${1}
local lastone=${2}
if [ -n "${PORT_LIST}" ]; then
DEVICE=${dev}
else
if ! ifcfg_get_device ${dev}; then
return 1
fi
fi
vfile_add_line " \"${DEVICE}\" : {"
if [ "${PRIMARY}" == "${DEVICE}" ]; then
vfile_add_line " \"prio\" : -10,"
else
vfile_add_line " \"prio\" : -100,"
fi
if [ -n "${PRIMARY_RESELECT}" ]; then
if [ "${PRIMARY}" == "$port" ]; then
vfile_add_line " \"sticky\" : true "
else
vfile_add_line " \"sticky\" : false "
fi
else
vfile_add_line " \"sticky\" : false "
fi
if [ ${lastone} -eq 1 ]; then
vfile_add_line " }"
else
vfile_add_line " },"
fi
return 0
}
# Runner Functions
runner_add_opt()
{
pr_dbg "${FUNCNAME} $*"
local pos=${#RUNNER_OPTS[*]}
RUNNER_OPTS[${pos}]="$1"
}
runner_parse_adselect()
{
pr_dbg "${FUNCNAME} $*"
local value=$1
case $value in
"0"|"stable")
runner_add_opt "\"agg_select_policy\" : \"bandwidth\"" || return 1
;;
"1"|"bandwidth")
runner_add_opt "\"agg_select_policy\" : \"bandwidth\"" || return 1
;;
"2"|"count")
runner_add_opt "\"agg_select_policy\" : \"count\"" || return 1
;;
*)
pr_error "parameter ad_select=$value is not supported"
return 1
esac
}
runner_parse_failovermac()
{
pr_dbg "${FUNCNAME} $*"
local value=$1
case $value in
"0")
runner_add_opt "\"hwaddr_policy\" : \"same_all\"" || return 1
;;
"1"|"active")
runner_add_opt "\"hwaddr_policy\" : \"by_active\"" || return 1
;;
"2"|"follow")
runner_add_opt "\"hwaddr_policy\" : \"only_active\"" || return 1
;;
*)
pr_error "parameter fail_over_mac $value is not supported"
return 1
;;
esac
}
runner_parse_lacprate()
{
pr_dbg "${FUNCNAME} $*"
local value=$1
case $value in
"slow"|"0")
runner_add_opt "\"fast_rate\" : 0" || return 1
;;
"fast"|"1")
runner_add_opt "\"fast_rate\" : 1" || return 1
;;
*)
pr_error "parameter lacp_rate=$value is not supported"
return 1
;;
esac
}
runner_parse_xmit_policy()
{
pr_dbg "${FUNCNAME} $*"
local value=$1
case $value in
"layer2")
runner_add_opt "\"tx_hash\" : [ \"eth\" ]" || return 1
;;
"layer2+3")
runner_add_opt "\"tx_hash\" : [ \"eth\", \"l3\" ]" || return 1
;;
"layer3+4")
runner_add_opt "\"tx_hash\" : [ \"l3\", \"l4\" ]" || return 1
;;
*)
pr_error "parameter xmit_hash_policy=$value is not supported"
return 1
esac
}
runner_parse_mode()
{
pr_dbg "${FUNCNAME} $*"
local value=$1
case $value in
"0"|"balance-rr")
runner_add_opt "\"name\" : \"roundrobin\"" || return 1
;;
"1"|"active-backup")
runner_add_opt "\"name\" : \"activebackup\"" || return 1
;;
"2"|"balance-xor")
# FIXME
runner_add_opt "\"name\" : \"loadbalance\"" || return 1
;;
"3"|"broadcast")
runner_add_opt "\"name\" : \"broadcast\"" || return 1
;;
"4"|"802.3ad")
runner_add_opt "\"name\" : \"lacp\"" || return 1
;;
"5"|"balance-tlb")
runner_add_opt "\"name\" : \"loadbalance\"" || return 1
;;
"6"|"balance-alb")
pr_error "parameter mode=$value is not supported"
return 1
;;
*)
pr_error "parameter mode=$value is not supported"
return 1
;;
esac
}
runner_parse_opt()
{
pr_dbg "${FUNCNAME} $*"
local param=$1
local value=$2
case $param in
"ad_select")
runner_parse_adselect $value || return 1
;;
"fail_over_mac")
runner_parse_failovermac $value || return 1
;;
"lacp_rate")
runner_parse_lacprate $value || return 1
;;
"min_links")
runner_add_opt "\"min_ports\" : $value" || return 1
;;
"mode")
runner_parse_mode $value || return 1
;;
"xmit_hash_policy")
runner_parse_xmit_policy $value || return 1
;;
esac
}
# Link Watch functions
lwatch_add_opt()
{
pr_dbg "${FUNCNAME} $*"
local pos=${#LWATCH_OPTS[*]}
LWATCH_OPTS[${pos}]="$1"
}
lwatch_parse_arp_validate()
{
pr_dbg "${FUNCNAME} $*"
local value=$1
case $value in
"0"|"none")
;;
"1"|"active")
lwatch_add_opt "\"validate_active\" : 1" || return 1
;;
"2"|"backup")
lwatch_add_opt "\"validate_inactive\" : 1" || return 1
;;
"3"|"all")
lwatch_add_opt "\"validate_active\" : 1" || return 1
lwatch_add_opt "\"validate_inactive\" : 1" || return 1
;;
*)
pr_error "parameter arp_validate=$value is not supported"
return 1
;;
esac
}
lwatch_parse_arpiptarget()
{
#FIXME: supports only one arp_ip_target address.
# otherwise a new linkwatch section must be create
pr_dbg "${FUNCNAME} $*"
local ip_addrs=$1
local ip_list=${ip_addrs//,/ }
local ip_array=($ip_list)
if [ ${#ip_array[*]} -ne 1 ]; then
pr_error "parameter arp_ip_target= with multiple IP addresses is not supported"
return 1
fi
for addr in ${ip_list}
do
lwatch_add_opt "\"target_host\" : \"$addr\""
done
}
lwatch_parse_opt()
{
pr_dbg "${FUNCNAME} $*"
local param=$1
local value=$2
case $param in
"arp_interval")
lwatch_add_opt "\"interval\" : $value"
;;
"arp_ip_target")
lwatch_add_opt "\"name\" : \"arp_ping\""
if ! lwatch_parse_arpiptarget $value; then
return 1
fi
;;
"arp_validate")
lwatch_parse_arp_validate $value
;;
"downdelay")
lwatch_add_opt "\"delay_down\" : $value"
;;
"miimon")
lwatch_add_opt "\"name\" : \"ethtool\""
;;
"updelay")
lwatch_add_opt "\"delay_up\" : $value"
;;
*)
pr_error "parameter $param=$value is not supported"
return 1
;;
esac
}
port_parse_opt()
{
pr_dbg "${FUNCNAME} $*"
local param=$1
local value=$2
case $param in
"primary")
PRIMARY="$value"
;;
"primary_reselect")
case $value in
"0"|"always")
PRIMARY_RESELECT=1
;;
"1"|"better")
;;
"2"|"failure")
;;
*)
pr_error "parameter $param=$value is not supported"
return 1
esac
;;
*)
pr_error "parameter $param=$value is not supported"
return 1
;;
esac
}
convert_bond_opts()
{
local bonding_opts=$1
pr_dbg "${FUNCNAME} $*"
for arg in $bonding_opts
do
key=${arg%%=*};
value=${arg##*=};
pr_dbg "parsing $key=$value"
case "$key" in
"active_slave"|"max_bonds"|"use_carrier")
pr_info "parameter $key not supported, ignoring"
continue
;;
"all_slaves_active"|"resend_igmp"|"num_grat_arp"|"num_unsol_na")
pr_error "parameter $key not supported, aborting"
return 1
;;
"ad_select"|"fail_over_mac"|"lacp_rate"|"min_links"|"mode"|"xmit_hash_policy")
runner_parse_opt $key $value || return 1
;;
"arp_interval"|"arp_ip_target"|"arp_validate"|"downdelay"|"miimon"|"updelay")
lwatch_parse_opt $key $value || return 1
;;
"primary"|"primary_reselect")
port_parse_opt $key $value || return 1
;;
*)
pr_error "unknown parameter $key=$value, aborting"
return 1
;;
esac
done
}
# Parse command line options
while :;
do
case "$1" in
"--master")
MASTER="$2"
shift 2
;;
"--bonding_opts")
BONDING_OPTS="$2"
shift 2
;;
"--ifcfg")
OUTPUT_FORMAT=${FORMAT_IFCFG}
shift
;;
"--json")
OUTPUT_FORMAT=${FORMAT_JANSSON}
shift
;;
"--quiet")
PR_LVL=${PR_QUIET}
shift
;;
"--debug")
PR_LVL=`expr ${PR_LVL} + 1`
shift
;;
"--outputdir")
OUTPUT_DIR="$2"
shift 2
;;
"--configdir")
CONFIGDIR="$2"
shift 2
;;
"--rename")
[ -n "${RENAME}" ] && usage && exit 1
RENAME="$2"
shift 2
;;
"--stdout")
STDOUT=0
shift
;;
"--port")
PORT_LIST="${PORT_LIST} $2"
shift 2
;;
"--version")
echo "$VERSION"
exit 0
;;
"--help")
usage
exit 0
;;
"--examples")
show_examples
exit 0
;;
*)
if [ -z "$1" ]; then
break
fi
pr_error "unknown parameter: $1"
usage
exit 1
;;
esac
done
if [ -n "${OUTPUT_DIR}" -a ! -d "${OUTPUT_DIR}" ]; then
pr_error "Invalid output diretory: ${OUTPUT_DIR}"
usage
exit 1
fi
if [ -z "${MASTER}" -a -z "${BONDING_OPTS}" ]; then
pr_error "No master interface or bonding options specified"
usage
exit 1
fi
# no master means no ifcfg to read
if [ -z "${MASTER}" ]; then
MODE=${MODE_NOIFCFG}
fi
if [ ${OUTPUT_FORMAT} -eq ${FORMAT_JANSSON} -a -z "${MASTER}" ]; then
MASTER="team0"
fi
if ! ifcfg_get_master_file ${MASTER}; then
exit 1
fi
# load the ifcfg file
if ! vfile_load_ifcfg ${MASTER}; then
exit 1
fi
# get the bonding options
if ! ifcfg_get_bond_opts ${MASTER}; then
exit 1
fi
if ! convert_bond_opts "${BONDING_OPTS}"; then
exit 1
fi
if ! vfile_get_device; then
exit 1
fi
TEAM_MASTER=${DEVICE}
if ! ifcfg_device_rename ${DEVICE} ${RENAME}; then
exit 1
fi
BOND_MASTER=${DEVICE}
if [ ${OUTPUT_FORMAT} -eq ${FORMAT_IFCFG} ]; then
if ! team_master_ifcfg_create; then
exit 1
fi
if ! team_ifcfg_write ${TEAM_MASTER}; then
clean_up
exit 1
fi
# process all ports
for portcfg in $(LANG=C grep -s -l "^[[:space:]]*MASTER=\"\?${BOND_MASTER}\"\?\([[:space:]#]\|$\)" ${CONFIGDIR}/ifcfg-*)
do
if ! team_port_ifcfg_create $portcfg; then
clean_up
exit 1
fi
if ! team_ifcfg_write ${DEVICE}; then
clean_up
exit 1
fi
done
team_ifcfg_deliver
else
if ! teamd_config_create; then
exit 1
fi
if ! teamd_port_create; then
exit 1
fi
if [ -n "${PORT_LIST}" ]; then
portcfg_list=${PORT_LIST}
else
portcfg_list=$(LANG=C grep -s -l "^[[:space:]]*MASTER=\"\?${BOND_MASTER}\"\?\([[:space:]#]\|$\)" ${CONFIGDIR}/ifcfg-*)
fi
# count number of ports
portcfg_total=0
for portcfg in ${portcfg_list}
do
portcfg_total=$((${portcfg_total} + 1))
done
# process all ports
portcfg_nr=0
lastone=0
for portcfg in ${portcfg_list}
do
portcfg_nr=$((${portcfg_nr} + 1))
if [ ${portcfg_nr} -eq ${portcfg_total} ]; then
lastone=1
fi
if ! teamd_port_add ${portcfg} ${lastone}; then
exit 1
fi
done
if ! teamd_port_close; then
exit 1
fi
if ! teamd_config_close; then
exit 1
fi
if ! teamd_config_write; then
exit 1
fi
fi