aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur She <arthur.she@linaro.org>2015-10-17 22:53:39 -0700
committerArthur She <arthur.she@linaro.org>2015-10-17 22:53:39 -0700
commit329aa6129426668ddb7c14e7e495a727f184b6b3 (patch)
tree36a73c1c0aa9a3b631281bd89ce952353fcf8111
parent7c3752d50b921462e1441370be1ace50690adddd (diff)
1. Add argument for Jenkins URL, template file, result file.
2. process uncomplete test jobs 3. using logging module modified: report_automation.py
-rwxr-xr-xreport_automation.py177
1 files changed, 103 insertions, 74 deletions
diff --git a/report_automation.py b/report_automation.py
index f427283..e8b2cb7 100755
--- a/report_automation.py
+++ b/report_automation.py
@@ -9,17 +9,23 @@ import zipfile
import base64
import shutil
import argparse
+import logging
+from argparse import RawTextHelpFormatter
+import netrc
from StringIO import StringIO
import xml.etree.ElementTree as ET
from py3o.template import Template
from jenkinsapi.jenkins import Jenkins
CTS_RESULT_FILE_NAME = "testResult.xml"
+logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
+logger = logging.getLogger(__name__)
+#logger.setLevel(logging.INFO)
class LinaroAndroidBuildSystem(object):
def __init__(self, base_url, build_job,
username=None, password=None):
- print("Jenkins build job: %s" % build_job)
+ logger.info("Jenkins build job: %s" % build_job)
self.base_url = base_url
self.build_job = build_job
self.username = username
@@ -28,19 +34,17 @@ class LinaroAndroidBuildSystem(object):
self.jenkins = Jenkins(self.base_url, self.username, self.password)
self.project = self.jenkins[self.build_job]
except Exception as e:
- print("Can not get Jenkins job: %s" % project)
- print e
+ logger.exception("Can not get Jenkins job: %s" % project)
def get_build(self, build_no):
try:
build = self.project.get_build(build_no)
return build
except Exception as e:
- print("Can not get build: #%d" % build_no)
- print e
+ logger.exception("Can not get build: #%d" % build_no)
def get_test_job_ids(self, build_no):
- print("Querying build #%d test job ids from Jenkins build job: %s" %
+ logger.info("Querying build #%d test job ids from Jenkins build job: %s" %
(build_no, self.build_job))
job_id_list = []
build = self.get_build(build_no)
@@ -57,28 +61,32 @@ class LAVA(object):
server_url = "https://%s:%s@%sRPC2/" % (self.username, self.token, self.lava_server.split("//")[1])
self.server = xmlrpclib.ServerProxy(server_url)
except:
- print("Can not connect to LAVA server: %s" % lava_server)
+ logger.error("Can not connect to LAVA server: %s" % lava_server)
+ exit(-1)
def get_job_info(self, job_no):
job_info = {}
try:
job_status = self.server.scheduler.job_status(job_no)
- job_detail = self.server.scheduler.job_details(job_no)
- except:
- print("Can not get any information for test job: %d" % job_no)
+ except Exception as e:
+ logger.exception("Can not get any information for test job: %s" % job_no)
- job_info['job_no'] = job_no
- job_info['result_link'] = job_detail['_results_link']
- job_info['result_bundle'] = json.loads(self.server.dashboard.get(job_status['bundle_sha1'])['content'])
- if any(t['test_id'] == 'bionic_libc_tests' for t in job_info['result_bundle']['test_runs']):
- job_info['type'] = "lava_test"
- elif any(t['test_id'] == 'cts-host' for t in job_info['result_bundle']['test_runs']):
- job_info['type'] = "cts"
- elif any(t['test_id'] == 'lava-android-benchmark-target' or t['test_id'] == 'wa2-host-postprocessing'
- for t in job_info['result_bundle']['test_runs']):
- job_info['type'] = "benchmark"
+ if job_status['job_status'] != 'Complete':
+ logger.warning("!!Job #%s is not a complete job.\n\tJob status: %s!! " % (job_no, job_status['job_status']))
else:
- job_info['type'] = "other"
+ job_detail = self.server.scheduler.job_details(job_no)
+ job_info['job_no'] = job_no
+ job_info['result_link'] = job_detail['_results_link']
+ job_info['result_bundle'] = json.loads(self.server.dashboard.get(job_status['bundle_sha1'])['content'])
+ if any(t['test_id'] == 'bionic_libc_tests' for t in job_info['result_bundle']['test_runs']):
+ job_info['type'] = "lava_test"
+ elif any(t['test_id'] == 'cts-host' for t in job_info['result_bundle']['test_runs']):
+ job_info['type'] = "cts"
+ elif any(t['test_id'] == 'lava-android-benchmark-target' or t['test_id'] == 'wa2-host-postprocessing'
+ for t in job_info['result_bundle']['test_runs']):
+ job_info['type'] = "benchmark"
+ else:
+ job_info['type'] = "other"
return job_info
@@ -152,7 +160,7 @@ class Report(object):
self.kernel_version = kernel_version
def parse_lava_test(self, job_info):
- print("Parsing lava test job #%s" % job_info['job_no'])
+ logger.info("Parsing lava test job #%s" % job_info['job_no'])
lava_tests = {}
lava_tests['result_link'] = job_info['result_link']
lava_tests['test_cases'] = []
@@ -176,7 +184,7 @@ class Report(object):
self.lava_tests = lava_tests
def parse_benchmark_test(self, job_info):
- print("Parsing benchmark test job #%s" % job_info['job_no'])
+ logger.info("Parsing benchmark test job #%s" % job_info['job_no'])
benchmark_test = {}
sub_tests = []
try:
@@ -185,8 +193,7 @@ class Report(object):
t['test_id'] == 'wa2-host-postprocessing').next()
src = (s for s in test_run['software_context']['sources'] if 'test_params' in s).next()
except Exception as e:
- print("Job %s seems not be a completed job." % job_info['job_no'])
- print e
+ logger.exception("\tJob %s seems not be a completed job." % job_info['job_no'])
if test_run['test_id'] == 'lava-android-benchmark-host':
benchmark_test['test_id'] = ast.literal_eval(src['test_params'])['TEST_NAME']
else:
@@ -210,39 +217,41 @@ class Report(object):
self.benchmark_tests.append(benchmark_test)
def parse_cts(self, job_info):
- print("Parsing cts test job #%s" % job_info['job_no'])
+ logger.info("Parsing cts test job #%s" % job_info['job_no'])
+ attachment = None
try:
test_run = (r for r in job_info['result_bundle']['test_runs']
if r['test_id'] == 'cts-host').next()
attachment = (a for a in test_run['attachments']
if a['pathname'].startswith('android-cts')).next()
except Exception as e:
- print("Job %s seems not be a completed job." % job_info['job_no'])
- print e
- try:
- infile = StringIO(attachment['content'])
- outfile = StringIO()
- base64.decode(infile, outfile)
- compressed = zipfile.ZipFile(outfile)
- compressed.extractall()
- except Exception as e:
- print("Can not extract attachment: %s" % attachment['pathname'])
- print e
- CTS_TEST_RESULT_DIR = "./%s" % attachment['pathname'].split('/')[-1].split('.zip')[0]
- CTS_RESULT_FILE = "%s/%s" % (CTS_TEST_RESULT_DIR, CTS_RESULT_FILE_NAME)
- tree = ET.parse(CTS_RESULT_FILE)
- root = tree.getroot()
- for pkg in root.iter("TestPackage"):
- cts_test = {}
- cts_test['package_name'] = pkg.get('appPackageName')
- cts_test['total'] = len(pkg.findall(".//Test"))
- cts_test['passed'] = len(pkg.findall(".//Test[@result='pass']"))
- cts_test['failed'] = len(pkg.findall(".//Test[@result='fail']"))
- cts_test['skipped'] = len(pkg.findall(".//Test[@result='skip']"))
- cts_test['pass_rate'] = 100 * cts_test['passed']/cts_test['total']
- self.cts_tests['test_pkgs'].append(cts_test)
+ logger.exception("\tJob %s seems not be a completed job." % job_info['job_no'])
- shutil.rmtree(CTS_TEST_RESULT_DIR)
+ if attachment is not None:
+ try:
+ infile = StringIO(attachment['content'])
+ outfile = StringIO()
+ base64.decode(infile, outfile)
+ compressed = zipfile.ZipFile(outfile)
+ compressed.extractall()
+ except Exception as e:
+ logger.exception("\tCan not extract attachment: %s" % attachment['pathname'])
+ CTS_TEST_RESULT_DIR = "./%s" % attachment['pathname'].split('/')[-1].split('.zip')[0]
+ CTS_RESULT_FILE = "%s/%s" % (CTS_TEST_RESULT_DIR, CTS_RESULT_FILE_NAME)
+ tree = ET.parse(CTS_RESULT_FILE)
+ root = tree.getroot()
+ for pkg in root.iter("TestPackage"):
+ cts_test = {}
+ cts_test['package_name'] = pkg.get('appPackageName')
+ cts_test['total'] = len(pkg.findall(".//Test"))
+ cts_test['passed'] = len(pkg.findall(".//Test[@result='pass']"))
+ cts_test['failed'] = len(pkg.findall(".//Test[@result='fail']"))
+ cts_test['skipped'] = len(pkg.findall(".//Test[@result='skip']"))
+ cts_test['pass_rate'] = 100 * cts_test['passed']/cts_test['total']
+ self.cts_tests['test_pkgs'].append(cts_test)
+ shutil.rmtree(CTS_TEST_RESULT_DIR)
+ else:
+ logger.warning("\tNo attachment in it")
def to_dict(self):
# Calculate numbers of CTS tests
@@ -268,53 +277,73 @@ if __name__ == '__main__':
JENKINS_URL = "https://android-build.linaro.org/jenkins/"
JENKINS_JOB = "linaro-android_lcr-member-juno"
- LAVA_USERNAME = "arthur.she"
- LAVA_TOKEN = "a6eajjn85bp11n87u30oaxb11ewn687843btsdw63wc3gt10t72rqj4x3bi0bd0czuqotz8rp2w3moa5gja5r03u920f0duux10z78t7fcdslqi8omaxtnsgttgfcfs7"
REPORT_TEMPLATE = "py3o_report_juno_template.odt"
- REPORT_OUTPUT = "py3o_report_juno_output.odt"
+ REPORT_OUTPUT = "report_output.odt"
- parser = argparse.ArgumentParser()
- parser.add_argument("-job", "--jenkins_job_name", type=str, default=JENKINS_JOB,
+ parser = argparse.ArgumentParser(formatter_class=RawTextHelpFormatter,
+ description="""This script will collect all data and make a report.
+The authentication credential for LAVA server should be put in ~/.netrc
+e.g.
+ machine validation.linaro.org
+ login USERNAME
+ password AUTHENTICATION TOKEN""")
+ parser.add_argument("-u", "--jenkins-url", dest="jenkins_url", default=JENKINS_URL,
+ help="Specify the Jenkins URL. Default: %s" % JENKINS_URL)
+ parser.add_argument("-job", "--jenkins-job-name", dest="jenkins_job_name", default=JENKINS_JOB,
help="Specify the Jenkins job name. Default: %s" % JENKINS_JOB)
- parser.add_argument("-bn", "--build_no", type=int, required=True,
+ parser.add_argument("-bn", "--build-no", dest="build_no", type=int, required=True,
help="Specify the Jenkins build number")
- parser.add_argument("-a", "--manual_lava_jobs", nargs = '+',
+ parser.add_argument("-a", "--manual-lava-jobs", dest="manual_lava_jobs", nargs = '+',
help="Specify the test jobs that were submitted manually")
- parser.add_argument("-d", "--exclude_lava_jobs", nargs = '+',
+ parser.add_argument("-d", "--exclude-lava-jobs", dest="exclude_lava_jobs", nargs = '+',
help="Specify the test jobs that don't want to be included in the report")
+ parser.add_argument("-temp", "--template", dest="template_file", default=REPORT_TEMPLATE,
+ help="Specify the report template. Default: %s" % REPORT_TEMPLATE)
+ parser.add_argument("-o", "--output", dest="output_file", default=REPORT_OUTPUT,
+ help="Specify the output file name. Default: %s" % REPORT_OUTPUT)
args = parser.parse_args()
- t = Template(REPORT_TEMPLATE, REPORT_OUTPUT)
+ lava_login_info = netrc.netrc().authenticators("validation.linaro.org")
+ if lava_login_info is None:
+ logger.error("Can not get authentication credential for LAVA Server from ~/.netrc")
+ exit(-1)
+ jenkins_ligin_info = netrc.netrc().authenticators(args.jenkins_url.split('/')[2])
+ t = Template(args.template_file, args.output_file)
rep_obj = Report()
- jenkins = LinaroAndroidBuildSystem(base_url=JENKINS_URL, build_job=args.jenkins_job_name)
- lava_server = LAVA(LAVA_USERNAME, LAVA_TOKEN)
+ if jenkins_ligin_info is not None:
+ jenkins = LinaroAndroidBuildSystem(base_url=args.jenkins_url, build_job=args.jenkins_job_name,
+ username=jenkins_ligin_info[0], password=jenkins_ligin_info[2])
+ else:
+ jenkins = LinaroAndroidBuildSystem(base_url=args.jenkins_url, build_job=args.jenkins_job_name)
+ lava_server = LAVA(lava_login_info[0], lava_login_info[2])
# Query test job IDs
test_job_ids = []
test_job_ids = jenkins.get_test_job_ids(args.build_no)
if not test_job_ids:
- print("There is no test jobs in this build!")
+ logger.error("There is no test jobs in this build!")
exit(-1)
- print("Get the test job IDs:")
+ logger.info("Get the test job IDs:")
if args.exclude_lava_jobs:
test_job_ids = [id for id in test_job_ids if id not in args.exclude_lava_jobs]
if args.manual_lava_jobs:
test_job_ids.extend(args.manual_lava_jobs)
- print(test_job_ids)
- print("Going to parse these test jobs!!")
+ logger.info(test_job_ids)
+ logger.info("Going to parse these test jobs!!")
for job in test_job_ids:
job_info = {}
job_info = lava_server.get_job_info(job)
- if job_info['type'] == 'lava_test':
- rep_obj.parse_lava_test(job_info)
- elif job_info['type'] == 'benchmark':
- rep_obj.parse_benchmark_test(job_info)
- elif job_info['type'] == 'cts':
- rep_obj.parse_cts(job_info)
+ if job_info:
+ if job_info['type'] == 'lava_test':
+ rep_obj.parse_lava_test(job_info)
+ elif job_info['type'] == 'benchmark':
+ rep_obj.parse_benchmark_test(job_info)
+ elif job_info['type'] == 'cts':
+ rep_obj.parse_cts(job_info)
- print("Prepare for the report!!")
+ logger.info("Prepare for the report!!")
data = rep_obj.to_dict()
t.render(data)
- print("Done, the output report is \"%s\"" % REPORT_OUTPUT)
+ logger.info("Done, the output report is \"%s\"" % REPORT_OUTPUT)