<p>pespin has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-gsm-tester/+/17134">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">iperf3: Support running iperf3 remotely<br><br>The new RunNode class is used and ip_address support will be dropped<br>eventually, replaced by the former.<br><br>Change-Id: Ib803d7774cb502c7d07443d7720a7b013684faa8<br>---<br>M src/osmo_gsm_tester/iperf3.py<br>1 file changed, 103 insertions(+), 10 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-gsm-tester refs/changes/34/17134/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/osmo_gsm_tester/iperf3.py b/src/osmo_gsm_tester/iperf3.py</span><br><span>index 55cb546..2038daa 100644</span><br><span>--- a/src/osmo_gsm_tester/iperf3.py</span><br><span>+++ b/src/osmo_gsm_tester/iperf3.py</span><br><span>@@ -20,7 +20,7 @@</span><br><span> import os</span><br><span> import json</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from . import log, util, process, pcap_recorder</span><br><span style="color: hsl(120, 100%, 40%);">+from . import log, util, process, pcap_recorder, run_node, remote</span><br><span> </span><br><span> def iperf3_result_to_json(file):</span><br><span>     with open(file) as f:</span><br><span>@@ -35,32 +35,77 @@</span><br><span> class IPerf3Server(log.Origin):</span><br><span> </span><br><span>     DEFAULT_SRV_PORT = 5003</span><br><span style="color: hsl(120, 100%, 40%);">+    LOGFILE = 'iperf3_srv.json'</span><br><span style="color: hsl(120, 100%, 40%);">+    REMOTE_DIR = '/tmp'</span><br><span> </span><br><span>     def __init__(self, suite_run, ip_address):</span><br><span>         super().__init__(log.C_RUN, 'iperf3-srv_%s' % ip_address.get('addr'))</span><br><span>         self.run_dir = None</span><br><span style="color: hsl(0, 100%, 40%);">-        self.config_file = None</span><br><span>         self.process = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self._run_node = None</span><br><span>         self.suite_run = suite_run</span><br><span>         self.ip_address = ip_address</span><br><span>         self._port = IPerf3Server.DEFAULT_SRV_PORT</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_log_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log_copied = False</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def cleanup(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.process is None:</span><br><span style="color: hsl(120, 100%, 40%);">+            return</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.runs_locally():</span><br><span style="color: hsl(120, 100%, 40%);">+            return</span><br><span style="color: hsl(120, 100%, 40%);">+        # copy back files (may not exist, for instance if there was an early error of process):</span><br><span style="color: hsl(120, 100%, 40%);">+        try:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.rem_host.scpfrom('scp-back-log', self.remote_log_file, self.log_file)</span><br><span style="color: hsl(120, 100%, 40%);">+        except Exception as e:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.log(repr(e))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def runs_locally(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        locally = not self._run_node or self._run_node.is_local()</span><br><span style="color: hsl(120, 100%, 40%);">+        return locally</span><br><span> </span><br><span>     def start(self):</span><br><span>         self.log('Starting iperf3-srv')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log_copied = False</span><br><span>         self.run_dir = util.Dir(self.suite_run.get_test_run_dir().new_dir(self.name()))</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log_file = self.run_dir.new_file(IPerf3Server.LOGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.runs_locally():</span><br><span style="color: hsl(120, 100%, 40%);">+            self.start_locally()</span><br><span style="color: hsl(120, 100%, 40%);">+        else:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.start_remotely()</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+    def start_remotely(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host = remote.RemoteHost(self.run_dir, self._run_node.ssh_user(), self._run_node.ssh_addr())</span><br><span style="color: hsl(120, 100%, 40%);">+        remote_prefix_dir = util.Dir(IPerf3Server.REMOTE_DIR)</span><br><span style="color: hsl(120, 100%, 40%);">+        remote_run_dir = util.Dir(remote_prefix_dir.child('srv-' + str(self)))</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_log_file = remote_run_dir.child(IPerf3Server.LOGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.recreate_remote_dir(remote_run_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        args = ('iperf3', '-s', '-B', self.addr(),</span><br><span style="color: hsl(120, 100%, 40%);">+                '-p', str(self._port), '-J',</span><br><span style="color: hsl(120, 100%, 40%);">+                '--logfile', self.remote_log_file)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.process = self.rem_host.RemoteProcess(self.name(), args)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.suite_run.remember_to_stop(self.process)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.process.launch()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def start_locally(self):</span><br><span>         pcap_recorder.PcapRecorder(self.suite_run, self.run_dir.new_dir('pcap'), None,</span><br><span>                                    'host %s and port not 22' % self.addr())</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        self.log_file = self.run_dir.new_file('iperf3_srv.json')</span><br><span style="color: hsl(0, 100%, 40%);">-        self.process = process.Process(self.name(), self.run_dir,</span><br><span style="color: hsl(0, 100%, 40%);">-                                       ('iperf3', '-s', '-B', self.addr(),</span><br><span style="color: hsl(0, 100%, 40%);">-                                        '-p', str(self._port), '-J',</span><br><span style="color: hsl(0, 100%, 40%);">-                                        '--logfile', os.path.abspath(self.log_file)),</span><br><span style="color: hsl(0, 100%, 40%);">-                                       env={})</span><br><span style="color: hsl(120, 100%, 40%);">+        args = ('iperf3', '-s', '-B', self.addr(),</span><br><span style="color: hsl(120, 100%, 40%);">+                '-p', str(self._port), '-J',</span><br><span style="color: hsl(120, 100%, 40%);">+                '--logfile', os.path.abspath(self.log_file))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.process = process.Process(self.name(), self.run_dir, args, env={})</span><br><span>         self.suite_run.remember_to_stop(self.process)</span><br><span>         self.process.launch()</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+    def set_run_node(self, run_node):</span><br><span style="color: hsl(120, 100%, 40%);">+        self._run_node = run_node</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>     def set_port(self, port):</span><br><span>         self._port = port</span><br><span> </span><br><span>@@ -68,6 +113,9 @@</span><br><span>         self.suite_run.stop_process(self.process)</span><br><span> </span><br><span>     def get_results(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        if not self.runs_locally() and not self.log_copied:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.rem_host.scpfrom('scp-back-log', self.remote_log_file, self.log_file)</span><br><span style="color: hsl(120, 100%, 40%);">+            self.log_copied = True</span><br><span>         return iperf3_result_to_json(self.log_file)</span><br><span> </span><br><span>     def addr(self):</span><br><span>@@ -87,22 +135,57 @@</span><br><span> </span><br><span> class IPerf3Client(log.Origin):</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+    REMOTE_DIR = '/tmp'</span><br><span style="color: hsl(120, 100%, 40%);">+    LOGFILE = 'iperf3_cli.json'</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>     def __init__(self, suite_run, iperf3srv):</span><br><span>         super().__init__(log.C_RUN, 'iperf3-cli_%s' % iperf3srv.addr())</span><br><span>         self.run_dir = None</span><br><span style="color: hsl(0, 100%, 40%);">-        self.config_file = None</span><br><span>         self.process = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self._run_node = None</span><br><span>         self.server = iperf3srv</span><br><span>         self.suite_run = suite_run</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_log_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log_copied = False</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def runs_locally(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        locally = not self._run_node or self._run_node.is_local()</span><br><span style="color: hsl(120, 100%, 40%);">+        return locally</span><br><span> </span><br><span>     def prepare_test_proc(self, netns=None):</span><br><span>         self.log('Starting iperf3-client connecting to %s:%d' % (self.server.addr(), self.server.port()))</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log_copied = False</span><br><span>         self.run_dir = util.Dir(self.suite_run.get_test_run_dir().new_dir(self.name()))</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log_file = self.run_dir.new_file(IPerf3Client.LOGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.runs_locally():</span><br><span style="color: hsl(120, 100%, 40%);">+            return self.prepare_test_proc_locally()</span><br><span style="color: hsl(120, 100%, 40%);">+        else:</span><br><span style="color: hsl(120, 100%, 40%);">+            return self.prepare_test_proc_remotely()</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+    def prepare_test_proc_remotely(self, netns=None):</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host = remote.RemoteHost(self.run_dir, self._run_node.ssh_user(), self._run_node.ssh_addr())</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        remote_prefix_dir = util.Dir(IPerf3Client.REMOTE_DIR)</span><br><span style="color: hsl(120, 100%, 40%);">+        remote_run_dir = util.Dir(remote_prefix_dir.child('cli-' + str(self)))</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_log_file = remote_run_dir.child(IPerf3Client.LOGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.recreate_remote_dir(remote_run_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        popen_args = ('iperf3', '-c',  self.server.addr(),</span><br><span style="color: hsl(120, 100%, 40%);">+                      '-p', str(self.server.port()), '-J',</span><br><span style="color: hsl(120, 100%, 40%);">+                      '--logfile', self.remote_log_file)</span><br><span style="color: hsl(120, 100%, 40%);">+        if netns:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.process = self.rem_host.RemoteNetNSProcess(self.name(), netns, popen_args, env={})</span><br><span style="color: hsl(120, 100%, 40%);">+        else:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.process = self.rem_host.RemoteProcess(self.name(), popen_args, env={})</span><br><span style="color: hsl(120, 100%, 40%);">+        return self.process</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def prepare_test_proc_locally(self, netns=None):</span><br><span>         pcap_recorder.PcapRecorder(self.suite_run, self.run_dir.new_dir('pcap'), None,</span><br><span>                                    'host %s and port not 22' % self.server.addr(), netns)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        self.log_file = self.run_dir.new_file('iperf3_cli.json')</span><br><span>         popen_args = ('iperf3', '-c',  self.server.addr(),</span><br><span>                       '-p', str(self.server.port()), '-J',</span><br><span>                       '--logfile', os.path.abspath(self.log_file))</span><br><span>@@ -118,6 +201,16 @@</span><br><span>         return self.get_results()</span><br><span> </span><br><span>     def get_results(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        if not self.runs_locally() and not self.log_copied:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.rem_host.scpfrom('scp-back-log', self.remote_log_file, self.log_file)</span><br><span style="color: hsl(120, 100%, 40%);">+            self.log_copied = True</span><br><span>         return iperf3_result_to_json(self.log_file)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+    def set_run_node(self, run_node):</span><br><span style="color: hsl(120, 100%, 40%);">+        self._run_node = run_node</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def __str__(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        # FIXME: somehow differentiate between several clients connected to same server?</span><br><span style="color: hsl(120, 100%, 40%);">+        return "%s:%u" %(self.server.addr(), self.server.port())</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> # vim: expandtab tabstop=4 shiftwidth=4</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-gsm-tester/+/17134">change 17134</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-gsm-tester/+/17134"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-gsm-tester </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Ib803d7774cb502c7d07443d7720a7b013684faa8 </div>
<div style="display:none"> Gerrit-Change-Number: 17134 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>