Ido Barkan has uploaded a new change for review.
Change subject: net: tests: support iperf3 for performance tests
......................................................................
net: tests: support iperf3 for performance tests
Support running iperf3 client server using context managers in an
optional network namespace. This is handy for performance testing on
a single machine. TC qos tests following patches use it.
Change-Id: I15657f8844d131c5444dd680b8de7aa1c4ec2638
Signed-off-by: Ido Barkan <ibarkan(a)redhat.com>
---
M configure.ac
M lib/vdsm/constants.py.in
M tests/nettestlib.py
3 files changed, 92 insertions(+), 3 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/48/46448/1
diff --git a/configure.ac b/configure.ac
index 88817a8..1fee53c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -285,6 +285,7 @@
AC_PATH_PROG([IFUP_PATH], [ifup], [/sbin/ifup])
AC_PATH_PROG([IONICE_PATH], [ionice], [/usr/bin/ionice])
AC_PATH_PROG([IP_PATH], [ip], [/sbin/ip])
+AC_PATH_PROG([IPERF3_PATH], [iperf3], [/usr/bin/iperf3])
AC_PATH_PROG([ISCSIADM_PATH], [iscsiadm], [/sbin/iscsiadm])
AC_PATH_PROG([KILL_PATH], [kill], [/bin/kill])
AC_PATH_PROG([LVM_PATH], [lvm], [/sbin/lvm])
diff --git a/lib/vdsm/constants.py.in b/lib/vdsm/constants.py.in
index c9dff39..d4adac9 100644
--- a/lib/vdsm/constants.py.in
+++ b/lib/vdsm/constants.py.in
@@ -117,6 +117,7 @@
EXT_IFDOWN = '@IFDOWN_PATH@'
EXT_IFUP = '@IFUP_PATH@'
EXT_IONICE = '@IONICE_PATH@'
+EXT_IPERF3 = '@IPERF3_PATH@'
EXT_ISCSIADM = '@ISCSIADM_PATH@'
EXT_TC = '@TC_PATH@'
diff --git a/tests/nettestlib.py b/tests/nettestlib.py
index c923f44..d019778 100644
--- a/tests/nettestlib.py
+++ b/tests/nettestlib.py
@@ -20,6 +20,7 @@
import errno
import fcntl
import functools
+import json
import os
import platform
import signal
@@ -28,13 +29,17 @@
from multiprocessing import Process
from nose.plugins.skip import SkipTest
+import time
-from vdsm.constants import EXT_BRCTL, EXT_TC
-from vdsm.ipwrapper import addrAdd, linkSet, linkAdd, linkDel, IPRoute2Error
+from vdsm.constants import EXT_BRCTL, EXT_TC, EXT_IPERF3
+from vdsm.ipwrapper import addrAdd, linkSet, linkAdd, linkDel, IPRoute2Error, \
+ netns_add, netns_delete
from vdsm.netlink import monitor
-from vdsm.utils import execCmd, random_iface_name
+from vdsm.utils import (execCmd, random_iface_name, pgrep, kill_and_rm_pid,
+ CommandPath)
EXT_IP = "/sbin/ip"
+_IPERF3_BINARY = CommandPath('iperf3', EXT_IPERF3)
class ExecError(RuntimeError):
@@ -237,6 +242,70 @@
raise SkipTest(message)
+class _Iperf(object):
+ @staticmethod
+ def stop():
+ pids = pgrep(_IPERF3_BINARY.name)
+ for pid in pids:
+ kill_and_rm_pid(pid, pid_file=None)
+
+
+class IperfServer(_Iperf):
+ """starts iperf as a daemon"""
+ def __init__(self, host, network_ns=None):
+ """host: the IP address for the server to listen on.
+ network_ns: an optional network namespace for the server to run in.
+ """
+ self._bind_to = host
+ self._net_ns = network_ns
+
+ def start(self):
+ cmd = [EXT_IPERF3, '--server', '--bind', self._bind_to,
'--daemon']
+ if self._net_ns is not None:
+ cmd = ['ip', 'netns', 'exec', self._net_ns] + cmd
+ rc, out, err = execCmd(cmd)
+ return rc
+
+
+class IperfClient(_Iperf):
+ def __init__(self, server_ip, bind_to, test_time, threads=1):
+ """the client generate a machine readable json output that is set
in
+ _raw_output upon completion, ANd can be read using the 'out' property.
+ server_ip: the ip of the corresponding iperf server
+ bind_to: IP address of the client
+ test_time: in seconds
+ """
+ self._server_ip = server_ip
+ self._bind_to = bind_to
+ self._test_time = test_time
+ self._threads = threads
+ self._raw_output = None
+
+ def start(self):
+ cmd = [EXT_IPERF3, '--client', self._server_ip,
+ '--version4', # only IPv4
+ '--time', str(self._test_time), '--parallel',
+ str(self._threads), '--bind', self._bind_to,
+ '--zerocopy', # use less cpu
+ '--json']
+ rc, self._raw_output, err = execCmd(cmd)
+ if rc == 1 and 'No route to host' in self.error:
+ time.sleep(3)
+ rc, self._raw_output, err = execCmd(cmd)
+ if rc:
+ raise Exception('iperf3 client failed: cmd=%s, rc=%s, out=%s, '
+ 'err=%s' % (' '.join(cmd), rc,
self._raw_output,
+ err))
+
+ @property
+ def error(self):
+ return self.out['error']
+
+ @property
+ def out(self):
+ return json.loads(' '.join(self._raw_output))
+
+
@contextmanager
def dummy_device(prefix='dummy_', max_length=11):
dummy_interface = Dummy(prefix, max_length)
@@ -304,3 +373,21 @@
check_tc()
return f(*a, **kw)
return wrapper
+
+
+def check_iperf():
+ try:
+ execCmd([_IPERF3_BINARY.cmd, "--version"])
+ except OSError as e:
+ if e.errno == errno.ENOENT:
+ raise SkipTest("Cannot run %r: %s\nDo you have iperf3 installed?"
+ % (_IPERF3_BINARY.cmd, e))
+ raise
+
+
+def requires_iperf3(f):
+ @functools.wraps(f)
+ def wrapper(*a, **kw):
+ check_iperf()
+ return f(*a, **kw)
+ return wrapper
--
To view, visit
https://gerrit.ovirt.org/46448
To unsubscribe, visit
https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I15657f8844d131c5444dd680b8de7aa1c4ec2638
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Ido Barkan <ibarkan(a)redhat.com>