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 <[email protected]>
---
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 <[email protected]>
_______________________________________________
vdsm-patches mailing list
[email protected]
https://lists.fedorahosted.org/mailman/listinfo/vdsm-patches

Reply via email to