Oops, need to double check what 000* is going to actual send, please ignore this and the following older qemu_runner patch.

Sau!

On 11/10/20 8:10 PM, Saul Wold wrote:
Signed-off-by: Saul Wold <saul.w...@windriver.com>
---
  meta/lib/oeqa/core/target/ssh.py       |  9 ++--
  meta/lib/oeqa/runtime/cases/network.py | 28 +++++++++++
  meta/lib/oeqa/runtime/files/kill_net   |  5 ++
  meta/lib/oeqa/targetcontrol.py         |  3 ++
  meta/lib/oeqa/utils/dump.py            | 22 ++++++++
  meta/lib/oeqa/utils/qemurunner.py      | 70 +++++++++++++++++++++++++-
  6 files changed, 133 insertions(+), 4 deletions(-)
  create mode 100644 meta/lib/oeqa/runtime/cases/network.py
  create mode 100644 meta/lib/oeqa/runtime/files/kill_net

diff --git a/meta/lib/oeqa/core/target/ssh.py b/meta/lib/oeqa/core/target/ssh.py
index 461448dbc5..c744b90719 100644
--- a/meta/lib/oeqa/core/target/ssh.py
+++ b/meta/lib/oeqa/core/target/ssh.py
@@ -54,7 +54,7 @@ class OESSHTarget(OETarget):
          """
              Runs command in target using SSHProcess.
          """
-        self.logger.debug("[Running]$ %s" % " ".join(command))
+        self.logger.debug("sgw-[Running]$ %s" % " ".join(command))
starttime = time.time()
          status, output = SSHCall(command, self.logger, timeout)
