summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2024-11-20 16:54:44 +0000
committerSteve Sakoman <steve@sakoman.com>2025-01-13 05:49:08 -0800
commit66f9cec85308921d62fa447f10828043c89a79c2 (patch)
tree4b90862ae78edb1a461a5ae6598bfe220f45f844
parentf7169136671458a98690a7eb3328aa743f02d19e (diff)
downloadpoky-66f9cec85308921d62fa447f10828043c89a79c2.tar.gz
oeqa/ssh: Improve performance and log sizes
The current code is not fit for purpose when handling large files via ssh. In the strace ptest case, we can end up with a 1.4GB archive being transferred for which every byte is printed into the task logfile twice over. This is then sent over bitbake IPC which compounds the problems. Make the following improvements: * when the output is large (over 64kb), don't print it * use a bytearray for better concat performance since strings are slow for this * when there is no ssh output, say that * print periodic size status output rather than the data itself since this could be binary and/or large * fix the killed process message logic which appeared broken (From OE-Core rev: 57673a71b20e2bbb53e7652a709bdcb32c429b6b) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> (cherry picked from commit e7dd009a17dc902852983a82bce41bf78bb1e242) Signed-off-by: Steve Sakoman <steve@sakoman.com>
-rw-r--r--meta/lib/oeqa/core/target/ssh.py44
1 files changed, 32 insertions, 12 deletions
diff --git a/meta/lib/oeqa/core/target/ssh.py b/meta/lib/oeqa/core/target/ssh.py
index d473469384..8b5c450a05 100644
--- a/meta/lib/oeqa/core/target/ssh.py
+++ b/meta/lib/oeqa/core/target/ssh.py
@@ -92,7 +92,10 @@ class OESSHTarget(OETarget):
92 processTimeout = self.timeout 92 processTimeout = self.timeout
93 93
94 status, output = self._run(sshCmd, processTimeout, ignore_status, raw) 94 status, output = self._run(sshCmd, processTimeout, ignore_status, raw)
95 self.logger.debug('Command: %s\nStatus: %d Output: %s\n' % (command, status, output)) 95 if len(output) > (64 * 1024):
96 self.logger.debug('Command: %s\nStatus: %d Output length: %s\n' % (command, status, len(output)))
97 else:
98 self.logger.debug('Command: %s\nStatus: %d Output: %s\n' % (command, status, output))
96 99
97 return (status, output) 100 return (status, output)
98 101
@@ -211,17 +214,18 @@ def SSHCall(command, logger, timeout=None, raw=False, **opts):
211 def run(): 214 def run():
212 nonlocal output 215 nonlocal output
213 nonlocal process 216 nonlocal process
214 output_raw = b'' 217 output_raw = bytearray()
215 starttime = time.time() 218 starttime = time.time()
219 progress = time.time()
216 process = subprocess.Popen(command, **options) 220 process = subprocess.Popen(command, **options)
217 has_timeout = False 221 has_timeout = False
222 appendline = None
218 if timeout: 223 if timeout:
219 endtime = starttime + timeout 224 endtime = starttime + timeout
220 eof = False 225 eof = False
221 os.set_blocking(process.stdout.fileno(), False) 226 os.set_blocking(process.stdout.fileno(), False)
222 while not has_timeout and not eof: 227 while not has_timeout and not eof:
223 try: 228 try:
224 logger.debug('Waiting for process output: time: %s, endtime: %s' % (time.time(), endtime))
225 if select.select([process.stdout], [], [], 5)[0] != []: 229 if select.select([process.stdout], [], [], 5)[0] != []:
226 # wait a bit for more data, tries to avoid reading single characters 230 # wait a bit for more data, tries to avoid reading single characters
227 time.sleep(0.2) 231 time.sleep(0.2)
@@ -229,9 +233,9 @@ def SSHCall(command, logger, timeout=None, raw=False, **opts):
229 if not data: 233 if not data:
230 eof = True 234 eof = True
231 else: 235 else:
232 output_raw += data 236 output_raw.extend(data)
233 # ignore errors to capture as much as possible 237 # ignore errors to capture as much as possible
234 logger.debug('Partial data from SSH call:\n%s' % data.decode('utf-8', errors='ignore')) 238 #logger.debug('Partial data from SSH call:\n%s' % data.decode('utf-8', errors='ignore'))
235 endtime = time.time() + timeout 239 endtime = time.time() + timeout
236 except InterruptedError: 240 except InterruptedError:
237 logger.debug('InterruptedError') 241 logger.debug('InterruptedError')
@@ -244,6 +248,10 @@ def SSHCall(command, logger, timeout=None, raw=False, **opts):
244 logger.debug('SSHCall has timeout! Time: %s, endtime: %s' % (time.time(), endtime)) 248 logger.debug('SSHCall has timeout! Time: %s, endtime: %s' % (time.time(), endtime))
245 has_timeout = True 249 has_timeout = True
246 250
251 if time.time() >= (progress + 60):
252 logger.debug('Waiting for process output at time: %s with datasize: %s' % (time.time(), len(output_raw)))
253 progress = time.time()
254
247 process.stdout.close() 255 process.stdout.close()
248 256
249 # process hasn't returned yet 257 # process hasn't returned yet
@@ -256,17 +264,29 @@ def SSHCall(command, logger, timeout=None, raw=False, **opts):
256 logger.debug('OSError when killing process') 264 logger.debug('OSError when killing process')
257 pass 265 pass
258 endtime = time.time() - starttime 266 endtime = time.time() - starttime
259 lastline = ("\nProcess killed - no output for %d seconds. Total" 267 appendline = ("\nProcess killed - no output for %d seconds. Total"
260 " running time: %d seconds." % (timeout, endtime)) 268 " running time: %d seconds." % (timeout, endtime))
261 logger.debug('Received data from SSH call:\n%s ' % lastline) 269 logger.debug('Received data from SSH call:\n%s ' % appendline)
262 output += lastline
263 process.wait() 270 process.wait()
264 271
272 if raw:
273 output = bytes(output_raw)
274 if appendline:
275 output += bytes(appendline, "utf-8")
276 else:
277 output = output_raw.decode('utf-8', errors='ignore')
278 if appendline:
279 output += appendline
265 else: 280 else:
266 output_raw = process.communicate()[0] 281 output = output_raw = process.communicate()[0]
267 282 if not raw:
268 output = output_raw if raw else output_raw.decode('utf-8', errors='ignore') 283 output = output_raw.decode('utf-8', errors='ignore')
269 logger.debug('Data from SSH call:\n%s' % output.rstrip()) 284
285 if len(output) < (64 * 1024):
286 if output.rstrip():
287 logger.debug('Data from SSH call:\n%s' % output.rstrip())
288 else:
289 logger.debug('No output from SSH call')
270 290
271 # timout or not, make sure process exits and is not hanging 291 # timout or not, make sure process exits and is not hanging
272 if process.returncode == None: 292 if process.returncode == None: