createhdds/openqa_trigger/report_job_results.py
Adam Williamson 5c9d7142d5 report_job_results: handle cancelled jobs
Summary:
Cancelled jobs have their own state (at least in the openQA
running on happyassassin, they do). This causes r_j_r to get
stuck forever if any of the jobs are cancelled. Consider a
cancelled job 'done'.

Test Plan:
Try submitting results for a set of jobs that includes one or
more cancelled jobs. It should now work (before it would get
stuck).

Reviewers: jskladan, garretraziel

Reviewed By: garretraziel

Subscribers: tflink

Differential Revision: https://phab.qadevel.cloud.fedoraproject.org/D492
2015-08-10 11:10:57 -07:00

104 lines
4.0 KiB
Python

import argparse
import sys
import time
import logging
import conf_test_suites
from operator import attrgetter
from openqa_client.client import OpenQA_Client
from wikitcms.wiki import Wiki, ResTuple
SLEEPTIME = 60
logger = logging.getLogger(__name__)
def get_passed_testcases(job_ids, client):
"""
job_ids ~ list of int (job ids)
Returns ~ list of str - names of passed testcases
"""
running_jobs = dict([(job_id, "jobs/%s" % job_id) for job_id in job_ids])
logger.info("running jobs: %s", running_jobs)
finished_jobs = {}
while running_jobs:
for job_id, url in running_jobs.items():
output = client.openqa_request('GET', url)
job_state = output['job']
if job_state['state'] in ('done', 'cancelled'):
logger.info("job %s is done", job_id)
finished_jobs[job_id] = job_state
del running_jobs[job_id]
if running_jobs:
time.sleep(SLEEPTIME)
logger.info("all jobs finished")
passed_testcases = set()
for job_id in job_ids:
job = finished_jobs[job_id]
if job['result'] == 'passed':
(release, milestone, compose) = job['settings']['BUILD'].split('_')
testsuite = job['settings']['TEST']
arch = job['settings']['ARCH']
flavor = job['settings']['FLAVOR']
for testcase in conf_test_suites.TESTSUITES[testsuite]:
# each 'testsuite' is a list using testcase names to indicate which Wikitcms tests
# have passed if this job passes. Each testcase name is the name of a dict in the
# TESTCASES dict-of-dicts which more precisely identifies the 'test instance' (when
# there is more than one for a testcase) and environment for which the result
# should be filed.
uniqueres = conf_test_suites.TESTCASES[testcase]
testname = ''
if 'name_cb' in uniqueres:
testname = uniqueres['name_cb'](flavor)
env = arch if uniqueres['env'] == '$RUNARCH$' else uniqueres['env']
result = ResTuple(
testtype=uniqueres['type'], release=release, milestone=milestone,
compose=compose, testcase=testcase, section=uniqueres['section'],
testname=testname, env=env, status='pass', bot=True)
passed_testcases.add(result)
return sorted(list(passed_testcases), key=attrgetter('testcase'))
def report_results(job_ids, client, verbose=False, report=True):
passed_testcases = get_passed_testcases(job_ids, client)
if verbose:
for restup in passed_testcases:
print restup
logger.info("passed testcases: %s", passed_testcases)
if report:
if verbose:
print "Reporting test passes:"
logger.info("reporting test passes")
wiki = Wiki()
wiki.login()
if not wiki.logged_in:
logger.error("could not log in to wiki")
sys.exit("Could not log in to wiki!")
# Submit the results
(insuffs, dupes) = wiki.report_validation_results(passed_testcases)
for dupe in dupes:
tmpl = "already reported result for test %s, env %s! Will not report dupe."
if verbose:
print tmpl % (dupe.testcase, dupe.env)
logger.info(tmpl, dupe.testcase, dupe.env)
else:
if verbose:
print "\n\n### No reporting is done! ###\n\n"
logger.warning("no reporting is done")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Evaluate per-testcase results from OpenQA job "
"runs")
parser.add_argument('jobs', type=int, nargs='+')
parser.add_argument('--report', default=False, action='store_true')
args = parser.parse_args()
client = OpenQA_Client() # uses first server from ~/.config/openqa/client.conf
report_results(args.jobs, client, verbose=True, report=args.report)