abort_suite.py revision de781113c3a9238899c1bb1919eb1ee5041b7acb
1#!/usr/bin/python -t 2# 3# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 4# Use of this source code is governed by a BSD-style license that can be 5# found in the LICENSE file. 6 7 8""" 9Usage: ./abort_suite.py [-i and -s you passed to run_suite.py] 10 11This code exists to allow buildbot to abort a HWTest run if another part of 12the build fails while HWTesting is going on. If we're going to fail the 13build anyway, there's no point in continuing to run tests. 14 15One can also pass just the build version to -i, to abort all boards running the 16suite against that version. ie. |./abort_suite.py -i R28-3993.0.0 -s dummy| 17would abort all boards running dummy on R28-3993.0.0. 18 19""" 20 21 22import argparse 23import getpass 24import sys 25 26import common 27from autotest_lib.server import frontend 28 29 30SUITE_JOB_NAME_TEMPLATE = '%s-test_suites/control.%s' 31 32 33def find_jobs_by_name(afe, substring): 34 """ 35 Contact the AFE to find unfinished jobs whose name contain the argument. 36 37 @param afe An instance of frontend.AFE to make RPCs with. 38 @param substring The substring to search for in the job name. 39 @return List of matching job IDs. 40 41 """ 42 # We need to avoid pulling back finished jobs, in case an overly general 43 # name to match against was passed in. Unfortunately, we can't pass 44 # `not_yet_run` and `running` at the same time, so we do it as two calls. 45 # These two calls need to be in this order in case a suite goes from queued 46 # to running in between the two calls. 47 queued_jobs = afe.run('get_jobs', not_yet_run=True, 48 name__contains=substring, owner=getpass.getuser()) 49 running_jobs = afe.run('get_jobs', running=True, 50 name__contains=substring, owner=getpass.getuser()) 51 # If a job does go from queued to running, we'll get it twice, so we need 52 # to remove duplicates. The RPC interface only accepts a list, so it is 53 # easiest if we return a list from this function. 54 job_ids = [int(job['id']) for job in queued_jobs + running_jobs] 55 return list(set(job_ids)) 56 57 58def parse_args(): 59 """ 60 Parse the arguments to this script. 61 62 @return The arguments to this script. 63 64 """ 65 parser = argparse.ArgumentParser() 66 parser.add_argument('-s', '--suite_name', dest='name') 67 parser.add_argument('-i', '--build', dest='build') 68 return parser.parse_args() 69 70 71def abort_jobs(afe, job_ids): 72 """ 73 Abort all of the HQEs associated with the given jobs. 74 75 @param afe An instance of frontend.AFE to make RPCs with. 76 @param job_ids A list of ints that are the job id's to abort. 77 @return None 78 79 """ 80 afe.run('abort_host_queue_entries', job_id__in=job_ids) 81 82 83def main(): 84 """Main.""" 85 afe = frontend.AFE() 86 args = parse_args() 87 name = SUITE_JOB_NAME_TEMPLATE % (args.build, args.name) 88 job_ids = find_jobs_by_name(afe, name) 89 print "Aborting jobs %s" % ', '.join([str(x) for x in job_ids]) 90 abort_jobs(afe, job_ids) 91 return 0 92 93 94if __name__ == '__main__': 95 sys.exit(main()) 96