Openembedded Core Discussions
 help / color / mirror / Atom feed
* [PATCH 0/4 v2] Get dumps when qemu fails
@ 2015-08-25 15:55 mariano.lopez
  2015-08-25 15:55 ` [PATCH 1/4 v2] dump: Created new classes for dump host and target mariano.lopez
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: mariano.lopez @ 2015-08-25 15:55 UTC (permalink / raw)
  To: openembedded-core

From: Mariano Lopez <mariano.lopez@linux.intel.com>

This provides classes for dump logs from the host
and the target. This way it's easier to get dumps
from the runner or the target and not just from
the test. With this now the qemurunner instance
get the dumps from the host when qemu fails.

This also allows to have datastore vars in the
commands and removes the special case commands.

This fix the regresion regression when testin real
hardware

This depends on:

http://lists.openembedded.org/pipermail/openembedded-core/2015-August/108912.html

[YOCTO #8118]
[YOCTO #8203]

Mariano Lopez (4):
  dump: Created new classes for dump host and target
  qemurunner: Added host dumps when there are errors
  dump: allow to have datastore vars on dump commands
  oetest: Fix regression when testing real hardware

 meta/classes/testimage.bbclass    | 14 +++++--
 meta/lib/oeqa/oetest.py           | 56 ++++---------------------
 meta/lib/oeqa/targetcontrol.py    | 16 +++----
 meta/lib/oeqa/utils/dump.py       | 87 +++++++++++++++++++++++++++++++++++++++
 meta/lib/oeqa/utils/qemurunner.py | 14 ++++++-
 5 files changed, 129 insertions(+), 58 deletions(-)
 create mode 100644 meta/lib/oeqa/utils/dump.py

-- 
1.9.1



^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/4 v2] dump: Created new classes for dump host and target
  2015-08-25 15:55 [PATCH 0/4 v2] Get dumps when qemu fails mariano.lopez
@ 2015-08-25 15:55 ` mariano.lopez
  2015-08-25 15:55 ` [PATCH 2/4 v2] qemurunner: Added host dumps when there are errors mariano.lopez
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: mariano.lopez @ 2015-08-25 15:55 UTC (permalink / raw)
  To: openembedded-core

From: Mariano Lopez <mariano.lopez@linux.intel.com>

It makes sense to separate the dump commands from the
oeRuntimeTest class, this way it can be used in all
the test context.

These are the changes included in this patch:

    - Created classes: BaseDumper, HostDumper, TargetDumper
    - Create an instance of HostDumper in imagetest.bbclass
      and add it to TestContext class, this way any class
      that have access to the TestContext would be able
      to dump logs from the host
    - Create an instance of TargetDumper in QemuTarget
      class after get the runner, this way it is
      accessible during the tests.

[YOCTO #8118]

Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
 meta/classes/testimage.bbclass |  5 +++
 meta/lib/oeqa/oetest.py        | 52 ++++------------------------
 meta/lib/oeqa/targetcontrol.py |  6 ++--
 meta/lib/oeqa/utils/dump.py    | 77 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 91 insertions(+), 49 deletions(-)
 create mode 100644 meta/lib/oeqa/utils/dump.py

diff --git a/meta/classes/testimage.bbclass b/meta/classes/testimage.bbclass
index 1d9464f..824b47f 100644
--- a/meta/classes/testimage.bbclass
+++ b/meta/classes/testimage.bbclass
@@ -231,6 +231,7 @@ def testimage_main(d):
     import time
     from oeqa.oetest import loadTests, runTests
     from oeqa.targetcontrol import get_target_controller
+    from oeqa.utils.dump import get_host_dumper
 
     pn = d.getVar("PN", True)
     export = oe.utils.conditional("TEST_EXPORT_ONLY", "1", True, False, d)
@@ -245,6 +246,9 @@ def testimage_main(d):
     testslist = get_tests_list(d)
     testsrequired = [t for t in d.getVar("TEST_SUITES", True).split() if t != "auto"]
 
+    # we need the host dumper in test context
+    host_dumper = get_host_dumper(d)
+
     # the robot dance
     target = get_target_controller(d)
 
@@ -255,6 +259,7 @@ def testimage_main(d):
             self.testsrequired = testsrequired
             self.filesdir = os.path.join(os.path.dirname(os.path.abspath(oeqa.runtime.__file__)),"files")
             self.target = target
+            self.host_dumper = host_dumper
             self.imagefeatures = d.getVar("IMAGE_FEATURES", True).split()
             self.distrofeatures = d.getVar("DISTRO_FEATURES", True).split()
             manifest = os.path.join(d.getVar("DEPLOY_DIR_IMAGE", True), d.getVar("IMAGE_LINK_NAME", True) + ".manifest")
diff --git a/meta/lib/oeqa/oetest.py b/meta/lib/oeqa/oetest.py
index e765c96..b33ca0a 100644
--- a/meta/lib/oeqa/oetest.py
+++ b/meta/lib/oeqa/oetest.py
@@ -11,8 +11,6 @@ import os, re, mmap
 import unittest
 import inspect
 import subprocess
-import datetime
-import commands
 import bb
 from oeqa.utils.decorators import LogResults
 from sys import exc_info, exc_clear
@@ -124,51 +122,13 @@ class oeRuntimeTest(oeTest):
         # If a test fails or there is an exception
         if not exc_info() == (None, None, None):
             exc_clear()
-            dump_dir = self.create_dump_dir()
+            self.tc.host_dumper.create_dir(self._testMethodName)
+            self.target.target_dumper.dump_target(
+                    self.tc.host_dumper.dump_dir)
+            self.tc.host_dumper.dump_host()
             print ("%s dump data from host and target "
-                "stored in %s" % (self._testMethodName, dump_dir))
-            self.dump_host_logs(dump_dir)
-            self.dump_target_logs(dump_dir)
-
-    def create_dump_dir(self):
-        dump_sub_dir = ("%s_%s" % (
-                datetime.datetime.now().strftime('%Y%m%d%H%M'),
-                self._testMethodName))
-        dump_dir = os.path.join(self.target.dump_dir, dump_sub_dir)
-        os.makedirs(dump_dir)
-        return dump_dir
-
-    def dump_host_logs(self, dump_dir):
-        for cmd in self.target.dump_host.split('\n'):
-            cmd = cmd.lstrip()
-            if not cmd:
-                continue
-            output = commands.getoutput(cmd)
-            filename = "host_%s" % cmd.split()[0]
-            with open(os.path.join(dump_dir, filename), 'w') as f:
-                f.write(output)
-
-    def dump_target_logs(self, dump_dir):
-        for cmd in self.target.dump_target.split('\n'):
-            cmd = cmd.lstrip()
-            if not cmd:
-                continue
-            # This will ping the host from target
-            if cmd == "_ping":
-                 comm = "ping -c3 %s" % self.target.server_ip
-            # This will get all the logs from /var/log/
-            elif cmd == "_logs":
-                comm = 'find /var/log/ -type f 2>/dev/null '
-                comm = '%s-exec echo "%s" \\; ' % (comm, '='*20)
-                comm = '%s-exec echo {} \\; ' % comm
-                comm = '%s-exec echo "%s" \\; ' % (comm, '='*20)
-                comm = '%s-exec cat {} \\; -exec echo "" \\;' % comm
-            else:
-                comm = cmd
-            (status, output) = self.target.run_serial(comm)
-            filename = "target_%s" % cmd.split()[0]
-            with open(os.path.join(dump_dir, filename), 'w') as f:
-                f.write(output)
+                    "stored in %s" % (self._testMethodName,
+                     self.target.target_dumper.dump_dir))
 
     #TODO: use package_manager.py to install packages on any type of image
     def install_packages(self, packagelist):
diff --git a/meta/lib/oeqa/targetcontrol.py b/meta/lib/oeqa/targetcontrol.py
index 59cae2e..2d58f17 100644
--- a/meta/lib/oeqa/targetcontrol.py
+++ b/meta/lib/oeqa/targetcontrol.py
@@ -14,6 +14,7 @@ import logging
 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.controllers.testtargetloader import TestTargetLoader
 from abc import ABCMeta, abstractmethod
 
@@ -123,9 +124,6 @@ class QemuTarget(BaseTarget):
         self.origrootfs = os.path.join(d.getVar("DEPLOY_DIR_IMAGE", True),  d.getVar("IMAGE_LINK_NAME", True) + '.' + self.image_fstype)
         self.rootfs = os.path.join(self.testdir, d.getVar("IMAGE_LINK_NAME", True) + '-testimage.' + self.image_fstype)
         self.kernel = os.path.join(d.getVar("DEPLOY_DIR_IMAGE", True), d.getVar("KERNEL_IMAGETYPE", False) + '-' + d.getVar('MACHINE', False) + '.bin')
-        self.dump_target = d.getVar("testimage_dump_target", True)
-        self.dump_host = d.getVar("testimage_dump_host", True)
-        self.dump_dir = d.getVar("TESTIMAGE_DUMP_DIR", True)
 
         # Log QemuRunner log output to a file
         import oe.path
@@ -155,6 +153,8 @@ class QemuTarget(BaseTarget):
                             logfile = self.qemulog,
                             boottime = int(d.getVar("TEST_QEMUBOOT_TIMEOUT", True)))
 
+        self.target_dumper = TargetDumper(d, self.runner)
+
     def deploy(self):
         try:
             bb.utils.mkdirhier(self.testdir)
diff --git a/meta/lib/oeqa/utils/dump.py b/meta/lib/oeqa/utils/dump.py
new file mode 100644
index 0000000..a0fa699
--- /dev/null
+++ b/meta/lib/oeqa/utils/dump.py
@@ -0,0 +1,77 @@
+import os
+import sys
+import errno
+import datetime
+import itertools
+from commands import runCmd
+
+def get_host_dumper(d):
+    return HostDumper(d)
+
+
+class BaseDumper(object):
+
+    def __init__(self, d):
+        self.parent_dir = d.getVar("TESTIMAGE_DUMP_DIR", True)
+
+    def create_dir(self, dir_suffix):
+        dump_subdir = ("%s_%s" % (
+                datetime.datetime.now().strftime('%Y%m%d%H%M'),
+                dir_suffix))
+        dump_dir = os.path.join(self.parent_dir, dump_subdir)
+        try:
+            os.makedirs(dump_dir)
+        except OSError as err:
+            if err.errno != errno.EEXIST:
+                raise err
+        self.dump_dir = dump_dir
+
+    def write_dump(self, command, output):
+        if isinstance(self, HostDumper):
+            prefix = "host"
+        elif isinstance(self, TargetDumper):
+            prefix = "target"
+        else:
+            prefix = "unknown"
+        for i in itertools.count():
+            filename = "%s_%02d_%s" % (prefix, i, command)
+            fullname = os.path.join(self.dump_dir, filename)
+            if not os.path.exists(fullname):
+                break
+        with open(fullname, 'w') as dump_file:
+            dump_file.write(output)
+
+
+class HostDumper(BaseDumper):
+
+    def __init__(self, d):
+        super(HostDumper, self).__init__(d)
+        self.host_cmds = d.getVar("testimage_dump_host", True)
+
+    def dump_host(self, dump_dir=""):
+        if dump_dir:
+            self.dump_dir = dump_dir
+        for cmd in self.host_cmds.split('\n'):
+            cmd = cmd.lstrip()
+            if not cmd or cmd[0] == '#':
+                continue
+            result = runCmd(cmd, ignore_status=True)
+            self.write_dump(cmd.split()[0], result.output)
+
+
+class TargetDumper(BaseDumper):
+
+    def __init__(self, d, qemurunner):
+        super(TargetDumper, self).__init__(d)
+        self.target_cmds = d.getVar("testimage_dump_target", True)
+        self.runner = qemurunner
+
+    def dump_target(self, dump_dir=""):
+        if dump_dir:
+            self.dump_dir = dump_dir
+        for cmd in self.target_cmds.split('\n'):
+            cmd = cmd.lstrip()
+            if not cmd or cmd[0] == '#':
+                continue
+            (status, output) = self.runner.run_serial(cmd)
+            self.write_dump(cmd.split()[0], output)
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/4 v2] qemurunner: Added host dumps when there are errors
  2015-08-25 15:55 [PATCH 0/4 v2] Get dumps when qemu fails mariano.lopez
  2015-08-25 15:55 ` [PATCH 1/4 v2] dump: Created new classes for dump host and target mariano.lopez
@ 2015-08-25 15:55 ` mariano.lopez
  2015-08-25 15:55 ` [PATCH 3/4 v2] dump: allow to have datastore vars on dump commands mariano.lopez
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: mariano.lopez @ 2015-08-25 15:55 UTC (permalink / raw)
  To: openembedded-core

From: Mariano Lopez <mariano.lopez@linux.intel.com>

This adds an instance of HostDumper to qemurunner,
with this instance now is possible to get dumps
from the host when there is an error.

This also adds dump points in the next cases:
    - runqemu exits before seeing qemu pid
    - Fail to get qemu process arguments
    - Not reach login banner before timeout
    - qemu pid never appears

[YOCTO #8118]

Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
 meta/classes/testimage.bbclass    |  2 +-
 meta/lib/oeqa/targetcontrol.py    | 10 ++++++----
 meta/lib/oeqa/utils/qemurunner.py | 14 +++++++++++++-
 3 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/meta/classes/testimage.bbclass b/meta/classes/testimage.bbclass
index 824b47f..2131869 100644
--- a/meta/classes/testimage.bbclass
+++ b/meta/classes/testimage.bbclass
@@ -250,7 +250,7 @@ def testimage_main(d):
     host_dumper = get_host_dumper(d)
 
     # the robot dance
-    target = get_target_controller(d)
+    target = get_target_controller(d, host_dumper)
 
     class TestContext(object):
         def __init__(self):
diff --git a/meta/lib/oeqa/targetcontrol.py b/meta/lib/oeqa/targetcontrol.py
index 2d58f17..14ba1d9 100644
--- a/meta/lib/oeqa/targetcontrol.py
+++ b/meta/lib/oeqa/targetcontrol.py
@@ -18,11 +18,11 @@ from oeqa.utils.dump import TargetDumper
 from oeqa.controllers.testtargetloader import TestTargetLoader
 from abc import ABCMeta, abstractmethod
 
-def get_target_controller(d):
+def get_target_controller(d, host_dumper):
     testtarget = d.getVar("TEST_TARGET", True)
     # old, simple names
     if testtarget == "qemu":
-        return QemuTarget(d)
+        return QemuTarget(d, host_dumper)
     elif testtarget == "simpleremote":
         return SimpleRemoteTarget(d)
     else:
@@ -115,7 +115,7 @@ class QemuTarget(BaseTarget):
 
     supported_image_fstypes = ['ext3', 'ext4', 'cpio.gz']
 
-    def __init__(self, d):
+    def __init__(self, d, host_dumper):
 
         super(QemuTarget, self).__init__(d)
 
@@ -124,6 +124,7 @@ class QemuTarget(BaseTarget):
         self.origrootfs = os.path.join(d.getVar("DEPLOY_DIR_IMAGE", True),  d.getVar("IMAGE_LINK_NAME", True) + '.' + self.image_fstype)
         self.rootfs = os.path.join(self.testdir, d.getVar("IMAGE_LINK_NAME", True) + '-testimage.' + self.image_fstype)
         self.kernel = os.path.join(d.getVar("DEPLOY_DIR_IMAGE", True), d.getVar("KERNEL_IMAGETYPE", False) + '-' + d.getVar('MACHINE', False) + '.bin')
+        self.host_dumper = host_dumper
 
         # Log QemuRunner log output to a file
         import oe.path
@@ -151,7 +152,8 @@ class QemuTarget(BaseTarget):
                             deploy_dir_image = d.getVar("DEPLOY_DIR_IMAGE", True),
                             display = d.getVar("BB_ORIGENV", False).getVar("DISPLAY", True),
                             logfile = self.qemulog,
-                            boottime = int(d.getVar("TEST_QEMUBOOT_TIMEOUT", True)))
+                            boottime = int(d.getVar("TEST_QEMUBOOT_TIMEOUT", True)),
+                            host_dumper = self.host_dumper)
 
         self.target_dumper = TargetDumper(d, self.runner)
 
