blob: 3ec753d69809e58cbd2066c913d29deb27b3b7ec [file] [log] [blame]
mblighc6b01ed2006-10-13 17:03:26 +00001#!/usr/bin/python
mbligh74fc0462007-11-05 20:24:17 +00002import os, re, md5, sys, email.Message, smtplib
mblighbb7b8912006-10-08 03:59:02 +00003
4valid_users = r'(apw|mbligh|andyw|korgtest)'
5build_stock = re.compile('build generic stock (2\.\S+)')
mblighb85e6b02006-10-08 17:20:56 +00006build_url = re.compile('build generic url \S*/linux-(2\.\d\.\d+(\.\d+)?(-rc\d+)?).tar')
mbligh340c9682006-10-08 18:26:08 +00007valid_kernel= re.compile('2\.\d\.\d+(\.\d+)?(-rc\d+)?(-(git|bk))\d+')
mblighb10a60f2007-10-17 00:03:32 +00008user = re.compile(r'user(\s*)=')
9label = re.compile(r'label(\s*)=')
mblighb85e6b02006-10-08 17:20:56 +000010
mbligh006f2302007-09-13 20:46:46 +000011debug = True
12
mbligh74fc0462007-11-05 20:24:17 +000013# XXX: these mail bits came almost verbatim from mirror/mirror and this should
14# probably be refactored into another file and used by both.
15def mail(from_address, to_addresses, cc_addresses, subject, message_text):
16 # if passed a string for the to_addresses convert it to a tuple
17 if type(to_addresses) is str:
18 to_addresses = (to_addresses,)
19
20 message = email.Message.Message()
21 message["To"] = ", ".join(to_addresses)
22 message["Cc"] = ", ".join(cc_addresses)
23 message["From"] = from_address
24 message["Subject"] = subject
25 message.set_payload(message_text)
26
27 try:
28 sendmail(message.as_string())
29 except SendmailException, e:
30 server = smtplib.SMTP("localhost")
31 server.sendmail(from_address, to_addresses, cc_addresses, message.as_string())
32 server.quit()
33
34
35MAIL = "sendmail"
36
37class SendmailException(Exception):
38 pass
39
40def sendmail(message):
41 """Send an email using sendmail"""
42 # open a pipe to the mail program and
43 # write the data to the pipe
44 p = os.popen("%s -t" % MAIL, 'w')
45 p.write(message)
46 exitcode = p.close()
47 if exitcode:
48 raise SendmailException("Exit code: %s" % exitcode)
49
50# XXX: End of code from mirror/mirror
51
52
mblighb85e6b02006-10-08 17:20:56 +000053def shorten_patch(long):
mbligh340c9682006-10-08 18:26:08 +000054 short = os.path.basename(long)
mblighb85e6b02006-10-08 17:20:56 +000055 short = re.sub(r'^patch-', '', short)
56 short = re.sub(r'\.(bz2|gz)$', '', short)
57 short = re.sub(r'\.patch$', '', short)
58 short = re.sub(r'\+', '_', short)
59 return short
60
mblighbb7b8912006-10-08 03:59:02 +000061
mbligh006f2302007-09-13 20:46:46 +000062def dprint(info):
63 if debug:
64 sys.stderr.write(str(info) + '\n')
65
66
mblighe9cf9d42007-08-31 08:56:00 +000067class job:
68 def __init__(self, dir, type):
69 self.dir = dir
mblighd5c33db2006-10-08 21:34:16 +000070 self.type = type
mblighe9cf9d42007-08-31 08:56:00 +000071 self.control = os.path.join(dir, "control")
mbligh237bed32007-09-05 13:05:57 +000072 self.status = os.path.join(dir, "status")
mblighbb7b8912006-10-08 03:59:02 +000073 self.variables = {}
mblighe9cf9d42007-08-31 08:56:00 +000074 self.tests = []
mblighbb7b8912006-10-08 03:59:02 +000075 self.kernel = None
76
mblighb10a60f2007-10-17 00:03:32 +000077 # Get the user + tag info from the keyval file.
mbligh74fc0462007-11-05 20:24:17 +000078 jobkeyval = os.path.join(os.path.dirname (dir), "keyval")
mblighb10a60f2007-10-17 00:03:32 +000079 self.user = None
80 self.label = None
81 if os.path.exists(jobkeyval):
82 for line in open(jobkeyval, 'r').readlines():
83 if user.search(line):
84 (key, value) = line.split('=', 1)
85 self.user = value.strip()
86 if label.search(line):
87 (key,value) = line.split('=', 1)
88 self.label = value.strip()
mbligh8e1ab172007-09-13 17:29:56 +000089 if not os.path.exists(self.status):
90 return None
91
92 # We should really replace this with sysinfo/hostname!
93 uname = os.path.join(dir, "sysinfo/uname_-a")
94 try:
95 self.machine = open(uname, 'r').readline().split()[1]
96 except:
97 return None
98
mbligh529f2f32007-08-30 11:22:50 +000099 self.grope_status()
mblighbb7b8912006-10-08 03:59:02 +0000100
101
mblighd5c33db2006-10-08 21:34:16 +0000102 def grope_status(self):
mblighde7335d2007-09-26 16:53:20 +0000103 dprint('=====================================================')
104 dprint(self.dir)
105 dprint('=====================================================')
mbligh049f5e62007-09-30 02:00:14 +0000106 self.kernel = kernel(self.dir)
mbligh237bed32007-09-05 13:05:57 +0000107
mblighde7335d2007-09-26 16:53:20 +0000108 # NOTE: currently we don't cope with nested START / END blocks
109 group_subdir = None
mbligh237bed32007-09-05 13:05:57 +0000110 for line in open(self.status, 'r').readlines():
mblighde7335d2007-09-26 16:53:20 +0000111 dprint('STATUS: ' + line.rstrip())
112 if not re.match(r'\t*\S', line):
113 continue # ignore continuation lines
114 if re.match(r'\t*START', line):
115 group_subdir = None
116 continue # ignore start lines
117 reason = None
118 if line.startswith('END'):
119 elements = line.split(None, 4)[1:]
120 else:
121 elements = line.split(None, 3)
122 elements.append(None) # in case no reason specified
123 (status, subdir, testname, reason) = elements[0:4]
124 ################################################
125 # REMOVE THIS SECTION ONCE OLD FORMAT JOBS ARE GONE
126 ################################################
127 if re.match(r'(GOOD|FAIL|WARN) ', line):
128 (status, testname, reason) = line.split(None, 2)
129 if testname.startswith('kernel.'):
130 subdir = 'build'
131 else:
132 subdir = testname
133 if testname.startswith('completed'):
134 raise 'testname is crap'
135 ################################################
136 if subdir == '----':
137 subdir = None
138 if line.startswith('END'):
139 subdir = group_subdir
140 if line.startswith('\t'): # we're in a block group
141 if subdir:
142 group_subdir = subdir
143 continue
144 debug = str((status, subdir, testname, reason))
145 dprint('GROPE_STATUS: ' + debug)
146 if not re.match(r'(boot$|kernel\.)', testname):
147 # This is a real test
148 if subdir and subdir.count('.'):
149 # eg dbench.ext3
150 testname = subdir
151 self.tests.append(test(subdir, testname, status, reason, self.kernel, self))
152 dprint('')
mblighe9cf9d42007-08-31 08:56:00 +0000153
154
155class kernel:
mbligh049f5e62007-09-30 02:00:14 +0000156 def __init__(self, topdir):
mblighe9cf9d42007-08-31 08:56:00 +0000157 self.base = None
158 self.patches = []
mblighe9cf9d42007-08-31 08:56:00 +0000159 patch_hashes = []
mbligh049f5e62007-09-30 02:00:14 +0000160 # HACK. we don't have proper build tags in the status file yet
161 # so we hardcode build/ and do it at the start of the job
162 builddir = os.path.join(topdir, 'build')
163
164 if not os.path.exists(builddir):
165 uname_file = os.path.join(topdir, 'sysinfo/uname_-a')
166 uname = open(uname_file, 'r').readline().split()
167 self.base = uname[2]
168 else:
169 log = os.path.join(builddir, 'debug/build_log')
170 if not os.path.exists(log):
171 return
172 for line in open(log, 'r'):
173 print line
174 (type, rest) = line.split(': ', 1)
175 words = rest.split()
176 if type == 'BASE':
177 self.base = words[0]
178 if type == 'PATCH':
179 print words
180 self.patches.append(patch(*words[0:]))
181 # patch_hashes.append(words[2])
mbligh52f97442007-09-14 17:43:28 +0000182 if self.base:
183 self.kernel_hash = self.get_kver_hash(self.base, patch_hashes)
mblighe9cf9d42007-08-31 08:56:00 +0000184
185
mbligh237bed32007-09-05 13:05:57 +0000186 def get_kver_hash(self, base, patch_hashes):
mblighe9cf9d42007-08-31 08:56:00 +0000187 """\
188 Calculate a hash representing the unique combination of
189 the kernel base version plus
190 """
191 key_string = ','.join([base] + patch_hashes)
192 return md5.new(key_string).hexdigest()
193
194
mbligh237bed32007-09-05 13:05:57 +0000195class patch:
196 def __init__(self, spec, reference=None, hash=None):
197 # NEITHER OF THE ABOVE SHOULD HAVE DEFAULTS!!!! HACK HACK
198 if not reference:
199 reference = spec
200 print 'PATCH::%s %s %s' % (spec, reference, hash)
201 self.spec = spec
202 self.reference = reference
203 self.hash = hash
204
205
mblighe9cf9d42007-08-31 08:56:00 +0000206class test:
mblighde7335d2007-09-26 16:53:20 +0000207 def __init__(self, subdir, testname, status, reason, kernel, job):
mblighde940942007-11-05 17:25:56 +0000208 # NOTE: subdir may be none here for lines that aren't an
209 # actual test
mbligh2bd48872007-09-20 18:32:25 +0000210 self.subdir = subdir
mblighde7335d2007-09-26 16:53:20 +0000211 self.testname = testname
mblighe9cf9d42007-08-31 08:56:00 +0000212 self.status = status
213 self.reason = reason
mblighde940942007-11-05 17:25:56 +0000214 self.version = None
215 self.keyval = None
mbligh994a23d2007-10-25 15:28:58 +0000216
mblighde7335d2007-09-26 16:53:20 +0000217 if subdir:
mblighde940942007-11-05 17:25:56 +0000218 keyval = os.path.join(job.dir, subdir, 'results/keyval')
219 if os.path.exists(keyval):
220 self.keyval = keyval
221 keyval2 = os.path.join(job.dir, subdir, 'keyval')
222 if os.path.exists(keyval2):
223 self.version = open(keyval2, 'r').readline().split('=')[1]
mblighde7335d2007-09-26 16:53:20 +0000224 else:
225 self.keyval = None
mblighe9cf9d42007-08-31 08:56:00 +0000226 self.iterations = []
mbligh237bed32007-09-05 13:05:57 +0000227 self.kernel = kernel
mbligh8e1ab172007-09-13 17:29:56 +0000228 self.machine = job.machine
mblighe9cf9d42007-08-31 08:56:00 +0000229
mblighde7335d2007-09-26 16:53:20 +0000230 dprint("PARSING TEST %s %s %s" % (subdir, testname, self.keyval))
mbligh994a23d2007-10-25 15:28:58 +0000231
mblighde7335d2007-09-26 16:53:20 +0000232 if not self.keyval:
mblighe9cf9d42007-08-31 08:56:00 +0000233 return
234 count = 1
235 lines = []
236 for line in open(self.keyval, 'r').readlines():
mbligh2bd48872007-09-20 18:32:25 +0000237 if not re.search('\S', line): # blank line
mblighe9cf9d42007-08-31 08:56:00 +0000238 self.iterations.append(iteration(count, lines))
239 lines = []
240 count += 1
mblighe9cf9d42007-08-31 08:56:00 +0000241 else:
242 lines.append(line)
243 if lines:
244 self.iterations.append(iteration(count, lines))
245
246
247class iteration:
248 def __init__(self, index, lines):
249 self.index = index
250 self.keyval = {}
251
mbligh2bd48872007-09-20 18:32:25 +0000252 dprint("ADDING ITERATION %d" % index)
mblighe9cf9d42007-08-31 08:56:00 +0000253 for line in lines:
254 (key, value) = line.split('=', 1)
255 self.keyval[key] = value