1# 2# Copyright OpenEmbedded Contributors 3# 4# SPDX-License-Identifier: MIT 5# 6 7# Run a set of actions after tests. The runner provides internal data 8# dictionary as well as test context to any action to run. 9 10import datetime 11import io 12import os 13import stat 14import subprocess 15import tempfile 16from oeqa.utils import get_artefact_dir 17 18################################################################## 19# Host/target statistics 20################################################################## 21 22def get_target_disk_usage(d, tc, artifacts_list, outputdir): 23 output_file = os.path.join(outputdir, "target_disk_usage.txt") 24 try: 25 (status, output) = tc.target.run('df -h') 26 with open(output_file, 'w') as f: 27 f.write(output) 28 f.write("\n") 29 except Exception as e: 30 bb.warn(f"Can not get target disk usage: {e}") 31 32def get_host_disk_usage(d, tc, artifacts_list, outputdir): 33 import subprocess 34 35 output_file = os.path.join(outputdir, "host_disk_usage.txt") 36 try: 37 with open(output_file, 'w') as f: 38 output = subprocess.run(['df', '-hl'], check=True, text=True, stdout=f, env={}) 39 except Exception as e: 40 bb.warn(f"Can not get host disk usage: {e}") 41 42################################################################## 43# Artifacts retrieval 44################################################################## 45 46def get_artifacts_list(target, raw_list): 47 result = [] 48 # Passed list may contains patterns in paths, expand them directly on target 49 for raw_path in raw_list.split(): 50 cmd = f"for p in {raw_path}; do if [ -e $p ]; then echo $p; fi; done" 51 try: 52 status, output = target.run(cmd) 53 if status != 0 or not output: 54 raise Exception() 55 result += output.split() 56 except: 57 bb.note(f"No file/directory matching path {raw_path}") 58 59 return result 60 61def list_and_fetch_failed_tests_artifacts(d, tc, artifacts_list, outputdir): 62 artifacts_list = get_artifacts_list(tc.target, artifacts_list) 63 if not artifacts_list: 64 bb.warn("Could not load artifacts list, skip artifacts retrieval") 65 return 66 try: 67 # We need gnu tar for sparse files, not busybox 68 cmd = "tar --sparse -zcf - " + " ".join(artifacts_list) 69 (status, output) = tc.target.run(cmd, raw = True) 70 if status != 0 or not output: 71 raise Exception("Error while fetching compressed artifacts") 72 archive_name = os.path.join(outputdir, "tests_artifacts.tar.gz") 73 with open(archive_name, "wb") as f: 74 f.write(output) 75 except Exception as e: 76 bb.warn(f"Can not retrieve artifacts from test target: {e}") 77 78 79################################################################## 80# General post actions runner 81################################################################## 82 83def run_failed_tests_post_actions(d, tc): 84 artifacts = d.getVar("TESTIMAGE_FAILED_QA_ARTIFACTS") 85 # Allow all the code to be disabled by having no artifacts set, e.g. for systems with no ssh support 86 if not artifacts: 87 return 88 89 outputdir = get_artefact_dir(d) 90 os.makedirs(outputdir, exist_ok=True) 91 datestr = datetime.datetime.now().strftime('%Y%m%d') 92 outputdir = tempfile.mkdtemp(prefix='oeqa-target-artefacts-%s-' % datestr, dir=outputdir) 93 os.chmod(outputdir, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) 94 95 post_actions=[ 96 list_and_fetch_failed_tests_artifacts, 97 get_target_disk_usage, 98 get_host_disk_usage 99 ] 100 101 for action in post_actions: 102 action(d, tc, artifacts, outputdir) 103