summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/lib/oeqa/oetest.py10
-rw-r--r--meta/lib/oeqa/targetcontrol.py9
-rw-r--r--meta/lib/oeqa/utils/dump.py28
-rw-r--r--meta/lib/oeqa/utils/qemurunner.py15
4 files changed, 35 insertions, 27 deletions
diff --git a/meta/lib/oeqa/oetest.py b/meta/lib/oeqa/oetest.py
index f54113626b..4224206546 100644
--- a/meta/lib/oeqa/oetest.py
+++ b/meta/lib/oeqa/oetest.py
@@ -123,14 +123,14 @@ class oeRuntimeTest(oeTest):
123 # If a test fails or there is an exception 123 # If a test fails or there is an exception
124 if not exc_info() == (None, None, None): 124 if not exc_info() == (None, None, None):
125 exc_clear() 125 exc_clear()
126 self.tc.host_dumper.create_dir(self._testMethodName) 126 #Only dump for QemuTarget
127 self.tc.host_dumper.dump_host()
128 #Only QemuTarget has a serial console
129 if (isinstance(self.target, QemuTarget)): 127 if (isinstance(self.target, QemuTarget)):
128 self.tc.host_dumper.create_dir(self._testMethodName)
129 self.tc.host_dumper.dump_host()
130 self.target.target_dumper.dump_target( 130 self.target.target_dumper.dump_target(
131 self.tc.host_dumper.dump_dir) 131 self.tc.host_dumper.dump_dir)
132 print ("%s dump data stored in %s" % (self._testMethodName, 132 print ("%s dump data stored in %s" % (self._testMethodName,
133 self.tc.host_dumper.dump_dir)) 133 self.tc.host_dumper.dump_dir))
134 134
135 #TODO: use package_manager.py to install packages on any type of image 135 #TODO: use package_manager.py to install packages on any type of image
136 def install_packages(self, packagelist): 136 def install_packages(self, packagelist):
diff --git a/meta/lib/oeqa/targetcontrol.py b/meta/lib/oeqa/targetcontrol.py
index 2d58f17ddb..542e259112 100644
--- a/meta/lib/oeqa/targetcontrol.py
+++ b/meta/lib/oeqa/targetcontrol.py
@@ -124,6 +124,9 @@ class QemuTarget(BaseTarget):
124 self.origrootfs = os.path.join(d.getVar("DEPLOY_DIR_IMAGE", True), d.getVar("IMAGE_LINK_NAME", True) + '.' + self.image_fstype) 124 self.origrootfs = os.path.join(d.getVar("DEPLOY_DIR_IMAGE", True), d.getVar("IMAGE_LINK_NAME", True) + '.' + self.image_fstype)
125 self.rootfs = os.path.join(self.testdir, d.getVar("IMAGE_LINK_NAME", True) + '-testimage.' + self.image_fstype) 125 self.rootfs = os.path.join(self.testdir, d.getVar("IMAGE_LINK_NAME", True) + '-testimage.' + self.image_fstype)
126 self.kernel = os.path.join(d.getVar("DEPLOY_DIR_IMAGE", True), d.getVar("KERNEL_IMAGETYPE", False) + '-' + d.getVar('MACHINE', False) + '.bin') 126 self.kernel = os.path.join(d.getVar("DEPLOY_DIR_IMAGE", True), d.getVar("KERNEL_IMAGETYPE", False) + '-' + d.getVar('MACHINE', False) + '.bin')
127 dump_target_cmds = d.getVar("testimage_dump_target", True)
128 dump_host_cmds = d.getVar("testimage_dump_host", True)
129 dump_dir = d.getVar("TESTIMAGE_DUMP_DIR", True)
127 130
128 # Log QemuRunner log output to a file 131 # Log QemuRunner log output to a file
129 import oe.path 132 import oe.path
@@ -151,9 +154,11 @@ class QemuTarget(BaseTarget):
151 deploy_dir_image = d.getVar("DEPLOY_DIR_IMAGE", True), 154 deploy_dir_image = d.getVar("DEPLOY_DIR_IMAGE", True),
152 display = d.getVar("BB_ORIGENV", False).getVar("DISPLAY", True), 155 display = d.getVar("BB_ORIGENV", False).getVar("DISPLAY", True),
153 logfile = self.qemulog, 156 logfile = self.qemulog,
154 boottime = int(d.getVar("TEST_QEMUBOOT_TIMEOUT", True))) 157 boottime = int(d.getVar("TEST_QEMUBOOT_TIMEOUT", True)),
158 dump_dir = dump_dir,
159 dump_host_cmds = d.getVar("testimage_dump_host", True))
155 160
156 self.target_dumper = TargetDumper(d, self.runner) 161 self.target_dumper = TargetDumper(dump_target_cmds, dump_dir, self.runner)
157 162
158 def deploy(self): 163 def deploy(self):
159 try: 164 try:
diff --git a/meta/lib/oeqa/utils/dump.py b/meta/lib/oeqa/utils/dump.py
index e71e1cd341..6067438e35 100644
--- a/meta/lib/oeqa/utils/dump.py
+++ b/meta/lib/oeqa/utils/dump.py
@@ -6,30 +6,22 @@ import itertools
6from commands import runCmd 6from commands import runCmd
7 7
8def get_host_dumper(d): 8def get_host_dumper(d):
9 return HostDumper(d) 9 cmds = d.getVar("testimage_dump_host", True)
10 parent_dir = d.getVar("TESTIMAGE_DUMP_DIR", True)
11 return HostDumper(cmds, parent_dir)
10 12
11 13
12class BaseDumper(object): 14class BaseDumper(object):
13 15
14 def __init__(self, d, cmds): 16 def __init__(self, cmds, parent_dir):
15 self.cmds = [] 17 self.cmds = []
16 self.parent_dir = d.getVar("TESTIMAGE_DUMP_DIR", True) 18 self.parent_dir = parent_dir
17 if not cmds: 19 if not cmds:
18 return 20 return
19 for cmd in cmds.split('\n'): 21 for cmd in cmds.split('\n'):
20 cmd = cmd.lstrip() 22 cmd = cmd.lstrip()
21 if not cmd or cmd[0] == '#': 23 if not cmd or cmd[0] == '#':
22 continue 24 continue
23 # Replae variables from the datastore
24 while True:
25 index_start = cmd.find("${")
26 if index_start == -1:
27 break
28 index_start += 2
29 index_end = cmd.find("}", index_start)
30 var = cmd[index_start:index_end]
31 value = d.getVar(var, True)
32 cmd = cmd.replace("${%s}" % var, value)
33 self.cmds.append(cmd) 25 self.cmds.append(cmd)
34 26
35 def create_dir(self, dir_suffix): 27 def create_dir(self, dir_suffix):
@@ -62,9 +54,8 @@ class BaseDumper(object):
62 54
63class HostDumper(BaseDumper): 55class HostDumper(BaseDumper):
64 56
65 def __init__(self, d): 57 def __init__(self, cmds, parent_dir):
66 host_cmds = d.getVar("testimage_dump_host", True) 58 super(HostDumper, self).__init__(cmds, parent_dir)
67 super(HostDumper, self).__init__(d, host_cmds)
68 59
69 def dump_host(self, dump_dir=""): 60 def dump_host(self, dump_dir=""):
70 if dump_dir: 61 if dump_dir:
@@ -76,9 +67,8 @@ class HostDumper(BaseDumper):
76 67
77class TargetDumper(BaseDumper): 68class TargetDumper(BaseDumper):
78 69
79 def __init__(self, d, qemurunner): 70 def __init__(self, cmds, parent_dir, qemurunner):
80 target_cmds = d.getVar("testimage_dump_target", True) 71 super(TargetDumper, self).__init__(cmds, parent_dir)
81 super(TargetDumper, self).__init__(d, target_cmds)
82 self.runner = qemurunner 72 self.runner = qemurunner
83 73
84 def dump_target(self, dump_dir=""): 74 def dump_target(self, dump_dir=""):
diff --git a/meta/lib/oeqa/utils/qemurunner.py b/meta/lib/oeqa/utils/qemurunner.py
index bcdb69b38c..4ce5d9c685 100644
--- a/meta/lib/oeqa/utils/qemurunner.py
+++ b/meta/lib/oeqa/utils/qemurunner.py
@@ -14,13 +14,14 @@ import socket
14import select 14import select
15import errno 15import errno
16import threading 16import threading
17from oeqa.utils.dump import HostDumper
17 18
18import logging 19import logging
19logger = logging.getLogger("BitBake.QemuRunner") 20logger = logging.getLogger("BitBake.QemuRunner")
20 21
21class QemuRunner: 22class QemuRunner:
22 23
23 def __init__(self, machine, rootfs, display, tmpdir, deploy_dir_image, logfile, boottime): 24 def __init__(self, machine, rootfs, display, tmpdir, deploy_dir_image, logfile, boottime, dump_dir, dump_host_cmds):
24 25
25 # Popen object for runqemu 26 # Popen object for runqemu
26 self.runqemu = None 27 self.runqemu = None
@@ -42,6 +43,7 @@ class QemuRunner:
42 self.thread = None 43 self.thread = None
43 44
44 self.runqemutime = 60 45 self.runqemutime = 60
46 self.host_dumper = HostDumper(dump_host_cmds, dump_dir)
45 47
46 def create_socket(self): 48 def create_socket(self):
47 try: 49 try:
@@ -118,6 +120,7 @@ class QemuRunner:
118 if self.runqemu.returncode: 120 if self.runqemu.returncode:
119 # No point waiting any longer 121 # No point waiting any longer
120 logger.info('runqemu exited with code %d' % self.runqemu.returncode) 122 logger.info('runqemu exited with code %d' % self.runqemu.returncode)
123 self._dump_host()
121 self.stop() 124 self.stop()
122 logger.info("Output from runqemu:\n%s" % getOutput(output)) 125 logger.info("Output from runqemu:\n%s" % getOutput(output))
123 return False 126 return False
@@ -137,6 +140,7 @@ class QemuRunner:
137 self.server_ip = ips[1] 140 self.server_ip = ips[1]
138 except IndexError, ValueError: 141 except IndexError, ValueError:
139 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))) 142 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)))
143 self._dump_host()
140 self.stop() 144 self.stop()
141 return False 145 return False
142 logger.info("qemu cmdline used:\n{}".format(cmdline)) 146 logger.info("qemu cmdline used:\n{}".format(cmdline))
@@ -189,6 +193,7 @@ class QemuRunner:
189 lines = "\n".join(bootlog.splitlines()[-25:]) 193 lines = "\n".join(bootlog.splitlines()[-25:])
190 logger.info("Last 25 lines of text:\n%s" % lines) 194 logger.info("Last 25 lines of text:\n%s" % lines)
191 logger.info("Check full boot log: %s" % self.logfile) 195 logger.info("Check full boot log: %s" % self.logfile)
196 self._dump_host()
192 self.stop() 197 self.stop()
193 return False 198 return False
194 199
@@ -202,6 +207,7 @@ class QemuRunner:
202 207
203 else: 208 else:
204 logger.info("Qemu pid didn't appeared in %s seconds" % self.runqemutime) 209 logger.info("Qemu pid didn't appeared in %s seconds" % self.runqemutime)
210 self._dump_host()
205 self.stop() 211 self.stop()
206 logger.info("Output from runqemu:\n%s" % getOutput(output)) 212 logger.info("Output from runqemu:\n%s" % getOutput(output))
207 return False 213 return False
@@ -334,6 +340,13 @@ class QemuRunner:
334 status = 1 340 status = 1
335 return (status, str(data)) 341 return (status, str(data))
336 342
343
344 def _dump_host(self):
345 self.host_dumper.create_dir("qemu")
346 logger.error("Qemu ended unexpectedly, dump data from host"
347 " is in %s" % self.host_dumper.dump_dir)
348 self.host_dumper.dump_host()
349
337# This class is for reading data from a socket and passing it to logfunc 350# This class is for reading data from a socket and passing it to logfunc
338# to be processed. It's completely event driven and has a straightforward 351# to be processed. It's completely event driven and has a straightforward
339# event loop. The mechanism for stopping the thread is a simple pipe which 352# event loop. The mechanism for stopping the thread is a simple pipe which