diff --git a/meta/lib/oeqa/utils/qemurunner.py b/meta/lib/oeqa/utils/qemurunner.py
index 33f3185..4a21e7e 100644
--- a/meta/lib/oeqa/utils/qemurunner.py
+++ b/meta/lib/oeqa/utils/qemurunner.py
@@ -20,7 +20,7 @@ logger = logging.getLogger("BitBake.QemuRunner")
 
 class QemuRunner:
 
-    def __init__(self, machine, rootfs, display, tmpdir, deploy_dir_image, logfile, boottime):
+    def __init__(self, machine, rootfs, display, tmpdir, deploy_dir_image, logfile, boottime, host_dumper):
 
         # Popen object for runqemu
         self.runqemu = None
@@ -40,6 +40,7 @@ class QemuRunner:
         self.boottime = boottime
         self.logged = False
         self.thread = None
+        self.host_dumper = host_dumper
 
         self.runqemutime = 60
 
@@ -118,6 +119,7 @@ class QemuRunner:
                 if self.runqemu.returncode:
                     # No point waiting any longer
                     logger.info('runqemu exited with code %d' % self.runqemu.returncode)
+                    self._dump_host()
                     self.stop()
                     logger.info("Output from runqemu:\n%s" % getOutput(output))
                     return False
@@ -137,6 +139,7 @@ class QemuRunner:
                     self.server_ip = ips[1]
             except IndexError, ValueError:
                 logger.info("Couldn't get ip from qemu process arguments! Here is the qemu command line used:\n%s\nand output from runqemu:\n%s" % (cmdline, getOutput(output)))
