| #! /usr/bin/env python |
| """ |
| Basic test. |
| |
| Copyright (C) 2012-2015 Jiri Pirko <jiri@resnulli.us> |
| |
| This library is free software; you can redistribute it and/or |
| modify it under the terms of the GNU Lesser General Public |
| License as published by the Free Software Foundation; either |
| version 2.1 of the License, or (at your option) any later version. |
| |
| This library 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 |
| Lesser General Public License for more details. |
| |
| You should have received a copy of the GNU Lesser General Public |
| License along with this library; if not, write to the Free Software |
| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| """ |
| |
| __author__ = """ |
| jiri@resnulli.us (Jiri Pirko) |
| """ |
| |
| import sys |
| import os |
| import getopt |
| import subprocess |
| |
| def usage(): |
| """ |
| Print usage of this app |
| """ |
| print "Usage: team_basic_test.py [OPTION...]" |
| print "" |
| print " -h, --help print this message" |
| print " -c, --loop-count=NUMBER number of loops (default 1)" |
| print " -p, --port=NETDEV port device (can be defined multiple times)" |
| sys.exit() |
| |
| class CmdExecFailedException(Exception): |
| def __init__(self, retval): |
| self.__retval = retval |
| |
| def __str__(self): |
| return "Command execution failed: %s" % self.__retval |
| |
| class CmdExecUnexpectedOutputException(Exception): |
| def __init__(self, output, expected_output): |
| self.__output = output |
| self.__expected_output = expected_output |
| |
| def __str__(self): |
| return "Command execution output unexpected: \"%s\" != \"%s\"" % (self.__output, self.__expected_output) |
| |
| def print_output(out_type, string): |
| print("%s:\n" |
| "----------------------------\n" |
| "%s" |
| "----------------------------" % (out_type, string)) |
| |
| def cmd_exec(cmd, expected_output=None, cleaner=False): |
| cmd = cmd.rstrip(" ") |
| if not cleaner: |
| print("# \"%s\"" % cmd) |
| subp = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, |
| stderr=subprocess.PIPE) |
| (data_stdout, data_stderr) = subp.communicate() |
| |
| if subp.returncode and not cleaner: |
| if data_stdout: |
| print_output("Stdout", data_stdout) |
| if data_stderr: |
| print_output("Stderr", data_stderr) |
| raise CmdExecFailedException(subp.returncode) |
| output = data_stdout.rstrip() |
| if expected_output: |
| if output != expected_output: |
| raise CmdExecUnexpectedOutputException(output, expected_output) |
| return output |
| |
| class TeamBasicTest: |
| def __init__(self): |
| self._team_dev_name = "testteamx" |
| self._team_modes = ["broadcast", "roundrobin", "activebackup", "loadbalance"] |
| self._loop_count = 1 |
| self._port_names = [] |
| |
| def set_loop_count(self, new_loop_count): |
| self._loop_count = new_loop_count |
| |
| def port_add(self, port_name): |
| self._port_names.append(port_name) |
| |
| def _run_one_mode(self, mode_name): |
| team_name = self._team_dev_name |
| cmd_exec("ip link add %s type team" % team_name) |
| try: |
| self._created_teams.append(team_name) |
| cmd_exec("teamnl %s getoption mode" % team_name, "*NOMODE*") |
| cmd_exec("teamnl %s setoption mode %s" % (team_name, mode_name)) |
| cmd_exec("teamnl %s getoption mode" % team_name, mode_name) |
| |
| for port_name in self._port_names: |
| cmd_exec("ip link set %s down" % port_name) |
| cmd_exec("ip link set %s master %s" % (port_name, team_name)) |
| |
| cmd_exec("ip link set %s up" % team_name) |
| cmd_exec("ip addr add 192.168.241.231/24 dev %s" % team_name) |
| cmd_exec("ip link set %s down" % team_name) |
| cmd_exec("ip addr flush dev %s" % team_name) |
| |
| cmd_exec("teamnl %s options" % team_name) |
| cmd_exec("teamnl %s ports" % team_name) |
| |
| for port_name in self._port_names: |
| cmd_exec("ip link set %s nomaster" % port_name) |
| finally: |
| cmd_exec("ip link del %s" % team_name) |
| |
| def _create_team_initscript(self): |
| f = open("/etc/sysconfig/network-scripts/ifcfg-%s" % self._team_dev_name, "w") |
| f.write( |
| """ |
| DEVICE="%s" |
| DEVICETYPE="Team" |
| ONBOOT="no" |
| BOOTPROTO=none |
| NETMASK=255.255.255.0 |
| IPADDR=192.168.241.231 |
| TEAM_CONFIG='{"runner": {"name": "activebackup"}}' |
| """ % self._team_dev_name) |
| f.close() |
| cmd_exec("ifup %s" % self._team_dev_name) |
| |
| def _create_port_initscript(self, port_name): |
| f = open("/etc/sysconfig/network-scripts/ifcfg-%s" % port_name, "w") |
| f.write( |
| """ |
| DEVICE="%s" |
| DEVICETYPE="TeamPort" |
| ONBOOT="yes" |
| TEAM_MASTER="%s" |
| TEAM_PORT_CONFIG='{"prio": 10}' |
| """ % (port_name, self._team_dev_name)) |
| f.close() |
| cmd_exec("ifup %s" % port_name) |
| |
| def _run_teamd_initscripts(self): |
| os.makedirs("/tmp/team_test/") |
| try: |
| ifcfg_files = " ".join(["ifcfg-%s" % port_name for port_name in self._port_names]) |
| cmd_exec("tar --ignore-failed-read -C /etc/sysconfig/network-scripts/ -cf /tmp/team_test/initscripts_bkp.tar %s" % ifcfg_files) |
| self._create_team_initscript() |
| for port_name in self._port_names: |
| self._create_port_initscript(port_name) |
| cmd_exec("ifdown %s" % self._team_dev_name) |
| except: |
| cmd_exec("ifdown %s" % self._team_dev_name, cleaner=True) |
| cmd_exec("ip link del %s" % self._team_dev_name, cleaner=True) |
| raise |
| finally: |
| cmd_exec("tar -C /etc/sysconfig/network-scripts/ -xf /tmp/team_test/initscripts_bkp.tar") |
| os.unlink("/tmp/team_test/initscripts_bkp.tar") |
| os.removedirs("/tmp/team_test/") |
| |
| def _run_one_loop(self, run_nr): |
| print "RUN #%d" % (run_nr) |
| self._created_teams = [] |
| try: |
| for mode_name in self._team_modes: |
| self._run_one_mode(mode_name) |
| self._run_teamd_initscripts() |
| finally: |
| cmd_exec("modprobe -r team_mode_loadbalance team_mode_roundrobin team_mode_activebackup team_mode_broadcast team"); |
| |
| def run(self): |
| for i in xrange(self._loop_count): |
| self._run_one_loop(i + 1) |
| |
| def main(): |
| try: |
| opts, args = getopt.getopt( |
| sys.argv[1:], |
| "hc:p:", |
| ["help", "loop-count=", "port="] |
| ) |
| except getopt.GetoptError, err: |
| print str(err) |
| usage() |
| |
| btest = TeamBasicTest() |
| |
| for opt, arg in opts: |
| if opt in ("-h", "--help"): |
| usage() |
| elif opt in ("-c", "--loop-count"): |
| btest.set_loop_count(int(arg)) |
| elif opt in ("-p", "--port"): |
| btest.port_add(arg) |
| |
| btest.run() |
| |
| if __name__ == "__main__": |
| main() |