@@ -77,6 +77,7 @@ class OESSHTarget(OETarget):
                          0:          No timeout, runs until return.
          """
          targetCmd = 'export PATH=/usr/sbin:/sbin:/usr/bin:/bin; %s' % command
+        self.ip = "192.168.7.5"
          sshCmd = self.ssh + [self.ip, targetCmd]
if timeout:
@@ -87,8 +88,10 @@ class OESSHTarget(OETarget):
              processTimeout = self.timeout
status, output = self._run(sshCmd, processTimeout, True)
-        self.logger.debug('Command: %s\nOutput:  %s\n' % (command, output))
-        if (status == 255) and (('No route to host') in output):
+        self.logger.debug('Command: %s\nStatus: %d Output:  %s\n' % (command, 
status, output))
+#        if (status == 255) and (('No route to host') in output):
+        if status == 255:
+            self.target_dumper.dump_target()
              self.target_dumper.dump_target()
          return (status, output)
diff --git a/meta/lib/oeqa/runtime/cases/network.py b/meta/lib/oeqa/runtime/cases/network.py
new file mode 100644
index 0000000000..49fcac133a
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/network.py
@@ -0,0 +1,28 @@
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.runtime.decorator.package import OEHasPackage
+
+class NetworkTest(OERuntimeTestCase):
+
+    @classmethod
+    def setUp(cls):
+        src = os.path.join(cls.tc.runtime_files_dir, 'kill_net')
+        dst = '/home/root/kill_net'
+        cls.tc.target.copyTo(src, dst)
+
+
+    @OETestDepends(['ssh.SSHTest.test_ssh'])
+    def test_network_check(self):
+        (status, output) = self.target.run('/sbin/ip a')
+        msg = 'Failed to run "ip a". Output: %s' % output
+        self.assertEqual(status, 0, msg=msg)
+
+    @OETestDepends(['network.NetworkTest.test_network_check'])
+    def test_run_kill_net(self):
+        (status, output) = self.target.run('/bin/bash /home/root/kill_net > results 
2>&1 &')
+        msg = 'Failed to run "kill_net". Output: %s' % output
+        self.assertEqual(status, 0, msg=msg)
diff --git a/meta/lib/oeqa/runtime/files/kill_net 
b/meta/lib/oeqa/runtime/files/kill_net
new file mode 100644
index 0000000000..981eec816d
--- /dev/null
+++ b/meta/lib/oeqa/runtime/files/kill_net
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+ip a
+sleep 1
+ip link set eth0 down
diff --git a/meta/lib/oeqa/targetcontrol.py b/meta/lib/oeqa/targetcontrol.py
index 19f5a4ea7e..8cdd984179 100644
--- a/meta/lib/oeqa/targetcontrol.py
+++ b/meta/lib/oeqa/targetcontrol.py
@@ -17,6 +17,7 @@ from oeqa.utils.sshcontrol import SSHControl
  from oeqa.utils.qemurunner import QemuRunner
  from oeqa.utils.qemutinyrunner import QemuTinyRunner
  from oeqa.utils.dump import TargetDumper
+from oeqa.utils.dump import MonitorDumper
  from oeqa.controllers.testtargetloader import TestTargetLoader
  from abc import ABCMeta, abstractmethod
@@ -108,6 +109,7 @@ class QemuTarget(BaseTarget):
          self.qemulog = os.path.join(self.testdir, "qemu_boot_log.%s" % 
self.datetime)
          dump_target_cmds = d.getVar("testimage_dump_target")
          dump_host_cmds = d.getVar("testimage_dump_host")
+        dump_monitor_cmds = ['{"execute":"query-status"}\n', 
'{"execute":"query-status"}\n']
          dump_dir = d.getVar("TESTIMAGE_DUMP_DIR")
          if not dump_dir:
              dump_dir = os.path.join(d.getVar('LOG_DIR'), 'runtime-hostdump')
@@ -147,6 +149,7 @@ class QemuTarget(BaseTarget):
                              serial_ports = 
len(d.getVar("SERIAL_CONSOLES").split()))
self.target_dumper = TargetDumper(dump_target_cmds, dump_dir, self.runner)
+        self.monitor_dumper = MonitorDumper(dump_monitor_cmds, dump_dir, 
self.runner)
def deploy(self):
          bb.utils.mkdirhier(self.testdir)
diff --git a/meta/lib/oeqa/utils/dump.py b/meta/lib/oeqa/utils/dump.py
index 09a44329e0..058d1e46b1 100644
--- a/meta/lib/oeqa/utils/dump.py
+++ b/meta/lib/oeqa/utils/dump.py
@@ -96,3 +96,25 @@ class TargetDumper(BaseDumper):
              except:
                  print("Tried to dump info from target but "
                          "serial console failed")
+                print("Failed CMD: %s" % (cmd))
+
+class MonitorDumper(BaseDumper):
+    """ Class to get dumps via the Qemu Monitor, it only works with QemuRunner 
"""
+
+    def __init__(self, cmds, parent_dir, runner):
+        super(MonitorDumper, self).__init__(cmds, parent_dir)
+        self.runner = runner
+
+    def dump_monitor(self, dump_dir=""):
+        if dump_dir:
+            self.dump_dir = dump_dir
+        for cmd in self.cmds:
+            try:
+                print("dump_target: %s" % cmd)
+                output = self.runner.run_monitor(cmd)
+                print("result: %s" % (output))
+                self._write_dump(cmd.split()[0], output)
+            except:
+                print("Failed to dump montor data")
+                print("Failed CMD: %s" % (cmd))
+
diff --git a/meta/lib/oeqa/utils/qemurunner.py 
b/meta/lib/oeqa/utils/qemurunner.py
index 77ec939ad7..0ca0d78470 100644
--- a/meta/lib/oeqa/utils/qemurunner.py
+++ b/meta/lib/oeqa/utils/qemurunner.py
@@ -20,6 +20,7 @@ import string
  import threading
  import codecs
  import logging
+from contextlib import closing
  from oeqa.utils.dump import HostDumper
  from collections import defaultdict
@@ -84,6 +85,12 @@ class QemuRunner:
          default_boot_patterns['send_login_user'] = 'root\n'
          default_boot_patterns['search_login_succeeded'] = 
r"root@[a-zA-Z0-9\-]+:~#"
          default_boot_patterns['search_cmd_finished'] = 
r"[a-zA-Z0-9]+@[a-zA-Z0-9\-]+:~#"
+        monitor_cmds = defaultdict(str)
+        monitor_cmds['qmp_cap'] = 
'{"execute":"qmp_capabilities","arguments":{"enable":["oob"]}}\n'
+        monitor_cmds['cont'] = '{"execute":"cont"}\n'
+        monitor_cmds['quit'] = '{"execute":"quit"}\n'
+        monitor_cmds['preconfig'] = '{"execute":"x-exit-preconfig"}\n'
+        self.monitor_cmds = monitor_cmds
# Only override patterns that were set e.g. login user TESTIMAGE_BOOT_PATTERNS[send_login_user] = "webserver\n"
          for pattern in accepted_patterns:
@@ -168,10 +175,17 @@ class QemuRunner:
          return self.launch(launch_cmd, qemuparams=qemuparams, get_ip=get_ip, 
extra_bootparams=extra_bootparams, env=env)
def launch(self, launch_cmd, get_ip = True, qemuparams = None, extra_bootparams = None, env = None):
+        # Find a free socket port that can be used by the QEMU Monitor console
+        with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
+            s.bind(('', 0))
+            s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+            qmp_port = s.getsockname()[1]
+
          try:
              if self.serial_ports >= 2:
                  self.threadsock, threadport = self.create_socket()
              self.server_socket, self.serverport = self.create_socket()
+
          except socket.error as msg:
              self.logger.error("Failed to create listening socket: %s" % 
msg[1])
              return False
@@ -185,6 +199,9 @@ class QemuRunner:
          if os.path.exists(self.qemu_pidfile):
              os.remove(self.qemu_pidfile)
          self.qemuparams = 'bootparams="{0}" qemuparams="-pidfile 
{1}"'.format(bootparams, self.qemu_pidfile)
+        qemuparams += ' -S -qmp tcp:localhost:%s,server,wait' % (qmp_port)
+        qemuparams += ' -monitor tcp:localhost:4444,server,nowait'
+
          if qemuparams:
              self.qemuparams = self.qemuparams[:-1] + " " + qemuparams + " " + 
'\"'
@@ -250,6 +267,28 @@ class QemuRunner: if self.runqemu_exited:
              return False
+
+        # Create the client socket for the QEMU Monitor Control Socket
+        # This will allow us to read status from Qemu if the the process
+        # is still alive
+        try:
+            self.monitor_socket = socket.socket(socket.AF_INET, 
socket.SOCK_STREAM)
+            self.monitor_socket.connect(("127.0.0.1", qmp_port))
+            self.monitor_socket.setblocking(False)
+
+        except socket.error as msg:
+            self.logger.error("Failed to connect qemu monitor socket: %s" % 
msg[1])
+            return False
+
+        # Run an empty command to get the initial connection details, then
+        # send the qmp_capabilities command, this is required to initialize
+        # the monitor console
+        mon_output = self.run_monitor("")
+        self.logger.debug("Monitor: %s" % mon_output)
+        mon_output = self.run_monitor(self.monitor_cmds['qmp_cap'], 
timeout=120)
+        self.logger.debug("Monitor: %s" % mon_output)
+        mon_output = self.run_monitor(self.monitor_cmds['cont'], timeout=120)
+        self.logger.debug("Monitor: %s" % mon_output)
if not self.is_alive():
              self.logger.error("Qemu pid didn't appear in %s seconds (%s)" %
@@ -338,6 +377,7 @@ class QemuRunner:
          reachedlogin = False
          stopread = False
          qemusock = None
+        monsock = None
          bootlog = b''
          data = b''
          while time.time() < endtime and not stopread:
@@ -376,7 +416,6 @@ class QemuRunner:
                          sock.close()
                          stopread = True
-
          if not reachedlogin:
              if time.time() >= endtime:
                  self.logger.warning("Target didn't reach login banner in %d 
seconds (%s)" %
@@ -437,6 +476,9 @@ class QemuRunner:
              self.runqemu.stdout.close()
              self.runqemu_exited = True
+ if hasattr(self, 'monitor_socket') and self.monitor_socket:
+            self.monitor_socket.close()
+            self.monitor_socket = None
          if hasattr(self, 'server_socket') and self.server_socket:
              self.server_socket.close()
              self.server_socket = None
@@ -495,6 +537,32 @@ class QemuRunner:
                          return True
          return False
+ def run_monitor(self, command, timeout=60):
+        data = ''
+        self.monitor_socket.sendall(command.encode('utf-8'))
+        start = time.time()
+        end = start + timeout
+        while True:
+            now = time.time()
+            if now >= end:
+                data += "<<< run_monitor(): command timed out after %d seconds without 
output >>>\r\n\r\n" % timeout
+                break
+            try:
+                sread, _, _ = select.select([self.monitor_socket],[],[], end - 
now)
+            except InterruptedError:
+                continue
+            if sread:
+                answer = self.monitor_socket.recv(1024)
+                if answer:
+                    data += answer.decode('utf-8')
+                    if data.rfind('\r\n') != -1:
+                        break;
+                else:
+                    raise Exception("No data on monitor socket")
+
+        if data:
+            return (str(data))
+
      def run_serial(self, command, raw=False, timeout=60):
          # We assume target system have echo to get command status
          if not raw:






--
Sau!
-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#144466): 
https://lists.openembedded.org/g/openembedded-core/message/144466
Mute This Topic: https://lists.openembedded.org/mt/78176616/21656
Group Owner: openembedded-core+ow...@lists.openembedded.org
Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub 
[arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to