OK, I completed my fedfind/wikitcms conversion patch for openqa_fedora_tools. I also fixed up some of the test case submission data bits - they broke with relval report-auto (instead of jskladan's version of non-interactive result submission) because they didn't quite grok the 'test instance' concept report-auto follows.
Note this needs the very latest git wikitcms. I don't think latest relval or fedfind is strictly required, but may as well bump them anyway. I've installed the current wikitcms on fedora-qa-01. I will cut new releases tomorrow. I have tested this on fedora-qa-01, it ran and submitted a full set of results for 2015-02-07. I believe it should work for Branched nightlies (if we wind up nominating any) and TC/RC builds also, which is a significant win. I did test this a bit: https://fedora-qa-01.lab.bos.redhat.com/tests/15 is a one-job run against F21 Final RC5, you can see it successfully got the ISO and started the test but the test fails because the 'Timbuktu' screen isn't there. I revised the openqa_trigger.py CLI to use argparse; it has the same basic modes as before but the syntax is a bit different. 'openqa_trigger.py current' runs against the 'current' compose event if it has not already done so (what just plain 'openqa_trigger.py' did before). 'openqa_trigger.py event' takes the same 'version id' arguments as 'relval report-auto' and runs tasks (but does not automatically report results) against the specified compose (what you used to get by passing args, approximately, but much more robust and capable). The basic approach is that openqa_trigger gets a ValidationEvent from python-wikitcms - either the Wiki.current_event property for 'current', or the event specified, obtained via the newly-added Wiki.get_validation_event(), for 'event'. For 'event' it then just goes ahead and runs the jobs and prints the IDs. For 'current' it checks the last run compose version for each arch and runs if needed, as before. The ValidationEvent's 'sortname' property is the value written out to PERSISTENT to track the 'last run' - this property is intended to always sort compose events 'correctly', so we should always run when appropriate even when going from Rawhide to Branched, Branched to a TC, TC to RC, RC to (next milestone) TC. On both paths it gets a fedfind.Release object via the ValidationEvent - ValidationEvents have a ff_release property which is the fedfind.Release object that matches that event. It then queries fedfind for image locations using a query that tries to get just *one* generic-ish network install image for each arch. It passes the location to download_image(), which is just download_rawhide_iso() renamed and does the same job, only it can be simpler now. >From there it works pretty much as before, except we use the ValidationEvent's 'version' property as the BUILD setting for OpenQA, and report_job_results get_relval_commands() is tweaked slightly to parse this properly to produce a correct report-auto command. Probably the most likely bits to break here are the sortname thing (see wikitcms helpers.py fedora_release_sort(), it's pretty stupid, I should re-write it) and the image query, which might wind up getting more than one image depending on how exactly the F22 Alpha composes look. I'll keep a close eye on that. We can always take the list from fedfind and further filter it so we have just one image per arch. Image objects have a .arch attribute so this will be easy to do if necessary. I *could* give the fedfind query code a 'I'm feeling lucky'- ish mode to only return one image per (whatever), but not sure if that would be too specialized, I'll think about it. Please do ask any questions :) -- Adam Williamson Fedora QA Community Monkey IRC: adamw | Twitter: AdamW_Fedora | XMPP: adamw AT happyassassin . net http://www.happyassassin.net
From 55d5d1b4ce4bfd7ae7c239c8aca03bceee2f1f06 Mon Sep 17 00:00:00 2001 From: Adam Williamson <[email protected]> Date: Thu, 12 Feb 2015 19:32:27 -0800 Subject: [PATCH 1/3] use python-wikitcms and fedfind to handle events and images This removes a bunch of template-y bits that fedfind does better, and should make things work for all validation events. The CLI for openqa_trigger is completely redone to use argparse and check values and stuff. The syntax for the event sub-command is purposely similar to relval report-auto. Note this requires wikitcms changes currently in git master. --- tools/openqa_trigger/openqa_trigger.py | 159 +++++++++++++++++++---------- tools/openqa_trigger/report_job_results.py | 7 +- 2 files changed, 108 insertions(+), 58 deletions(-) diff --git a/tools/openqa_trigger/openqa_trigger.py b/tools/openqa_trigger/openqa_trigger.py index 9406d0c..7424c8b 100755 --- a/tools/openqa_trigger/openqa_trigger.py +++ b/tools/openqa_trigger/openqa_trigger.py @@ -7,15 +7,15 @@ import urlgrabber import os.path import sys import subprocess +import argparse +import wikitcms.wiki +import fedfind.release from report_job_results import report_results PERSISTENT = "/var/tmp/openqa_watcher.json" -CURRENT_TEST = "https://fedoraproject.org/wiki/Test_Results:Current_Installation_Test" -ISO_URL = "https://kojipkgs.fedoraproject.org/mash/rawhide-%s/rawhide/%s/os/images/boot.iso" -ISO_REGEX = re.compile(r'https://kojipkgs\.fedoraproject\.org/mash/(?P<name>rawhide-(?P<build>\d+))/rawhide/(?P<arch>x86_64|i386)/os/images/boot\.iso') ISO_PATH = "/var/lib/openqa/factory/iso/" -RUN_COMMAND = "/var/lib/openqa/script/client isos post ISO=%s DISTRI=fedora VERSION=rawhide FLAVOR=server ARCH=%s BUILD=%s_%s" +RUN_COMMAND = "/var/lib/openqa/script/client isos post ISO=%s DISTRI=fedora VERSION=rawhide FLAVOR=server ARCH=%s BUILD=%s" VERSIONS = ['i386', 'x86_64'] # read last tested version from file @@ -33,27 +33,27 @@ def read_last(): result[version] = json_parsed.get(version, None) return result, json_parsed -# read current version from Current Installation Test page -def read_currents(): - page = urllib2.urlopen(CURRENT_TEST).read() - f_regex = re.compile(r'<title>.*Fedora (?P<version>\d+).*</title>') - m = f_regex.search(page) - for match in ISO_REGEX.finditer(page): - yield m.group('version'), match.group("build"), match.group(0), match.group("name"), match.group("arch") - -# download rawhide iso from koji -def download_rawhide_iso(link, name, arch): - isoname = "%s_%s.iso" % (name, arch) +def download_image(image, event): + """Download a given image with a name that should be unique for + this event and arch (until we start testing different images + for the same event and arch). Returns the filename of the image + (not the path). + """ + isoname = "{0}_{1}.iso".format(event.version.replace(' ', '_'), image.arch) filename = os.path.join(ISO_PATH, isoname) if not os.path.isfile(filename): - link = "http://" + link[len("https://"):] - urlgrabber.urlgrab(link, filename) + # Icky hack around a urlgrabber bug: + # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=715416 + urlgrabber.urlgrab(image.url.replace('https', 'http'), filename) return isoname -# run OpenQA 'isos' job on selected isoname, with given arch and build -# returns list of job IDs -def run_openqa_jobs(isoname, arch, fedora_version, build): - command = RUN_COMMAND % (isoname, arch, fedora_version, build) +def run_openqa_jobs(isoname, arch, event_version): + """# run OpenQA 'isos' job on selected isoname, with given arch + and event version as the 'build'. **NOTE**: the 'build' is parsed + back into the 'relval report-auto' arguments later. Using + event.version makes sure this works. Returns list of job IDs + """ + command = RUN_COMMAND % (isoname, arch, event_version.replace(' ', '_')) # starts OpenQA jobs output = subprocess.check_output(command.split()) @@ -70,28 +70,20 @@ def run_openqa_jobs(isoname, arch, fedora_version, build): else: return [] -# run OpenQA on rawhide if there is newer version since last run -def run_if_newer(): +# run OpenQA on current compose if it is newer version since last run +def run_current(args, wiki): last_versions, json_parsed = read_last() - jobs = [] - - # for every architecture - for f_version, current_version, link, name, arch in read_currents(): - # don't run when there is newer version + currev = wiki.current_event + print("Current event: {0}".format(currev.version)) + runarches = [] + for arch in VERSIONS: last_version = last_versions.get(arch, None) - print f_version, current_version, link, name, arch, - if last_version is not None and (last_version >= current_version): - print " - Skipped" - continue - - print "" - - json_parsed[arch] = current_version - - isoname = download_rawhide_iso(link, name, arch) - job_ids = run_openqa_jobs(isoname, arch, f_version, current_version) - - jobs.extend(job_ids) + if last_version and last_version >= currev.sortname: + print("Skipped: {0}".format(arch)) + else: + runarches.append(arch) + json_parsed[arch] = currev.sortname + jobs = jobs_from_event(currev, runarches) # write info about latest versions f = open(PERSISTENT, "w") @@ -101,18 +93,81 @@ def run_if_newer(): # wait for jobs to finish and display results print jobs report_results(jobs) + sys.exit() +# run OpenQA on a specified event (don't update 'current' records +# or report results) +def run_event(args, wiki): + try: + event = wiki.get_validation_event( + args.release, args.build, args.version) + except ValueError as err: + sys.exit(err[0]) + if args.arch: + print(jobs_from_event(event, [args.arch])) + else: + print(jobs_from_event(event)) + sys.exit() + +def jobs_from_event(event, arches=VERSIONS): + """Given a python-wikitcms ValidationEvent, find the ISOs we want + and run jobs on them. arches is an iterable of arches to run on, + if not specified, we'll use our constant.""" + # Find boot.iso images for our arches; third query is a bit of a + # bodge till I know what 22 TCs/RCs will actually look like, + # ideally we want a query that will reliably return one image per + # arch without us having to filter further, but we can always just + # take the first image for each arch if necessary + jobs = [] + queries = ( + fedfind.release.Query('imagetype', ('boot',)), + fedfind.release.Query('arch', arches), + fedfind.release.Query('payload', ('server', 'generic'))) + + for image in event.ff_release.find_images(queries): + print("{0} {1}".format(image.url, image.desc)) + isoname = download_image(image, event) + job_ids = run_openqa_jobs(isoname, image.arch, event.version) + jobs.extend(job_ids) + return jobs if __name__ == "__main__": - if len(sys.argv) == 1: - run_if_newer() - elif len(sys.argv) == 3: - version = sys.argv[1] - arch = sys.argv[2] - name = "rawhide-%s" % version - link = ISO_URL % (sys.argv[1], sys.argv[2]) - isoname = download_rawhide_iso(link, name, arch) - job_ids = run_openqa_jobs(isoname, arch, "", version) - print job_ids + test_help = "Operate on the staging wiki (for testing)" + parser = argparse.ArgumentParser(description=( + "Run OpenQA tests for a release validation test event.")) + subparsers = parser.add_subparsers() + + parser_current = subparsers.add_parser( + 'current', description="Run for the current event, if needed.") + parser_current.add_argument( + '-t', '--test', help=test_help, required=False, action='store_true') + parser_current.set_defaults(func=run_current) + + parser_event = subparsers.add_parser( + 'event', description="Run for a specific event.") + parser_event.add_argument( + '-r', '--release', type=int, required=True, choices=range(12, 100), + metavar="12-99", help="Release number of a specific compose to run " + "against.") + parser_event.add_argument( + '-b', '--build', help="The build to run for; either a milestone " + "(for a TC/RC), or 'Rawhide' or 'Branched' (for a nightly build)", + required=True, + choices=['Alpha', 'Beta', 'Final', 'Branched', 'Rawhide']) + parser_event.add_argument( + '-v', '--version', help="The version to run for; either the compose " + "(for a TC/RC), or the date (for a nightly build)", required=True, + metavar="{T,R}C1-19 or YYYYMMDD") + parser_event.add_argument( + '-a', '--arch', help="The arch to run for", required=False, + choices=('x86_64', 'i386')) + parser_event.add_argument( + '-t', '--test', help=test_help, required=False, action='store_true') + parser_event.set_defaults(func=run_event) + + args = parser.parse_args() + if args.test: + wiki = wikitcms.wiki.Wiki(('https', 'stg.fedoraproject.org'), '/w/') else: - print "%s [rawhide_version arch]" % sys.arv[0] + wiki = wikitcms.wiki.Wiki(('https', 'fedoraproject.org'), '/w/') + args.func(args, wiki) diff --git a/tools/openqa_trigger/report_job_results.py b/tools/openqa_trigger/report_job_results.py index 31436a6..a617562 100644 --- a/tools/openqa_trigger/report_job_results.py +++ b/tools/openqa_trigger/report_job_results.py @@ -46,12 +46,7 @@ def get_relval_commands(passed_testcases): for key in passed_testcases: cmd_ = relval_template version, _, build, arch = key - - if version == 'rawhide': - cmd_ += ' --release "%s" --build Rawhide --version "%s"' % tuple(build.split('_')) #"22_20150110" - elif version == 'branched': - #cmd_ += ' --release "%s" --milestone "%s" --compose "%s"' % tuple(build.split('_')) #"22_Alpha_TC1" - continue + cmd_ += ' --release "%s" --build %s --version "%s"' % tuple(build.split('_')) for tc_name in passed_testcases[key]: testcase = conf_test_suites.TESTCASES[tc_name] -- 2.3.0
From 2e530cb275e7021c54fdc9a32d54fa99c0a645f6 Mon Sep 17 00:00:00 2001 From: Adam Williamson <[email protected]> Date: Fri, 13 Feb 2015 03:55:13 -0800 Subject: [PATCH 2/3] add a comment --- tools/openqa_trigger/openqa_trigger.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/openqa_trigger/openqa_trigger.py b/tools/openqa_trigger/openqa_trigger.py index 7424c8b..a6fdbe0 100755 --- a/tools/openqa_trigger/openqa_trigger.py +++ b/tools/openqa_trigger/openqa_trigger.py @@ -39,6 +39,10 @@ def download_image(image, event): for the same event and arch). Returns the filename of the image (not the path). """ + # We don't *really* need to pass in event and use event.version + # here, but as we're quite strongly tied to a validation event + # and we use it as an identifier elsewhere, using it here too + # keeps things consistent. isoname = "{0}_{1}.iso".format(event.version.replace(' ', '_'), image.arch) filename = os.path.join(ISO_PATH, isoname) if not os.path.isfile(filename): -- 2.3.0
From 61f5e61d097fa585c3bb815e22aa56e0348a83bb Mon Sep 17 00:00:00 2001 From: Adam Williamson <[email protected]> Date: Fri, 13 Feb 2015 03:55:20 -0800 Subject: [PATCH 3/3] tweak the test cases a bit: fixed the wikitcms bug I fixed the column name parsing issue commented here. Also, for the Default boot and install tests, QA:Testcase_Boot_ default_install is the 'test case', 'Server offline' or 'Server netinst' is the 'test name' (--testcase and --testname arguments to relval report-auto). I was nice in relval and made it try a 'test name' match for --testcase if there's no 'test case' match, so since these names are unique within the 'Default boot and install' section we can get away with this for now. We may need to be able to pass both --testcase and --testname with different values at some point, though, at which point this will need re-thinking. --- tools/openqa_trigger/conf_test_suites.py | 38 ++++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/tools/openqa_trigger/conf_test_suites.py b/tools/openqa_trigger/conf_test_suites.py index c136410..fd19714 100644 --- a/tools/openqa_trigger/conf_test_suites.py +++ b/tools/openqa_trigger/conf_test_suites.py @@ -1,10 +1,10 @@ TESTCASES = { - "QA:Testcase_Boot_default_install Server offline": { + "Server offline": { "section": 'Default boot and install', "env": "$RUNARCH$", "type": "Installation", }, - "QA:Testcase_Boot_default_install Server netinst": { + "Server netinst": { "section": 'Default boot and install', "env": "$RUNARCH$", "type": "Installation", @@ -16,7 +16,7 @@ TESTCASES = { }, "QA:Testcase_partitioning_guided_empty": { "section": "Guided storage configuration", - "env": "x86", # Probably a bug in relval - column name is "x86 BIOS", but there is a comment there just behind 'x86' which probably makes it strip the rest + "env": "x86 BIOS", "type": "Installation", }, "QA:Testcase_Anaconda_User_Interface_Graphical": { @@ -36,7 +36,7 @@ TESTCASES = { }, "QA:Testcase_partitioning_guided_delete_all": { "section": "Guided storage configuration", - "env": "x86", # Probably a bug in relval - column name is "x86 BIOS", but there is a comment there just behind 'x86' which probably makes it strip the rest + "env": "x86 BIOS", "type": "Installation", }, "QA:Testcase_install_to_SATA": { @@ -46,7 +46,7 @@ TESTCASES = { }, "QA:Testcase_partitioning_guided_multi_select": { "section": "Guided storage configuration", - "env": "x86", # Probably a bug in relval - column name is "x86 BIOS", but there is a comment there just behind 'x86' which probably makes it strip the rest + "env": "x86 BIOS", "type": "Installation", }, "QA:Testcase_install_to_SCSI": { @@ -71,17 +71,17 @@ TESTCASES = { }, "QA:Testcase_install_repository_Mirrorlist_graphical": { "section": "Installation repositories", - "env": "result", + "env": "Result", "type": "Installation", }, "QA:Testcase_install_repository_HTTP/FTP_graphical": { "section": "Installation repositories", - "env": "result", + "env": "Result", "type": "Installation", }, "QA:Testcase_install_repository_HTTP/FTP_variation": { "section": "Installation repositories", - "env": "result", + "env": "Result", "type": "Installation", }, "QA:Testcase_Package_Sets_Minimal_Package_Install": { @@ -91,7 +91,7 @@ TESTCASES = { }, "QA:Testcase_partitioning_guided_encrypted": { "section": "Guided storage configuration", - "env": "x86", # Probably a bug in relval - column name is "x86 BIOS", but there is a comment there just behind 'x86' which probably makes it strip the rest + "env": "x86 BIOS", "type": "Installation", }, "QA:Testcase_partitioning_guided_delete_partial": { @@ -109,7 +109,7 @@ TESTCASES = { TESTSUITES = { "server_simple":[ - "QA:Testcase_Boot_default_install Server netinst", + "Server netinst", "QA:Testcase_install_to_VirtIO", "QA:Testcase_partitioning_guided_empty", "QA:Testcase_Anaconda_User_Interface_Graphical", @@ -117,7 +117,7 @@ TESTSUITES = { "QA:Testcase_Package_Sets_Minimal_Package_Install", ], "server_delete_pata":[ - "QA:Testcase_Boot_default_install Server netinst", + "Server netinst", "QA:Testcase_install_to_PATA", "QA:Testcase_partitioning_guided_delete_all", "QA:Testcase_Anaconda_User_Interface_Graphical", @@ -125,7 +125,7 @@ TESTSUITES = { "QA:Testcase_Package_Sets_Minimal_Package_Install", ], "server_sata_multi":[ - "QA:Testcase_Boot_default_install Server netinst", + "Server netinst", "QA:Testcase_install_to_SATA", "QA:Testcase_partitioning_guided_multi_select", "QA:Testcase_Anaconda_User_Interface_Graphical", @@ -133,7 +133,7 @@ TESTSUITES = { "QA:Testcase_Package_Sets_Minimal_Package_Install", ], "server_scsi_updates_img":[ - "QA:Testcase_Boot_default_install Server netinst", + "Server netinst", "QA:Testcase_install_to_SCSI", "QA:Testcase_partitioning_guided_empty", "QA:Testcase_Anaconda_updates.img_via_URL", @@ -148,7 +148,7 @@ TESTSUITES = { "QA:Testcase_Kickstart_Http_Server_Ks_Cfg", ], "server_mirrorlist_graphical":[ - "QA:Testcase_Boot_default_install Server netinst", + "Server netinst", "QA:Testcase_install_to_VirtIO", "QA:Testcase_partitioning_guided_empty", "QA:Testcase_Anaconda_User_Interface_Graphical", @@ -157,7 +157,7 @@ TESTSUITES = { "QA:Testcase_Package_Sets_Minimal_Package_Install", ], "server_repository_http_graphical":[ - "QA:Testcase_Boot_default_install Server netinst", + "Server netinst", "QA:Testcase_install_to_VirtIO", "QA:Testcase_partitioning_guided_empty", "QA:Testcase_Anaconda_User_Interface_Graphical", @@ -166,7 +166,7 @@ TESTSUITES = { "QA:Testcase_Package_Sets_Minimal_Package_Install", ], "server_repository_http_variation":[ - "QA:Testcase_Boot_default_install Server netinst", + "Server netinst", "QA:Testcase_install_to_VirtIO", "QA:Testcase_partitioning_guided_empty", "QA:Testcase_Anaconda_User_Interface_Graphical", @@ -175,7 +175,7 @@ TESTSUITES = { "QA:Testcase_Package_Sets_Minimal_Package_Install", ], "server_mirrorlist_http_variation":[ - "QA:Testcase_Boot_default_install Server netinst", + "Server netinst", "QA:Testcase_install_to_VirtIO", "QA:Testcase_partitioning_guided_empty", "QA:Testcase_Anaconda_User_Interface_Graphical", @@ -184,7 +184,7 @@ TESTSUITES = { "QA:Testcase_Package_Sets_Minimal_Package_Install", ], "server_simple_encrypted": [ - "QA:Testcase_Boot_default_install Server netinst", + "Server netinst", "QA:Testcase_install_to_VirtIO", "QA:Testcase_partitioning_guided_empty", "QA:Testcase_Anaconda_User_Interface_Graphical", @@ -193,7 +193,7 @@ TESTSUITES = { "QA:Testcase_partitioning_guided_encrypted", ], "server_delete_partial": [ - "QA:Testcase_Boot_default_install Server netinst", + "Server netinst", "QA:Testcase_install_to_VirtIO", "QA:Testcase_partitioning_guided_delete_partial" "QA:Testcase_Anaconda_User_Interface_Graphical", -- 2.3.0
_______________________________________________ qa-devel mailing list [email protected] https://admin.fedoraproject.org/mailman/listinfo/qa-devel
