mbligh | 770e19c | 2009-09-18 16:55:00 +0000 | [diff] [blame] | 1 | #!/usr/bin/python |
| 2 | """ |
| 3 | This script will scan an autotest server results directory for job result |
| 4 | directories that have completed and that have not yet been published on |
| 5 | a remote dashboard server matching given filtering options and for those it |
| 6 | finds it will rsync them to the tko server and mark them as published (it uses |
| 7 | a <jobdir>/.tko_published flag file to determine if a jobdir results directory |
| 8 | has been published yet). |
| 9 | """ |
| 10 | |
| 11 | import sys, os, re, optparse |
| 12 | |
| 13 | import common |
| 14 | from autotest_lib.client.common_lib import utils |
| 15 | from autotest_lib.server import frontend |
| 16 | |
| 17 | options = optparse.Values() |
| 18 | |
| 19 | USAGE="""tko-publish [options] <resultsdir> <rsync-destination-path> |
| 20 | |
| 21 | Where: |
| 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""" |
| 28 | PUBLISH_FLAGFILE = '.tko_published' |
| 29 | RSYNC_COMMAND = 'rsync -aqz "%s" "%s"' |
| 30 | |
| 31 | |
| 32 | def 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 | |
| 49 | def 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 | |
| 59 | def 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: |
lmr | 12b4558 | 2010-01-11 21:22:02 +0000 | [diff] [blame] | 68 | jobname_pattern = re.compile(options.jobname_pattern) |
mbligh | 770e19c | 2009-09-18 16:55:00 +0000 | [diff] [blame] | 69 | else: |
lmr | 12b4558 | 2010-01-11 21:22:02 +0000 | [diff] [blame] | 70 | jobname_pattern = None |
mbligh | 770e19c | 2009-09-18 16:55:00 +0000 | [diff] [blame] | 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 | |
| 93 | if __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() |