1#!/usr/bin/python 2""" 3This script will scan an autotest server results directory for job result 4directories that have completed and that have not yet been published on 5a remote dashboard server matching given filtering options and for those it 6finds it will rsync them to the tko server and mark them as published (it uses 7a <jobdir>/.tko_published flag file to determine if a jobdir results directory 8has been published yet). 9""" 10 11import sys, os, re, optparse 12 13import common 14from autotest_lib.client.common_lib import utils 15from autotest_lib.server import frontend 16 17options = optparse.Values() 18 19USAGE="""tko-publish [options] <resultsdir> <rsync-destination-path> 20 21Where: 22<resultsdir> A path to the directory having the job results 23 directories to publish. 24 25<rsync-destination-path> A valid rsync destination path where to upload the 26 job result directories. 27 Example: user@machine.org:/home/autotest/results""" 28PUBLISH_FLAGFILE = '.tko_published' 29RSYNC_COMMAND = 'rsync -aqz "%s" "%s"' 30 31 32def get_job_dirs(path): 33 regex = re.compile('[1-9][0-9]*-') 34 jobdirs = [] 35 36 for dir in os.listdir(path): 37 # skip directories not matching the job result dir pattern 38 if not regex.match(dir): 39 continue 40 41 dir = os.path.join(options.resultsdir, dir) 42 if (os.path.isdir(dir) 43 and not os.path.exists(os.path.join(dir, PUBLISH_FLAGFILE))): 44 jobdirs.append(dir) 45 46 return jobdirs 47 48 49def publish_job(jobdir): 50 cmd = RSYNC_COMMAND % (jobdir, options.dest) 51 utils.system(cmd) 52 53 # mark the jobdir as published 54 fd = open(os.path.join(jobdir, PUBLISH_FLAGFILE), 'w') 55 fd.close() 56 print 'Published', jobdir 57 58 59def main(): 60 jobdirs = get_job_dirs(options.resultsdir) 61 62 afe = frontend.AFE() 63 # the way AFE API is right now is to give a whole list of jobs and can't 64 # get specific jobs so minimize the queries caching the result 65 finished_jobs = afe.get_jobs(finished=True) 66 67 if options.jobname_pattern: 68 jobname_pattern = re.compile(options.jobname_pattern) 69 else: 70 jobname_pattern = None 71 72 # for each unpublished possible jobdir find it in the database and see 73 # if it is completed 74 for jobdir in jobdirs: 75 job_id = int(os.path.basename(jobdir).split('-')[0]) 76 job = [job for job in finished_jobs if job.id == job_id] 77 78 if len(job) != 1: 79 continue 80 81 if jobname_pattern: 82 # does it match the jobname pattern? 83 if not jobname_pattern.match(job[0].name): 84 continue 85 86 # does it match the wanted job owner 87 if options.job_owner and options.job_owner != job[0].owner: 88 continue 89 90 publish_job(jobdir) 91 92 93if __name__ == '__main__': 94 parser = optparse.OptionParser(usage=USAGE) 95 parser.add_option('--jobname-pattern', dest='jobname_pattern', 96 help='Regexp pattern to match against job names, by ' 97 "default there won't be any matching done", 98 default=None) 99 parser.add_option('--job-owner', dest='job_owner', default=None, 100 help='Job owner username to match against for the ' 101 'published jobs, by default no matching is done.') 102 options, args = parser.parse_args() 103 104 if len(args) < 2: 105 print USAGE 106 sys.exit(-1) 107 108 options.resultsdir = args[0] 109 options.dest = args[1] 110 main() 111