blob: 9dbfbc8b6905839c62d2ea82caff526bd7488acd [file] [log] [blame]
Matthew Hartfb6fd362020-03-04 21:03:59 +00001#!/usr/bin/env python3
2
3from __future__ import print_function
4
5__copyright__ = """
6/*
7 * Copyright (c) 2020, Arm Limited. All rights reserved.
8 *
9 * SPDX-License-Identifier: BSD-3-Clause
10 *
11 */
12 """
13
14"""
15Script for waiting for LAVA jobs and parsing the results
16"""
17
18import os
19import sys
20import shutil
21import time
22import yaml
23import argparse
24import threading
25from copy import deepcopy
26from collections import OrderedDict
27from jinja2 import Environment, FileSystemLoader
28from lava_helper_configs import *
29from lava_helper import test_lava_dispatch_credentials
30
31try:
32 from tfm_ci_pylib.utils import save_json, load_json, sort_dict,\
33 load_yaml, test, print_test
34 from tfm_ci_pylib.lava_rpc_connector import LAVA_RPC_connector
35except ImportError:
36 dir_path = os.path.dirname(os.path.realpath(__file__))
37 sys.path.append(os.path.join(dir_path, "../"))
38 from tfm_ci_pylib.utils import save_json, load_json, sort_dict,\
39 load_yaml, test, print_test
40 from tfm_ci_pylib.lava_rpc_connector import LAVA_RPC_connector
41
42def wait_for_jobs(user_args):
43 job_list = user_args.job_ids.split(",")
44 job_list = [int(x) for x in job_list if x != '']
45 lava = test_lava_dispatch_credentials(user_args)
46 finished_jobs = lava.block_wait_for_jobs(job_list, user_args.dispatch_timeout, 0.5)
47 unfinished_jobs = [item for item in job_list if item not in finished_jobs]
48 for job in unfinished_jobs:
49 info_print("Cancelling unfinished job: {}".format(job))
50 lava.cancel_job(job)
51 if user_args.artifacts_path:
52 for job, info in finished_jobs.items():
53 info['job_dir'] = os.path.join(user_args.artifacts_path, "{}_{}".format(str(job), info['description']))
54 finished_jobs[job] = info
55 finished_jobs = fetch_artifacts(finished_jobs, user_args, lava)
56 print_lava_urls(finished_jobs, user_args)
57 boot_report(finished_jobs, user_args)
58 test_report(finished_jobs, user_args, lava)
59
60def fetch_artifacts(jobs, user_args, lava):
61 if not user_args.artifacts_path:
62 return
63 for job_id, info in jobs.items():
64 job_dir = info['job_dir']
65 info_print("Fetching artifacts for JOB: {} to {}".format(job_id, job_dir))
66 os.makedirs(job_dir, exist_ok=True)
67 def_path = os.path.join(job_dir, 'definition.yaml')
68 target_log = os.path.join(job_dir, 'target_log.txt')
69 config = os.path.join(job_dir, 'config.yaml')
70 definition, metadata = lava.get_job_definition(job_id, def_path)
71 jobs[job_id]['metadata'] = metadata
72 time.sleep(0.2) # be friendly to LAVA
73 lava.get_job_log(job_id, None, target_log)
74 time.sleep(0.2)
75 lava.get_job_config(job_id, config)
76 time.sleep(0.2)
77 return(jobs)
78
79
80def lava_id_to_url(id, user_args):
81 return "{}/scheduler/job/{}".format(user_args.lava_url, id)
82
83def boot_report(jobs, user_args):
84 incomplete_jobs = []
85 for job, info in jobs.items():
86 if info['health'] != 'Complete':
87 if info['error_reason'] == 'Infrastructure':
88 info_print("Job {} failed with Infrastructure error".format(job))
89 incomplete_jobs.append(job)
90 incomplete_output = [lava_id_to_url(x, user_args) for x in incomplete_jobs];
91 if len(incomplete_jobs) > 0:
92 print("BOOT_RESULT: -1 Failed: {}".format(incomplete_output))
93 else:
94 print("BOOT_RESULT: +1")
95
96def remove_lava_dupes(results):
97 for result in results:
98 if result['result'] != 'pass':
99 if result['suite'] == "lava":
100 for other in [x for x in results if x != result]:
101 if other['name'] == result['name']:
102 if other['result'] == 'pass':
103 results.remove(result)
104 return(results)
105
106def test_report(jobs, user_args, lava):
107 # parsing of test results is WIP
108 fail_j = []
109 jinja_data = []
110 for job, info in jobs.items():
111 if user_args.artifacts_path:
112 results_file = os.path.join(info['job_dir'], 'results.yaml')
113 results = lava.get_job_results(job, results_file)
114 else:
115 results = lava.get_job_results(job)
116 results = yaml.load(results)
117 #results = remove_lava_dupes(results)
118 non_lava_results = [x for x in results if x['suite'] != 'lava']
119 info['lava_url'] = lava_id_to_url(job, user_args)
120 info['artifacts_dir'] = "tf-m-ci-scripts/{}".format(info['job_dir'])
121 jinja_data.append({job: [info, non_lava_results]})
122 for result in non_lava_results:
123 if result['result'] != 'pass':
124 fail_j.append(job) if job not in fail_j else fail_j
125 time.sleep(0.5) # be friendly to LAVA
126 fail_output = [lava_id_to_url(x, user_args) for x in fail_j]
127 if len(fail_j) > 0:
128 print("TEST_RESULT: -1 Failed: {}".format(fail_output))
129 else:
130 print("TEST_RESULT: +1")
131 data = {}
132 data['jobs'] = jinja_data
133 render_jinja(data)
134
135def render_jinja(data):
136 work_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)), "jinja2_templates")
137 template_loader = FileSystemLoader(searchpath=work_dir)
138 template_env = Environment(loader=template_loader)
139 html = template_env.get_template("test_summary.jinja2").render(data)
140 csv = template_env.get_template("test_summary_csv.jinja2").render(data)
141 with open('test_summary.html', "w") as F:
142 F.write(html)
143 with open('test_summary.csv', "w") as F:
144 F.write(csv)
145
146def print_lava_urls(jobs, user_args):
147 output = [lava_id_to_url(x, user_args) for x in jobs]
148 print("LAVA jobs triggered for this build: {}".format(output))
149
150
151def info_print(line):
152 print("INFO: {}".format(line))
153
154def main(user_args):
155 """ Main logic """
156 user_args.lava_rpc = "RPC2"
157 wait_for_jobs(user_args)
158
159def get_cmd_args():
160 """ Parse command line arguments """
161
162 # Parse command line arguments to override config
163 parser = argparse.ArgumentParser(description="Lava Wait Jobs")
164 cmdargs = parser.add_argument_group("Lava Wait Jobs")
165
166 # Configuration control
167 cmdargs.add_argument(
168 "--lava-url", dest="lava_url", action="store", help="LAVA lab URL (without RPC2)"
169 )
170 cmdargs.add_argument(
171 "--job-ids", dest="job_ids", action="store", required=True, help="Comma separated list of job IDS"
172 )
173 cmdargs.add_argument(
174 "--lava-token", dest="token_secret", action="store", help="LAVA auth token"
175 )
176 cmdargs.add_argument(
177 "--lava-user", dest="token_usr", action="store", help="LAVA username"
178 )
179 cmdargs.add_argument(
180 "--use-env", dest="token_from_env", action="store_true", default=False, help="Use LAVA auth info from environment"
181 )
182 cmdargs.add_argument(
183 "--lava-timeout", dest="dispatch_timeout", action="store", type=int, default=3600, help="Time in seconds to wait for all jobs"
184 )
185 cmdargs.add_argument(
186 "--artifacts-path", dest="artifacts_path", action="store", help="Download LAVA artifacts to this directory"
187 )
188 return parser.parse_args()
189
190
191if __name__ == "__main__":
192 main(get_cmd_args())