+                self._dump_host()
                 self.stop()
                 return False
             logger.info("Target IP: %s" % self.ip)
@@ -188,6 +191,7 @@ class QemuRunner:
                 lines = "\n".join(bootlog.splitlines()[-25:])
                 logger.info("Last 25 lines of text:\n%s" % lines)
                 logger.info("Check full boot log: %s" % self.logfile)
+                self._dump_host()
                 self.stop()
                 return False
 
@@ -201,6 +205,7 @@ class QemuRunner:
 
         else:
             logger.info("Qemu pid didn't appeared in %s seconds" % self.runqemutime)
+            self._dump_host()
             self.stop()
             logger.info("Output from runqemu:\n%s" % getOutput(output))
             return False
@@ -333,6 +338,13 @@ class QemuRunner:
                     status = 1
         return (status, str(data))
 
+    def _dump_host(self):
+        self.host_dumper.create_dir("qemu")
+        logger.error("Qemu ended unexpectedly, dump data from host"
+                " is in %s" % self.host_dumper.dump_dir)
+        self.host_dumper.dump_host()
+
+
 # This class is for reading data from a socket and passing it to logfunc
 # to be processed. It's completely event driven and has a straightforward
 # event loop. The mechanism for stopping the thread is a simple pipe which
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/4 v2] dump: allow to have datastore vars on dump commands
  2015-08-25 15:55 [PATCH 0/4 v2] Get dumps when qemu fails mariano.lopez
  2015-08-25 15:55 ` [PATCH 1/4 v2] dump: Created new classes for dump host and target mariano.lopez
  2015-08-25 15:55 ` [PATCH 2/4 v2] qemurunner: Added host dumps when there are errors mariano.lopez
@ 2015-08-25 15:55 ` mariano.lopez
  2015-08-25 19:44   ` Benjamin Esquivel
  2015-08-25 15:55 ` [PATCH 4/4 v2] oetest: Fix regression when testing real hardware mariano.lopez
  2015-08-25 19:24 ` [PATCH 0/4 v2] Get dumps when qemu fails Benjamin Esquivel
  4 siblings, 1 reply; 8+ messages in thread
From: mariano.lopez @ 2015-08-25 15:55 UTC (permalink / raw)
  To: openembedded-core

From: Mariano Lopez <mariano.lopez@linux.intel.com>

This allows to have datastore variables in the dump
commands and will get the data when a new instance
it's created.

Also this remove special cases from the commands.

