summaryrefslogtreecommitdiffstats
path: root/meta/lib/oeqa/utils/qemurunner.py
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2022-09-13 10:29:01 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2022-09-13 23:03:36 +0100
commit2d96d3f5ace29bb886d825609bd042310019a620 (patch)
tree15309efefd7d7181d8344f8eefba3fb7ad7a7720 /meta/lib/oeqa/utils/qemurunner.py
parent8d5cb0399f255eca906e960ce7fe05c62a24e891 (diff)
downloadpoky-2d96d3f5ace29bb886d825609bd042310019a620.tar.gz
selftest/qemurunner: Work around possible control character contamination
Using a binary string as the login banner search expression is fraught with risks. We've seen cases on the autobuilder where "login:" is clearly shown but the code hasn't triggered. The most likely cause is hidden control characters in the output causing the search to fail. Take the opportunity to remove the horrible binary string search, at the expense of decoding the bootlog multiple times. Tweak the logging so we can know which log was printed (self.msg or bootlog) just in case this isn't the issue and we need more information in future. (From OE-Core rev: 91b9e30e08695e715ef14c3df7471e8c99f9deb5) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/lib/oeqa/utils/qemurunner.py')
-rw-r--r--meta/lib/oeqa/utils/qemurunner.py21
1 files changed, 13 insertions, 8 deletions
diff --git a/meta/lib/oeqa/utils/qemurunner.py b/meta/lib/oeqa/utils/qemurunner.py
index 948f8adc9f..6a85f57e49 100644
--- a/meta/lib/oeqa/utils/qemurunner.py
+++ b/meta/lib/oeqa/utils/qemurunner.py
@@ -85,7 +85,7 @@ class QemuRunner:
85 accepted_patterns = ['search_reached_prompt', 'send_login_user', 'search_login_succeeded', 'search_cmd_finished'] 85 accepted_patterns = ['search_reached_prompt', 'send_login_user', 'search_login_succeeded', 'search_cmd_finished']
86 default_boot_patterns = defaultdict(str) 86 default_boot_patterns = defaultdict(str)
87 # Default to the usual paterns used to communicate with the target 87 # Default to the usual paterns used to communicate with the target
88 default_boot_patterns['search_reached_prompt'] = b' login:' 88 default_boot_patterns['search_reached_prompt'] = ' login:'
89 default_boot_patterns['send_login_user'] = 'root\n' 89 default_boot_patterns['send_login_user'] = 'root\n'
90 default_boot_patterns['search_login_succeeded'] = r"root@[a-zA-Z0-9\-]+:~#" 90 default_boot_patterns['search_login_succeeded'] = r"root@[a-zA-Z0-9\-]+:~#"
91 default_boot_patterns['search_cmd_finished'] = r"[a-zA-Z0-9]+@[a-zA-Z0-9\-]+:~#" 91 default_boot_patterns['search_cmd_finished'] = r"[a-zA-Z0-9]+@[a-zA-Z0-9\-]+:~#"
@@ -109,12 +109,15 @@ class QemuRunner:
109 sock.close() 109 sock.close()
110 raise 110 raise
111 111
112 def decode_qemulog(self, todecode):
113 # Sanitize the data received from qemu as it may contain control characters
114 msg = todecode.decode("utf-8", errors='ignore')
115 msg = re_control_char.sub('', msg)
116 return msg
117
112 def log(self, msg): 118 def log(self, msg):
113 if self.logfile: 119 if self.logfile:
114 # It is needed to sanitize the data received from qemu 120 msg = self.decode_qemulog(msg)
115 # because is possible to have control characters
116 msg = msg.decode("utf-8", errors='ignore')
117 msg = re_control_char.sub('', msg)
118 self.msg += msg 121 self.msg += msg
119 with codecs.open(self.logfile, "a", encoding="utf-8") as f: 122 with codecs.open(self.logfile, "a", encoding="utf-8") as f:
120 f.write("%s" % msg) 123 f.write("%s" % msg)
@@ -468,7 +471,9 @@ class QemuRunner:
468 self.log(data) 471 self.log(data)
469 472
470 data = b'' 473 data = b''
471 if self.boot_patterns['search_reached_prompt'] in bootlog: 474
475 decodedlog = self.decode_qemulog(bootlog)
476 if self.boot_patterns['search_reached_prompt'] in decodedlog:
472 self.server_socket = qemusock 477 self.server_socket = qemusock
473 stopread = True 478 stopread = True
474 reachedlogin = True 479 reachedlogin = True
@@ -488,10 +493,10 @@ class QemuRunner:
488 self.logger.warning("Target didn't reach login banner in %d seconds (%s)" % 493 self.logger.warning("Target didn't reach login banner in %d seconds (%s)" %
489 (self.boottime, time.strftime("%D %H:%M:%S"))) 494 (self.boottime, time.strftime("%D %H:%M:%S")))
490 tail = lambda l: "\n".join(l.splitlines()[-25:]) 495 tail = lambda l: "\n".join(l.splitlines()[-25:])
491 bootlog = bootlog.decode("utf-8") 496 bootlog = self.decode_qemulog(bootlog)
492 # in case bootlog is empty, use tail qemu log store at self.msg 497 # in case bootlog is empty, use tail qemu log store at self.msg
493 lines = tail(bootlog if bootlog else self.msg) 498 lines = tail(bootlog if bootlog else self.msg)
494 self.logger.warning("Last 25 lines of text:\n%s" % lines) 499 self.logger.warning("Last 25 lines of text (%d):\n%s" % (len(bootlog), lines))
495 self.logger.warning("Check full boot log: %s" % self.logfile) 500 self.logger.warning("Check full boot log: %s" % self.logfile)
496 self._dump_host() 501 self._dump_host()
497 self.stop() 502 self.stop()