The first patch adds the tool and its man-page. The second patch changes the spec file to install them.
Flavio Leitner (1): utils: add bond2team conversion tool
man/bond2team.1 | 92 ++++ utils/bond2team | 1309 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1401 insertions(+) create mode 100644 man/bond2team.1 create mode 100755 utils/bond2team
The tool converts bonding configuration using ifcfg file or given options in the command line to team configuration maintaining the same functionality as much as possible.
The output can be selected between ifcfg format (default) or JSON format (teamd.conf).
There are some examples in the man-page and a few more when passing --examples option to the tool.
Signed-off-by: Flavio Leitner fbl@redhat.com --- man/bond2team.1 | 92 ++++ utils/bond2team | 1309 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1401 insertions(+) create mode 100644 man/bond2team.1 create mode 100755 utils/bond2team
diff --git a/man/bond2team.1 b/man/bond2team.1 new file mode 100644 index 0000000..0262564 --- /dev/null +++ b/man/bond2team.1 @@ -0,0 +1,92 @@ +.TH BOND2TEAM 1 "2013-07-18" "libteam" "Bonding to Team conversion tool" +.SH NAME +bond2team (em Converts bonding configuration to team +.SH SYNOPSIS +.B bond2team +.RB [options] +.SH DESCRIPTION +.PP +bond2team is a tool to convert bonding options to team trying as much as possible to keep the original functionality. +.PP +The resulted files are saved in a temporary directory using ifcfg style by default. In the case of converting a ifcfg file, it translates the bonding options to team preserving all other options. In that case, it converts the respective slave ifcfg files to team port preserving all their other options too. In case of converting from given bonding options in the command line, the tool can use the specified ports as team ports. +.SH OPTIONS +.TP +.B "--master <interface>" +Specify the interface name or ifcfg file to convert. If the interface name is specified, the tool will look at %/etc/sysconfig/network-scripts/ for the respective ifcfg file. +.TP +.B "--rename <interface>" +This is a convenient option to replace the original interface name by the specified name. For instance, if --master specifies bond0, it is possible to use --rename team0 to change the final interface name to team0. +.TP +.B --ifcfg +Set the output format to ifcfg config style. [default] +.TP +.B --json +Set the output format to JSON style. See +.BR teamd.conf (5) +for further details. +.TP +.B "--bonding_opts '<bonding options>'" +Specify the bonding options to be converted instead of reading them from the ifcfg file. +.TP +.B "--port <interface>" +Set the specified interface as a team port. +.TP +.B "--configdir <directory>" +Change the ifcfg configuration path from %/etc/sysconfig/network-scripts to the specified <directory>. +.TP +.B "--outputdir <directory>" +Set the output directory to <directory>. +.TP +.B "--stdout" +Print the result to the screen instead of writing to files. +.TP +.B "--debug" +Increase the debugging level. +.TP +.B "--quiet" +Disallow any messages to be printed to console. +.TP +.B "--version" +Print tool version to console and exit. +.TP +.B "--help" +Print help text to console and exit. +.TP +.B "--examples" +Print common usage examples to console and exit. +.SH EXAMPLES +.PP +To convert the current 'bond0' ifcfg configuration to team ifcfg: +.TP +.nf +# bond2team %--master %bond0 +.fi +.PP +To convert the current 'bond0' ifcfg configuration to team ifcfg renaming the interface name to 'team0'. +.B Caution +: firewall rules, aliases interfaces, etc., that might be tied to the original interface name can break after the renaming because the tool will only change the ifcfg file, nothing else. +.PP +.nf +# bond2team %--master %bond0 %--rename %team0 +.fi +.PP +To convert given bonding parameters with ports without any ifcfg: +.PP +.ni +# bond2team --bonding_opts '%mode=1 %miimon=500 %primary=eth1 %primary_reselect=0' %--port %eth1 %--port %eth2 %--port %eth3 %--port %eth4 +.fi +.PP +For more examples, see the option +.B --examples. +.SH CAVEATS +.PP +The tool will not convert any other configuration which might be tied to the current setup. For instance, firewall rules, aliases interfaces, bridges, and etc. +.SH AUTHOR +.PP +Flavio Leitner is the original author of the tool. +Jiri Pirko is the original author and current maintainer of libteam. +.SH SEE ALSO +.BR teamd (8), +.BR teamdctl (8), +.BR teamd.conf (5), +.BR teamnl (8) diff --git a/utils/bond2team b/utils/bond2team new file mode 100755 index 0000000..639b407 --- /dev/null +++ b/utils/bond2team @@ -0,0 +1,1309 @@ +#!/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|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"" + source_host=$(vfile_get_ipaddr) + if [ -z ${source_host} ]; then + pr_warn "could not find the source IP address required" + pr_warn "to convert arp_ip_target= parameter" + pr_warn "please fix the source_host parameter in the master ifcfg file" + lwatch_add_opt ""source_host" : "$addr"" + else + lwatch_add_opt ""source_host" : "$source_host"" + fi + 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
Signed-off-by: Flavio Leitner fbl@redhat.com
--- SPECS/libteam.spec.old 2013-06-11 07:39:55.000000000 -0300 +++ SPECS/libteam.spec 2013-07-19 16:49:09.479084713 -0300 @@ -92,6 +92,9 @@ install -p -m 755 teamd/redhat/initscrip install -p -m 755 teamd/redhat/initscripts_systemd/network-scripts/ifdown-Team $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/network-scripts install -p -m 755 teamd/redhat/initscripts_systemd/network-scripts/ifup-TeamPort $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/network-scripts install -p -m 755 teamd/redhat/initscripts_systemd/network-scripts/ifdown-TeamPort $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/network-scripts +install -p -m 755 utils/bond2team $RPM_BUILD_ROOT%{_bindir}/bond2team +mkdir -p $RPM_BUILD_ROOT%{_mandir}/man1 +install -p -m 644 man/bond2team.1* $RPM_BUILD_ROOT%{_mandir}/man1/ cd binding/python python ./setup.py install --root $RPM_BUILD_ROOT -O1
@@ -122,9 +125,11 @@ python ./setup.py install --root $RPM_BU %{_libdir}/libteamdctl.so.* %{_bindir}/teamd %{_bindir}/teamdctl +%{_bindir}/bond2team %{_mandir}/man8/teamd.8* %{_mandir}/man8/teamdctl.8* %{_mandir}/man5/teamd.conf.5* +%{_mandir}/man1/bond2team.1*
%files -n teamd-devel %doc COPYING
will apply this to Fedora git once I update teamd package. Thanks.
Fri, Jul 19, 2013 at 10:35:47PM CEST, fbl@redhat.com wrote:
Signed-off-by: Flavio Leitner fbl@redhat.com
--- SPECS/libteam.spec.old 2013-06-11 07:39:55.000000000 -0300 +++ SPECS/libteam.spec 2013-07-19 16:49:09.479084713 -0300 @@ -92,6 +92,9 @@ install -p -m 755 teamd/redhat/initscrip install -p -m 755 teamd/redhat/initscripts_systemd/network-scripts/ifdown-Team $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/network-scripts install -p -m 755 teamd/redhat/initscripts_systemd/network-scripts/ifup-TeamPort $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/network-scripts install -p -m 755 teamd/redhat/initscripts_systemd/network-scripts/ifdown-TeamPort $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/network-scripts +install -p -m 755 utils/bond2team $RPM_BUILD_ROOT%{_bindir}/bond2team +mkdir -p $RPM_BUILD_ROOT%{_mandir}/man1 +install -p -m 644 man/bond2team.1* $RPM_BUILD_ROOT%{_mandir}/man1/ cd binding/python python ./setup.py install --root $RPM_BUILD_ROOT -O1
@@ -122,9 +125,11 @@ python ./setup.py install --root $RPM_BU %{_libdir}/libteamdctl.so.* %{_bindir}/teamd %{_bindir}/teamdctl +%{_bindir}/bond2team %{_mandir}/man8/teamd.8* %{_mandir}/man8/teamdctl.8* %{_mandir}/man5/teamd.conf.5* +%{_mandir}/man1/bond2team.1*
%files -n teamd-devel %doc COPYING _______________________________________________ libteam mailing list libteam@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/libteam
On Sat, Jul 20, 2013 at 11:12:09AM +0200, Jiri Pirko wrote:
will apply this to Fedora git once I update teamd package. Thanks.
Sounds good, thanks!
fbl
Fri, Jul 19, 2013 at 10:35:47PM CEST, fbl@redhat.com wrote:
Signed-off-by: Flavio Leitner fbl@redhat.com
--- SPECS/libteam.spec.old 2013-06-11 07:39:55.000000000 -0300 +++ SPECS/libteam.spec 2013-07-19 16:49:09.479084713 -0300 @@ -92,6 +92,9 @@ install -p -m 755 teamd/redhat/initscrip install -p -m 755 teamd/redhat/initscripts_systemd/network-scripts/ifdown-Team $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/network-scripts install -p -m 755 teamd/redhat/initscripts_systemd/network-scripts/ifup-TeamPort $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/network-scripts install -p -m 755 teamd/redhat/initscripts_systemd/network-scripts/ifdown-TeamPort $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/network-scripts +install -p -m 755 utils/bond2team $RPM_BUILD_ROOT%{_bindir}/bond2team +mkdir -p $RPM_BUILD_ROOT%{_mandir}/man1 +install -p -m 644 man/bond2team.1* $RPM_BUILD_ROOT%{_mandir}/man1/ cd binding/python python ./setup.py install --root $RPM_BUILD_ROOT -O1
@@ -122,9 +125,11 @@ python ./setup.py install --root $RPM_BU %{_libdir}/libteamdctl.so.* %{_bindir}/teamd %{_bindir}/teamdctl +%{_bindir}/bond2team %{_mandir}/man8/teamd.8* %{_mandir}/man8/teamdctl.8* %{_mandir}/man5/teamd.conf.5* +%{_mandir}/man1/bond2team.1*
%files -n teamd-devel %doc COPYING _______________________________________________ libteam mailing list libteam@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/libteam
libteam mailing list libteam@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/libteam
libteam@lists.fedorahosted.org