[YOCTO #8118]

Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
 meta/classes/testimage.bbclass |  7 +++++--
 meta/lib/oeqa/utils/dump.py    | 42 ++++++++++++++++++++++++++----------------
 2 files changed, 31 insertions(+), 18 deletions(-)

diff --git a/meta/classes/testimage.bbclass b/meta/classes/testimage.bbclass
index 2131869..6a4b80a 100644
--- a/meta/classes/testimage.bbclass
+++ b/meta/classes/testimage.bbclass
@@ -63,11 +63,14 @@ testimage_dump_target () {
     ps
     free
     df
-    _ping
+    # The next command will export the default gateway IP
+    export DEFAULT_GATEWAY=$(ip route | awk '/default/ { print $3}')
+    ping -c3 $DEFAULT_GATEWAY
     dmesg
     netstat -an
     ip address
-    _logs
+    # Next command will dump logs from /var/log/
+    find /var/log/ -type f 2>/dev/null -exec echo "====================" \; -exec echo {} \; -exec echo "====================" \; -exec cat {} \; -exec echo "" \;
 }
 
 testimage_dump_host () {
diff --git a/meta/lib/oeqa/utils/dump.py b/meta/lib/oeqa/utils/dump.py
index a0fa699..a76aede 100644
--- a/meta/lib/oeqa/utils/dump.py
+++ b/meta/lib/oeqa/utils/dump.py
@@ -11,8 +11,24 @@ def get_host_dumper(d):
 
 class BaseDumper(object):
 
-    def __init__(self, d):
+    def __init__(self, d, cmds):
+        self.cmds = []
         self.parent_dir = d.getVar("TESTIMAGE_DUMP_DIR", True)
+        for cmd in cmds.split('\n'):
+            cmd = cmd.lstrip()
+            if not cmd or cmd[0] == '#':
+                continue
+            # Replae variables from the datastore
+            while True:
+                index_start = cmd.find("${")
+                if index_start == -1:
+                    break
+                index_start += 2
+                index_end = cmd.find("}", index_start)
+                var = cmd[index_start:index_end]
+                value = d.getVar(var, True)
+                cmd = cmd.replace("${%s}" % var, value)
+            self.cmds.append(cmd)
 
     def create_dir(self, dir_suffix):
         dump_subdir = ("%s_%s" % (
@@ -26,7 +42,7 @@ class BaseDumper(object):
                 raise err
         self.dump_dir = dump_dir
 
-    def write_dump(self, command, output):
+    def _write_dump(self, command, output):
         if isinstance(self, HostDumper):
             prefix = "host"
         elif isinstance(self, TargetDumper):
@@ -45,33 +61,27 @@ class BaseDumper(object):
 class HostDumper(BaseDumper):
 
     def __init__(self, d):
-        super(HostDumper, self).__init__(d)
-        self.host_cmds = d.getVar("testimage_dump_host", True)
+        host_cmds = d.getVar("testimage_dump_host", True)
+        super(HostDumper, self).__init__(d, host_cmds)
 
     def dump_host(self, dump_dir=""):
         if dump_dir:
             self.dump_dir = dump_dir
-        for cmd in self.host_cmds.split('\n'):
-            cmd = cmd.lstrip()
-            if not cmd or cmd[0] == '#':
-                continue
+        for cmd in self.cmds:
             result = runCmd(cmd, ignore_status=True)
-            self.write_dump(cmd.split()[0], result.output)
+            self._write_dump(cmd.split()[0], result.output)
 
 
 class TargetDumper(BaseDumper):
 
     def __init__(self, d, qemurunner):
-        super(TargetDumper, self).__init__(d)
-        self.target_cmds = d.getVar("testimage_dump_target", True)
+        target_cmds = d.getVar("testimage_dump_target", True)
+        super(TargetDumper, self).__init__(d, target_cmds)
         self.runner = qemurunner
 
     def dump_target(self, dump_dir=""):
         if dump_dir:
             self.dump_dir = dump_dir
-        for cmd in self.target_cmds.split('\n'):
-            cmd = cmd.lstrip()
-            if not cmd or cmd[0] == '#':
-                continue
+        for cmd in self.cmds:
             (status, output) = self.runner.run_serial(cmd)
-            self.write_dump(cmd.split()[0], output)
+            self._write_dump(cmd.split()[0], output)
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/4 v2] oetest: Fix regression when testing real hardware
  2015-08-25 15:55 [PATCH 0/4 v2] Get dumps when qemu fails mariano.lopez
                   ` (2 preceding siblings ...)
  2015-08-25 15:55 ` [PATCH 3/4 v2] dump: allow to have datastore vars on dump commands mariano.lopez
@ 2015-08-25 15:55 ` mariano.lopez
  2015-08-25 19:24 ` [PATCH 0/4 v2] Get dumps when qemu fails Benjamin Esquivel
  4 siblings, 0 replies; 8+ messages in thread
From: mariano.lopez @ 2015-08-25 15:55 UTC (permalink / raw)
  To: openembedded-core

From: Mariano Lopez <mariano.lopez@linux.intel.com>

This fix the regression introduced in commit
9c72c1a5aa0b49d3895bbefee7a264adfcc6f4ca
when testing with real hardware. This regression
happens when a test in real hardware fails.

[YOCTO #8203]

Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
 meta/lib/oeqa/oetest.py | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/meta/lib/oeqa/oetest.py b/meta/lib/oeqa/oetest.py
index b33ca0a..dbdbc90 100644
--- a/meta/lib/oeqa/oetest.py
+++ b/meta/lib/oeqa/oetest.py
@@ -13,6 +13,7 @@ import inspect
 import subprocess
 import bb
 from oeqa.utils.decorators import LogResults
+from oeqa.targetcontrol import QemuTarget
 from sys import exc_info, exc_clear
 
 def loadTests(tc, type="runtime"):
@@ -123,12 +124,13 @@ class oeRuntimeTest(oeTest):
         if not exc_info() == (None, None, None):
             exc_clear()
             self.tc.host_dumper.create_dir(self._testMethodName)
-            self.target.target_dumper.dump_target(
-                    self.tc.host_dumper.dump_dir)
             self.tc.host_dumper.dump_host()
-            print ("%s dump data from host and target "
-                    "stored in %s" % (self._testMethodName,
-                     self.target.target_dumper.dump_dir))
+            #Only QemuTarget has a serial console
+            if (isinstance(self.target, QemuTarget)):
+                self.target.target_dumper.dump_target(
+                        self.tc.host_dumper.dump_dir)
+            print ("%s dump data stored in %s" % (self._testMethodName,
+                     self.tc.host_dumper.dump_dir))
 
     #TODO: use package_manager.py to install packages on any type of image
     def install_packages(self, packagelist):
-- 
1.9.1



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 0/4 v2] Get dumps when qemu fails
  2015-08-25 15:55 [PATCH 0/4 v2] Get dumps when qemu fails mariano.lopez
                   ` (3 preceding siblings ...)
  2015-08-25 15:55 ` [PATCH 4/4 v2] oetest: Fix regression when testing real hardware mariano.lopez
@ 2015-08-25 19:24 ` Benjamin Esquivel
  4 siblings, 0 replies; 8+ messages in thread
From: Benjamin Esquivel @ 2015-08-25 19:24 UTC (permalink / raw)
  To: mariano.lopez, openembedded-core

Hi Mariano, a minor correction below:

On Tue, 2015-08-25 at 10:55 -0500, mariano.lopez@linux.intel.com wrote:
> From: Mariano Lopez <mariano.lopez@linux.intel.com>
> 
> This provides classes for dump logs from the host
> and the target. This way it's easier to get dumps
> from the runner or the target and not just from
> the test. With this now the qemurunner instance
> get the dumps from the host when qemu fails.
> 
> This also allows to have datastore vars in the
> commands and removes the special case commands.
> 
> This fix the regresion regression when testin real
> hardware
*This fixes the regression encountered when tested
in hardware
> 
> This depends on:
> 
> http://lists.openembedded.org/pipermail/openembedded-core/2015-August
> /108912.html
> 
> [YOCTO #8118]
> [YOCTO #8203]
> 
> Mariano Lopez (4):
>   dump: Created new classes for dump host and target
>   qemurunner: Added host dumps when there are errors
>   dump: allow to have datastore vars on dump commands
>   oetest: Fix regression when testing real hardware
> 
>  meta/classes/testimage.bbclass    | 14 +++++--
>  meta/lib/oeqa/oetest.py           | 56 ++++---------------------
>  meta/lib/oeqa/targetcontrol.py    | 16 +++----
>  meta/lib/oeqa/utils/dump.py       | 87
> +++++++++++++++++++++++++++++++++++++++
>  meta/lib/oeqa/utils/qemurunner.py | 14 ++++++-
>  5 files changed, 129 insertions(+), 58 deletions(-)
>  create mode 100644 meta/lib/oeqa/utils/dump.py
> 
> -- 
> 1.9.1
> 


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 3/4 v2] dump: allow to have datastore vars on dump commands
  2015-08-25 15:55 ` [PATCH 3/4 v2] dump: allow to have datastore vars on dump commands mariano.lopez
@ 2015-08-25 19:44   ` Benjamin Esquivel
  2015-08-25 22:03     ` Mariano Lopez
  0 siblings, 1 reply; 8+ messages in thread
From: Benjamin Esquivel @ 2015-08-25 19:44 UTC (permalink / raw)
  To: mariano.lopez, openembedded-core

Hi Mariano, please find my comments below.

On Tue, 2015-08-25 at 10:55 -0500, mariano.lopez@linux.intel.com wrote:
> From: Mariano Lopez <mariano.lopez@linux.intel.com>
> 
> This allows to have datastore variables in the dump
> commands and will get the data when a new instance
> it's created.
> 
> Also this remove special cases from the commands.
> 
> [YOCTO #8118]
> 
> Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
> ---
>  meta/classes/testimage.bbclass |  7 +++++--
>  meta/lib/oeqa/utils/dump.py    | 42 ++++++++++++++++++++++++++------
> ----------
>  2 files changed, 31 insertions(+), 18 deletions(-)
> 
> diff --git a/meta/classes/testimage.bbclass
> b/meta/classes/testimage.bbclass
> index 2131869..6a4b80a 100644
> --- a/meta/classes/testimage.bbclass
> +++ b/meta/classes/testimage.bbclass
> @@ -63,11 +63,14 @@ testimage_dump_target () {
>      ps
>      free
>      df
> -    _ping
> +    # The next command will export the default gateway IP
> +    export DEFAULT_GATEWAY=$(ip route | awk '/default/ { print $3}')
> +    ping -c3 $DEFAULT_GATEWAY
>      dmesg
>      netstat -an
>      ip address
> -    _logs
> +    # Next command will dump logs from /var/log/
suggestion to make this a function and call it from here.
> +    find /var/log/ -type f 2>/dev/null -exec echo
> "====================" \; -exec echo {} \; -exec echo
> "====================" \; -exec cat {} \; -exec echo "" \;
>  }
>  
>  testimage_dump_host () {
> diff --git a/meta/lib/oeqa/utils/dump.py
> b/meta/lib/oeqa/utils/dump.py
> index a0fa699..a76aede 100644
> --- a/meta/lib/oeqa/utils/dump.py
> +++ b/meta/lib/oeqa/utils/dump.py
> @@ -11,8 +11,24 @@ def get_host_dumper(d):
>  
>  class BaseDumper(object):
>  
> -    def __init__(self, d):
> +    def __init__(self, d, cmds):
> +        self.cmds = []
>          self.parent_dir = d.getVar("TESTIMAGE_DUMP_DIR", True)
> +        for cmd in cmds.split('\n'):
> +            cmd = cmd.lstrip()
> +            if not cmd or cmd[0] == '#':
> +                continue
> +            # Replae variables from the datastore
*Replace
> +            while True:
> +                index_start = cmd.find("${")
> +                if index_start == -1:
> +                    break
> +                index_start += 2
> +                index_end = cmd.find("}", index_start)
> +                var = cmd[index_start:index_end]
> +                value = d.getVar(var, True)
> +                cmd = cmd.replace("${%s}" % var, value)
> +            self.cmds.append(cmd)
>  
>      def create_dir(self, dir_suffix):
>          dump_subdir = ("%s_%s" % (
> @@ -26,7 +42,7 @@ class BaseDumper(object):
>                  raise err
>          self.dump_dir = dump_dir
>  
> -    def write_dump(self, command, output):
> +    def _write_dump(self, command, output):
>          if isinstance(self, HostDumper):
>              prefix = "host"
>          elif isinstance(self, TargetDumper):
> @@ -45,33 +61,27 @@ class BaseDumper(object):
>  class HostDumper(BaseDumper):
>  
>      def __init__(self, d):
> -        super(HostDumper, self).__init__(d)
> -        self.host_cmds = d.getVar("testimage_dump_host", True)
> +        host_cmds = d.getVar("testimage_dump_host", True)
> +        super(HostDumper, self).__init__(d, host_cmds)
>  
>      def dump_host(self, dump_dir=""):
>          if dump_dir:
>              self.dump_dir = dump_dir
> -        for cmd in self.host_cmds.split('\n'):
> -            cmd = cmd.lstrip()
> -            if not cmd or cmd[0] == '#':
> -                continue
> +        for cmd in self.cmds:
>              result = runCmd(cmd, ignore_status=True)
> -            self.write_dump(cmd.split()[0], result.output)
> +            self._write_dump(cmd.split()[0], result.output)
>  
>  
>  class TargetDumper(BaseDumper):
>  
Wondering why there is not a base class Dumper that inherits to
TargetDumper and HostDumper
>      def __init__(self, d, qemurunner):
> -        super(TargetDumper, self).__init__(d)
> -        self.target_cmds = d.getVar("testimage_dump_target", True)
> +        target_cmds = d.getVar("testimage_dump_target", True)
> +        super(TargetDumper, self).__init__(d, target_cmds)
>          self.runner = qemurunner
>  
>      def dump_target(self, dump_dir=""):
>          if dump_dir:
>              self.dump_dir = dump_dir
> -        for cmd in self.target_cmds.split('\n'):
> -            cmd = cmd.lstrip()
> -            if not cmd or cmd[0] == '#':
> -                continue
> +        for cmd in self.cmds:
>              (status, output) = self.runner.run_serial(cmd)
> -            self.write_dump(cmd.split()[0], output)
> +            self._write_dump(cmd.split()[0], output)
> -- 
> 1.9.1
> 


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 3/4 v2] dump: allow to have datastore vars on dump commands
  2015-08-25 19:44   ` Benjamin Esquivel
@ 2015-08-25 22:03     ` Mariano Lopez
  0 siblings, 0 replies; 8+ messages in thread
From: Mariano Lopez @ 2015-08-25 22:03 UTC (permalink / raw)
  To: benjamin.esquivel, openembedded-core



On 08/25/2015 02:44 PM, Benjamin Esquivel wrote:
> Hi Mariano, please find my comments below.
>
> On Tue, 2015-08-25 at 10:55 -0500, mariano.lopez@linux.intel.com wrote:
>> From: Mariano Lopez <mariano.lopez@linux.intel.com>
>>
>> This allows to have datastore variables in the dump
>> commands and will get the data when a new instance
>> it's created.
>>
>> Also this remove special cases from the commands.
>>
>> [YOCTO #8118]
>>
>> Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
>> ---
>>   meta/classes/testimage.bbclass |  7 +++++--
>>   meta/lib/oeqa/utils/dump.py    | 42 ++++++++++++++++++++++++++------
>> ----------
>>   2 files changed, 31 insertions(+), 18 deletions(-)
>>
>> diff --git a/meta/classes/testimage.bbclass
>> b/meta/classes/testimage.bbclass
>> index 2131869..6a4b80a 100644
>> --- a/meta/classes/testimage.bbclass
>> +++ b/meta/classes/testimage.bbclass
>> @@ -63,11 +63,14 @@ testimage_dump_target () {
>>       ps
>>       free
>>       df
>> -    _ping
>> +    # The next command will export the default gateway IP
>> +    export DEFAULT_GATEWAY=$(ip route | awk '/default/ { print $3}')
>> +    ping -c3 $DEFAULT_GATEWAY
>>       dmesg
>>       netstat -an
>>       ip address
>> -    _logs
>> +    # Next command will dump logs from /var/log/
> suggestion to make this a function and call it from here.

It would be possible to add a bitbake var with the code.

>> +    find /var/log/ -type f 2>/dev/null -exec echo
>> "====================" \; -exec echo {} \; -exec echo
>> "====================" \; -exec cat {} \; -exec echo "" \;
>>   }
>>   
>>   testimage_dump_host () {
>> diff --git a/meta/lib/oeqa/utils/dump.py
>> b/meta/lib/oeqa/utils/dump.py
>> index a0fa699..a76aede 100644
>> --- a/meta/lib/oeqa/utils/dump.py
>> +++ b/meta/lib/oeqa/utils/dump.py
>> @@ -11,8 +11,24 @@ def get_host_dumper(d):
>>   
>>   class BaseDumper(object):
>>   
>> -    def __init__(self, d):
>> +    def __init__(self, d, cmds):
>> +        self.cmds = []
>>           self.parent_dir = d.getVar("TESTIMAGE_DUMP_DIR", True)
>> +        for cmd in cmds.split('\n'):
>> +            cmd = cmd.lstrip()
>> +            if not cmd or cmd[0] == '#':
>> +                continue
>> +            # Replae variables from the datastore
> *Replace
>> +            while True:
>> +                index_start = cmd.find("${")
>> +                if index_start == -1:
>> +                    break
>> +                index_start += 2
>> +                index_end = cmd.find("}", index_start)
>> +                var = cmd[index_start:index_end]
>> +                value = d.getVar(var, True)
>> +                cmd = cmd.replace("${%s}" % var, value)
>> +            self.cmds.append(cmd)
>>   
>>       def create_dir(self, dir_suffix):
>>           dump_subdir = ("%s_%s" % (
>> @@ -26,7 +42,7 @@ class BaseDumper(object):
>>                   raise err
>>           self.dump_dir = dump_dir
>>   
>> -    def write_dump(self, command, output):
>> +    def _write_dump(self, command, output):
>>           if isinstance(self, HostDumper):
>>               prefix = "host"
>>           elif isinstance(self, TargetDumper):
>> @@ -45,33 +61,27 @@ class BaseDumper(object):
>>   class HostDumper(BaseDumper):
>>   
>>       def __init__(self, d):
>> -        super(HostDumper, self).__init__(d)
>> -        self.host_cmds = d.getVar("testimage_dump_host", True)
>> +        host_cmds = d.getVar("testimage_dump_host", True)
>> +        super(HostDumper, self).__init__(d, host_cmds)
>>   
>>       def dump_host(self, dump_dir=""):
>>           if dump_dir:
>>               self.dump_dir = dump_dir
>> -        for cmd in self.host_cmds.split('\n'):
>> -            cmd = cmd.lstrip()
>> -            if not cmd or cmd[0] == '#':
>> -                continue
>> +        for cmd in self.cmds:
>>               result = runCmd(cmd, ignore_status=True)
>> -            self.write_dump(cmd.split()[0], result.output)
>> +            self._write_dump(cmd.split()[0], result.output)
>>   
>>   
>>   class TargetDumper(BaseDumper):
>>   
> Wondering why there is not a base class Dumper that inherits to
> TargetDumper and HostDumper

It is there, it's called BaseDumper

>>       def __init__(self, d, qemurunner):
>> -        super(TargetDumper, self).__init__(d)
>> -        self.target_cmds = d.getVar("testimage_dump_target", True)
>> +        target_cmds = d.getVar("testimage_dump_target", True)
>> +        super(TargetDumper, self).__init__(d, target_cmds)
>>           self.runner = qemurunner
>>   
>>       def dump_target(self, dump_dir=""):
>>           if dump_dir:
>>               self.dump_dir = dump_dir
>> -        for cmd in self.target_cmds.split('\n'):
>> -            cmd = cmd.lstrip()
>> -            if not cmd or cmd[0] == '#':
>> -                continue
>> +        for cmd in self.cmds:
>>               (status, output) = self.runner.run_serial(cmd)
>> -            self.write_dump(cmd.split()[0], output)
>> +            self._write_dump(cmd.split()[0], output)
>> -- 
>> 1.9.1
>>

-- 
Mariano Lopez


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2015-08-25 22:03 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-08-25 15:55 [PATCH 0/4 v2] Get dumps when qemu fails mariano.lopez
2015-08-25 15:55 ` [PATCH 1/4 v2] dump: Created new classes for dump host and target mariano.lopez
2015-08-25 15:55 ` [PATCH 2/4 v2] qemurunner: Added host dumps when there are errors mariano.lopez
2015-08-25 15:55 ` [PATCH 3/4 v2] dump: allow to have datastore vars on dump commands mariano.lopez
2015-08-25 19:44   ` Benjamin Esquivel
2015-08-25 22:03     ` Mariano Lopez
2015-08-25 15:55 ` [PATCH 4/4 v2] oetest: Fix regression when testing real hardware mariano.lopez
2015-08-25 19:24 ` [PATCH 0/4 v2] Get dumps when qemu fails Benjamin Esquivel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox