Add a basic artifacts retrievers in testimage class which: - triggers when at least one runtime test fails - reads a list of files to retrieve from ARTIFACTS_LIST_PATH - retrieve those files over scp thanks to existing ssh class - store those files in an "artifacts" directory in "tmp/log/oeqa/<image>"
Bring partial solution to [YOCTO #14901] Signed-off-by: Alexis Lothoré <alexis.loth...@bootlin.com> --- meta/classes-recipe/testimage.bbclass | 51 +++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/meta/classes-recipe/testimage.bbclass b/meta/classes-recipe/testimage.bbclass index 6b10c1db09f9..3fd3dd5b0264 100644 --- a/meta/classes-recipe/testimage.bbclass +++ b/meta/classes-recipe/testimage.bbclass @@ -18,6 +18,12 @@ inherit image-artifact-names TESTIMAGE_AUTO ??= "0" +# When any test fails, if path to an artifacts configuration (listing +# files/directories to retrieve on target) has been provided, all listed +# elements will be downloaded from target before shutting it down + +ARTIFACTS_LIST_PATH ??= "" + # You can set (or append to) TEST_SUITES in local.conf to select the tests # which you want to run for your target. # The test names are the module names in meta/lib/oeqa/runtime/cases. @@ -192,6 +198,45 @@ def get_testimage_boot_patterns(d): boot_patterns[flag] = flagval.encode().decode('unicode-escape') return boot_patterns +def load_artifacts_list(artifacts_conf_path): + import json + + if not artifacts_conf_path: + return None + + if not os.path.isfile(artifacts_conf_path): + return None + + try: + with open(artifacts_conf_path) as f: + artifacts_list = json.load(f) + except json.decoder.JSONDecodeError as e: + bb.warn(f"Invalid tests artifact list format: {e.lineno}:{e.colno} : {e.msg}") + return None + + if 'artifacts' in artifacts_list: + return artifacts_list['artifacts'] + + return None + +def retrieve_test_artifacts(target, artifacts_list, target_dir): + import shutil + + local_artifacts_dir = os.path.join(target_dir, "artifacts") + if os.path.isdir(local_artifacts_dir): + shutil.rmtree(local_artifacts_dir) + + os.makedirs(local_artifacts_dir) + for artifact_path in artifacts_list: + if not os.path.isabs(artifact_path): + bb.warn(f"{artifact_path} is not an absolute path") + continue + try: + dest_dir = os.path.join(local_artifacts_dir, os.path.dirname(artifact_path[1:])) + os.makedirs(dest_dir, exist_ok=True) + target.copyFrom(artifact_path, dest_dir) + except: + bb.warn(f"Can not retrieve {artifact_path} from test target") def testimage_main(d): import os @@ -402,6 +447,12 @@ def testimage_main(d): get_testimage_result_id(configuration), dump_streams=d.getVar('TESTREPORT_FULLLOGS')) results.logSummary(pn) + if not results.wasSuccessful(): + artifacts_list = load_artifacts_list(d.getVar("ARTIFACTS_LIST_PATH")) + if not artifacts_list: + bb.warn("Could not load artifacts list, skip artifacts retrieval") + else: + retrieve_test_artifacts(tc.target, artifacts_list, get_testimage_json_result_dir(d)) tc.target.stop() -- 2.40.1
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#182300): https://lists.openembedded.org/g/openembedded-core/message/182300 Mute This Topic: https://lists.openembedded.org/mt/99283034/21656 Group Owner: openembedded-core+ow...@lists.openembedded.org Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-