<p>pespin has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-gsm-tester/+/17810">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">iperf3: Avoid using --logfile arg<br><br>Some older iperf3 versions don't support the --logfile arg. Let's<br>instead parse the json from stdout. Old --logfile behavior is left in<br>code but disabled since it's a nicer (less hacky) way to get results,<br>because parsing from stdout means we need to avoid reading some content.<br><br>Change-Id: Ia1b7fa4dae074089878963aeddf0006aea68e31f<br>---<br>M src/osmo_gsm_tester/obj/iperf3.py<br>1 file changed, 44 insertions(+), 23 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/10/17810/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/osmo_gsm_tester/obj/iperf3.py b/src/osmo_gsm_tester/obj/iperf3.py</span><br><span>index d2e9c36..9427770 100644</span><br><span>--- a/src/osmo_gsm_tester/obj/iperf3.py</span><br><span>+++ b/src/osmo_gsm_tester/obj/iperf3.py</span><br><span>@@ -23,14 +23,20 @@</span><br><span> from ..core import log, util, config, process, remote</span><br><span> from . import pcap_recorder, run_node</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-def iperf3_result_to_json(file):</span><br><span style="color: hsl(0, 100%, 40%);">-    with open(file) as f:</span><br><span style="color: hsl(0, 100%, 40%);">-            # Sometimes iperf3 provides 2 dictionaries, the 2nd one being an error about being interrupted (by us).</span><br><span style="color: hsl(0, 100%, 40%);">-            # json parser doesn't support (raises exception) parsing several dictionaries at a time (not a valid json object).</span><br><span style="color: hsl(0, 100%, 40%);">-            # We are only interested in the first dictionary, the regular results one:</span><br><span style="color: hsl(0, 100%, 40%);">-            d = f.read().split("\n}\n")[0] + "\n}\n"</span><br><span style="color: hsl(0, 100%, 40%);">-            data = json.loads(d)</span><br><span style="color: hsl(0, 100%, 40%);">-    return data</span><br><span style="color: hsl(120, 100%, 40%);">+def iperf3_result_to_json(log_obj, data):</span><br><span style="color: hsl(120, 100%, 40%);">+    try:</span><br><span style="color: hsl(120, 100%, 40%);">+        # Drop non-interesting self-generated output before json:</span><br><span style="color: hsl(120, 100%, 40%);">+        if not data.startswith('{\n'):</span><br><span style="color: hsl(120, 100%, 40%);">+            data = "{\n" + data.split("\n{\n")[1]</span><br><span style="color: hsl(120, 100%, 40%);">+        # Sometimes iperf3 provides 2 dictionaries, the 2nd one being an error about being interrupted (by us).</span><br><span style="color: hsl(120, 100%, 40%);">+        # json parser doesn't support (raises exception) parsing several dictionaries at a time (not a valid json object).</span><br><span style="color: hsl(120, 100%, 40%);">+        # We are only interested in the first dictionary, the regular results one:</span><br><span style="color: hsl(120, 100%, 40%);">+        data = data.split("\n}")[0] + "\n}"</span><br><span style="color: hsl(120, 100%, 40%);">+        j = json.loads(data)</span><br><span style="color: hsl(120, 100%, 40%);">+        return j</span><br><span style="color: hsl(120, 100%, 40%);">+    except Exception as e:</span><br><span style="color: hsl(120, 100%, 40%);">+        log_obj.log('failed parsing iperf3 output: "%s"' % data)</span><br><span style="color: hsl(120, 100%, 40%);">+        raise e</span><br><span> </span><br><span> </span><br><span> class IPerf3Server(log.Origin):</span><br><span>@@ -51,11 +57,12 @@</span><br><span>         self.rem_host = None</span><br><span>         self.remote_log_file = None</span><br><span>         self.log_copied = False</span><br><span style="color: hsl(120, 100%, 40%);">+        self.logfile_supported = False # some older versions of iperf doesn't support --logfile arg</span><br><span> </span><br><span>     def cleanup(self):</span><br><span>         if self.process is None:</span><br><span>             return</span><br><span style="color: hsl(0, 100%, 40%);">-        if self.runs_locally():</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.runs_locally() or not self.logfile_supported:</span><br><span>             return</span><br><span>         # copy back files (may not exist, for instance if there was an early error of process):</span><br><span>         try:</span><br><span>@@ -86,8 +93,10 @@</span><br><span>         self.rem_host.recreate_remote_dir(remote_run_dir)</span><br><span> </span><br><span>         args = ('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', self.remote_log_file)</span><br><span style="color: hsl(120, 100%, 40%);">+                '-p', str(self._port), '-J')</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.logfile_supported:</span><br><span style="color: hsl(120, 100%, 40%);">+            args += ('--logfile', self.remote_log_file,)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>         self.process = self.rem_host.RemoteProcess(self.name(), args)</span><br><span>         self.suite_run.remember_to_stop(self.process)</span><br><span>         self.process.launch()</span><br><span>@@ -97,8 +106,9 @@</span><br><span>                                    'host %s and port not 22' % self.addr())</span><br><span> </span><br><span>         args = ('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(120, 100%, 40%);">+                '-p', str(self._port), '-J')</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.logfile_supported:</span><br><span style="color: hsl(120, 100%, 40%);">+            args += ('--logfile', os.path.abspath(self.log_file),)</span><br><span> </span><br><span>         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>@@ -114,10 +124,14 @@</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(0, 100%, 40%);">-        if not self.runs_locally() and not self.log_copied:</span><br><span style="color: hsl(0, 100%, 40%);">-            self.rem_host.scpfrom('scp-back-log', self.remote_log_file, self.log_file)</span><br><span style="color: hsl(0, 100%, 40%);">-            self.log_copied = True</span><br><span style="color: hsl(0, 100%, 40%);">-        return iperf3_result_to_json(self.log_file)</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.logfile_supported:</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 style="color: hsl(120, 100%, 40%);">+            with open(self.log_file) as f:</span><br><span style="color: hsl(120, 100%, 40%);">+                return iperf3_result_to_json(self, f.read())</span><br><span style="color: hsl(120, 100%, 40%);">+        else:</span><br><span style="color: hsl(120, 100%, 40%);">+            return iperf3_result_to_json(self, self.process.get_stdout())</span><br><span> </span><br><span>     def addr(self):</span><br><span>         return self.ip_address.get('addr')</span><br><span>@@ -150,6 +164,7 @@</span><br><span>         self.rem_host = None</span><br><span>         self.remote_log_file = None</span><br><span>         self.log_copied = False</span><br><span style="color: hsl(120, 100%, 40%);">+        self.logfile_supported = False # some older versions of iperf doesn't support --logfile arg</span><br><span> </span><br><span>     def runs_locally(self):</span><br><span>         locally = not self._run_node or self._run_node.is_local()</span><br><span>@@ -191,8 +206,9 @@</span><br><span> </span><br><span>         popen_args = ('iperf3', '-c',  self.server.addr(),</span><br><span>                       '-p', str(self.server.port()), '-J',</span><br><span style="color: hsl(0, 100%, 40%);">-                      '--logfile', self.remote_log_file,</span><br><span>                       '-t', str(time_sec))</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.logfile_supported:</span><br><span style="color: hsl(120, 100%, 40%);">+            popen_args += ('--logfile', self.remote_log_file,)</span><br><span>         if downlink:</span><br><span>             popen_args += ('-R',)</span><br><span> </span><br><span>@@ -208,8 +224,9 @@</span><br><span> </span><br><span>         popen_args = ('iperf3', '-c',  self.server.addr(),</span><br><span>                       '-p', str(self.server.port()), '-J',</span><br><span style="color: hsl(0, 100%, 40%);">-                      '--logfile', os.path.abspath(self.log_file),</span><br><span>                       '-t', str(time_sec))</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.logfile_supported:</span><br><span style="color: hsl(120, 100%, 40%);">+            popen_args += ('--logfile', os.path.abspath(self.log_file),)</span><br><span>         if downlink:</span><br><span>             popen_args += ('-R',)</span><br><span> </span><br><span>@@ -225,10 +242,14 @@</span><br><span>         return self.get_results()</span><br><span> </span><br><span>     def get_results(self):</span><br><span style="color: hsl(0, 100%, 40%);">-        if not self.runs_locally() and not self.log_copied:</span><br><span style="color: hsl(0, 100%, 40%);">-            self.rem_host.scpfrom('scp-back-log', self.remote_log_file, self.log_file)</span><br><span style="color: hsl(0, 100%, 40%);">-            self.log_copied = True</span><br><span style="color: hsl(0, 100%, 40%);">-        return iperf3_result_to_json(self.log_file)</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.logfile_supported:</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 style="color: hsl(120, 100%, 40%);">+            with open(self.log_file) as f:</span><br><span style="color: hsl(120, 100%, 40%);">+                return iperf3_result_to_json(self, f.read())</span><br><span style="color: hsl(120, 100%, 40%);">+        else:</span><br><span style="color: hsl(120, 100%, 40%);">+            return iperf3_result_to_json(self, self.process.get_stdout())</span><br><span> </span><br><span>     def set_run_node(self, run_node):</span><br><span>         self._run_node = run_node</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-gsm-tester/+/17810">change 17810</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/+/17810"/><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: Ia1b7fa4dae074089878963aeddf0006aea68e31f </div>
<div style="display:none"> Gerrit-Change-Number: 17810 </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>