| #!/usr/bin/python |
| import os, re, md5, sys |
| |
| valid_users = r'(apw|mbligh|andyw|korgtest)' |
| build_stock = re.compile('build generic stock (2\.\S+)') |
| build_url = re.compile('build generic url \S*/linux-(2\.\d\.\d+(\.\d+)?(-rc\d+)?).tar') |
| valid_kernel= re.compile('2\.\d\.\d+(\.\d+)?(-rc\d+)?(-(git|bk))\d+') |
| |
| debug = True |
| |
| def shorten_patch(long): |
| short = os.path.basename(long) |
| short = re.sub(r'^patch-', '', short) |
| short = re.sub(r'\.(bz2|gz)$', '', short) |
| short = re.sub(r'\.patch$', '', short) |
| short = re.sub(r'\+', '_', short) |
| return short |
| |
| |
| def dprint(info): |
| if debug: |
| sys.stderr.write(str(info) + '\n') |
| |
| |
| class job: |
| def __init__(self, dir, type): |
| self.dir = dir |
| self.type = type |
| self.control = os.path.join(dir, "control") |
| self.status = os.path.join(dir, "status") |
| self.variables = {} |
| self.tests = [] |
| self.kernel = None |
| |
| if not os.path.exists(self.status): |
| return None |
| |
| # We should really replace this with sysinfo/hostname! |
| uname = os.path.join(dir, "sysinfo/uname_-a") |
| try: |
| self.machine = open(uname, 'r').readline().split()[1] |
| except: |
| return None |
| |
| self.grope_status() |
| |
| |
| def grope_status(self): |
| dprint('=====================================================') |
| dprint(self.dir) |
| dprint('=====================================================') |
| self.kernel = kernel(self.dir) |
| |
| # NOTE: currently we don't cope with nested START / END blocks |
| group_subdir = None |
| for line in open(self.status, 'r').readlines(): |
| dprint('STATUS: ' + line.rstrip()) |
| if not re.match(r'\t*\S', line): |
| continue # ignore continuation lines |
| if re.match(r'\t*START', line): |
| group_subdir = None |
| continue # ignore start lines |
| reason = None |
| if line.startswith('END'): |
| elements = line.split(None, 4)[1:] |
| else: |
| elements = line.split(None, 3) |
| elements.append(None) # in case no reason specified |
| (status, subdir, testname, reason) = elements[0:4] |
| ################################################ |
| # REMOVE THIS SECTION ONCE OLD FORMAT JOBS ARE GONE |
| ################################################ |
| if re.match(r'(GOOD|FAIL|WARN) ', line): |
| (status, testname, reason) = line.split(None, 2) |
| if testname.startswith('kernel.'): |
| subdir = 'build' |
| else: |
| subdir = testname |
| if testname.startswith('completed'): |
| raise 'testname is crap' |
| ################################################ |
| if subdir == '----': |
| subdir = None |
| if line.startswith('END'): |
| subdir = group_subdir |
| if line.startswith('\t'): # we're in a block group |
| if subdir: |
| group_subdir = subdir |
| continue |
| debug = str((status, subdir, testname, reason)) |
| dprint('GROPE_STATUS: ' + debug) |
| if not re.match(r'(boot$|kernel\.)', testname): |
| # This is a real test |
| if subdir and subdir.count('.'): |
| # eg dbench.ext3 |
| testname = subdir |
| self.tests.append(test(subdir, testname, status, reason, self.kernel, self)) |
| dprint('') |
| |
| |
| class kernel: |
| def __init__(self, topdir): |
| self.base = None |
| self.patches = [] |
| patch_hashes = [] |
| # HACK. we don't have proper build tags in the status file yet |
| # so we hardcode build/ and do it at the start of the job |
| builddir = os.path.join(topdir, 'build') |
| |
| if not os.path.exists(builddir): |
| uname_file = os.path.join(topdir, 'sysinfo/uname_-a') |
| uname = open(uname_file, 'r').readline().split() |
| self.base = uname[2] |
| else: |
| log = os.path.join(builddir, 'debug/build_log') |
| if not os.path.exists(log): |
| return |
| for line in open(log, 'r'): |
| print line |
| (type, rest) = line.split(': ', 1) |
| words = rest.split() |
| if type == 'BASE': |
| self.base = words[0] |
| if type == 'PATCH': |
| print words |
| self.patches.append(patch(*words[0:])) |
| # patch_hashes.append(words[2]) |
| if self.base: |
| self.kernel_hash = self.get_kver_hash(self.base, patch_hashes) |
| |
| |
| def get_kver_hash(self, base, patch_hashes): |
| """\ |
| Calculate a hash representing the unique combination of |
| the kernel base version plus |
| """ |
| key_string = ','.join([base] + patch_hashes) |
| return md5.new(key_string).hexdigest() |
| |
| |
| class patch: |
| def __init__(self, spec, reference=None, hash=None): |
| # NEITHER OF THE ABOVE SHOULD HAVE DEFAULTS!!!! HACK HACK |
| if not reference: |
| reference = spec |
| print 'PATCH::%s %s %s' % (spec, reference, hash) |
| self.spec = spec |
| self.reference = reference |
| self.hash = hash |
| |
| |
| class test: |
| def __init__(self, subdir, testname, status, reason, kernel, job): |
| self.subdir = subdir |
| self.testname = testname |
| self.status = status |
| self.reason = reason |
| if subdir: |
| self.keyval = os.path.join(job.dir, subdir, 'results/keyval') |
| if not os.path.exists(self.keyval): |
| self.keyval = None |
| else: |
| self.keyval = None |
| self.iterations = [] |
| self.kernel = kernel |
| self.machine = job.machine |
| |
| dprint("PARSING TEST %s %s %s" % (subdir, testname, self.keyval)) |
| if not self.keyval: |
| return |
| count = 1 |
| lines = [] |
| for line in open(self.keyval, 'r').readlines(): |
| if not re.search('\S', line): # blank line |
| self.iterations.append(iteration(count, lines)) |
| lines = [] |
| count += 1 |
| else: |
| lines.append(line) |
| if lines: |
| self.iterations.append(iteration(count, lines)) |
| |
| |
| class iteration: |
| def __init__(self, index, lines): |
| self.index = index |
| self.keyval = {} |
| |
| dprint("ADDING ITERATION %d" % index) |
| for line in lines: |
| (key, value) = line.split('=', 1) |
| self.keyval[key] = value |