blob: 0e1433b430a49a559005934bfe3f8add063d9c45 [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
mbligh532cb272007-11-26 18:54:20 +00003client_bin = os.path.join(os.path.dirname(__file__), '../client/bin')
4sys.path.insert(0, os.path.abspath(client_bin))
5from autotest_utils import read_keyval
mblighbb7b8912006-10-08 03:59:02 +00006
mblighb10a60f2007-10-17 00:03:32 +00007user = re.compile(r'user(\s*)=')
8label = re.compile(r'label(\s*)=')
mblighb85e6b02006-10-08 17:20:56 +00009
mbligh006f2302007-09-13 20:46:46 +000010debug = True
11
mbligh74fc0462007-11-05 20:24:17 +000012# XXX: these mail bits came almost verbatim from mirror/mirror and this should
13# probably be refactored into another file and used by both.
14def mail(from_address, to_addresses, cc_addresses, subject, message_text):
mbligh08415d82007-11-24 19:23:34 +000015 # if passed a string for the to_addresses convert it to a tuple
16 if type(to_addresses) is str:
17 to_addresses = (to_addresses,)
mbligh74fc0462007-11-05 20:24:17 +000018
mbligh08415d82007-11-24 19:23:34 +000019 message = email.Message.Message()
20 message["To"] = ", ".join(to_addresses)
21 message["Cc"] = ", ".join(cc_addresses)
22 message["From"] = from_address
23 message["Subject"] = subject
24 message.set_payload(message_text)
mbligh74fc0462007-11-05 20:24:17 +000025
mbligh08415d82007-11-24 19:23:34 +000026 try:
27 sendmail(message.as_string())
28 except SendmailException, e:
29 server = smtplib.SMTP("localhost")
30 server.sendmail(from_address, to_addresses, cc_addresses, message.as_string())
31 server.quit()
mbligh74fc0462007-11-05 20:24:17 +000032
33
34MAIL = "sendmail"
35
36class SendmailException(Exception):
mbligh08415d82007-11-24 19:23:34 +000037 pass
mbligh74fc0462007-11-05 20:24:17 +000038
39def sendmail(message):
mbligh08415d82007-11-24 19:23:34 +000040 """Send an email using sendmail"""
41 # open a pipe to the mail program and
42 # write the data to the pipe
43 p = os.popen("%s -t" % MAIL, 'w')
44 p.write(message)
45 exitcode = p.close()
46 if exitcode:
47 raise SendmailException("Exit code: %s" % exitcode)
mbligh74fc0462007-11-05 20:24:17 +000048
49# XXX: End of code from mirror/mirror
50
51
mblighb85e6b02006-10-08 17:20:56 +000052def shorten_patch(long):
mbligh340c9682006-10-08 18:26:08 +000053 short = os.path.basename(long)
mblighb85e6b02006-10-08 17:20:56 +000054 short = re.sub(r'^patch-', '', short)
55 short = re.sub(r'\.(bz2|gz)$', '', short)
56 short = re.sub(r'\.patch$', '', short)
57 short = re.sub(r'\+', '_', short)
58 return short
59
mblighbb7b8912006-10-08 03:59:02 +000060
mbligh006f2302007-09-13 20:46:46 +000061def dprint(info):
62 if debug:
63 sys.stderr.write(str(info) + '\n')
64
65
mblighe9cf9d42007-08-31 08:56:00 +000066class job:
mbligh532cb272007-11-26 18:54:20 +000067 def __init__(self, dir):
mblighe9cf9d42007-08-31 08:56:00 +000068 self.dir = dir
mblighe9cf9d42007-08-31 08:56:00 +000069 self.control = os.path.join(dir, "control")
mbligh237bed32007-09-05 13:05:57 +000070 self.status = os.path.join(dir, "status")
mblighbb7b8912006-10-08 03:59:02 +000071 self.variables = {}
mblighe9cf9d42007-08-31 08:56:00 +000072 self.tests = []
mblighbb7b8912006-10-08 03:59:02 +000073 self.kernel = None
74
mblighb10a60f2007-10-17 00:03:32 +000075 # Get the user + tag info from the keyval file.
mbligh8e1ab172007-09-13 17:29:56 +000076 try:
mbligh532cb272007-11-26 18:54:20 +000077 keyval = read_keyval(dir)
78 print keyval
mbligh8e1ab172007-09-13 17:29:56 +000079 except:
mbligh532cb272007-11-26 18:54:20 +000080 raise
81 keyval = {}
82 self.user = keyval.get('user', None)
83 self.label = keyval.get('label', None)
84 self.machine = keyval.get('hostname', None)
85
86 if not self.machine:
87 self.get_machine()
88
89 print 'MACHINE NAME: ' + self.machine
90 if not os.path.exists(self.status):
mbligh8e1ab172007-09-13 17:29:56 +000091 return None
92
mbligh529f2f32007-08-30 11:22:50 +000093 self.grope_status()
mblighbb7b8912006-10-08 03:59:02 +000094
95
mbligh532cb272007-11-26 18:54:20 +000096 def get_machine(self):
97 try:
98 hostname = os.path.join(dir, "sysinfo/hostname")
99 self.machine = open(hostname, 'r').readline().rstrip()
100 return
101 except:
102 pass
103 try:
104 uname = os.path.join(dir, "sysinfo/uname_-a")
105 self.machine = open(uname, 'r').readline().split()[1]
106 return
107 except:
108 pass
109
110
mblighd5c33db2006-10-08 21:34:16 +0000111 def grope_status(self):
mblighde7335d2007-09-26 16:53:20 +0000112 dprint('=====================================================')
113 dprint(self.dir)
114 dprint('=====================================================')
mbligh049f5e62007-09-30 02:00:14 +0000115 self.kernel = kernel(self.dir)
mbligh237bed32007-09-05 13:05:57 +0000116
mblighde7335d2007-09-26 16:53:20 +0000117 # NOTE: currently we don't cope with nested START / END blocks
118 group_subdir = None
mbligh237bed32007-09-05 13:05:57 +0000119 for line in open(self.status, 'r').readlines():
mblighde7335d2007-09-26 16:53:20 +0000120 dprint('STATUS: ' + line.rstrip())
121 if not re.match(r'\t*\S', line):
122 continue # ignore continuation lines
123 if re.match(r'\t*START', line):
124 group_subdir = None
125 continue # ignore start lines
126 reason = None
127 if line.startswith('END'):
128 elements = line.split(None, 4)[1:]
129 else:
130 elements = line.split(None, 3)
131 elements.append(None) # in case no reason specified
132 (status, subdir, testname, reason) = elements[0:4]
mbligh59a479f2007-11-24 19:24:05 +0000133 if testname == '----':
134 # This is a job level event, not a test
135 continue
mblighde7335d2007-09-26 16:53:20 +0000136 ################################################
137 # REMOVE THIS SECTION ONCE OLD FORMAT JOBS ARE GONE
138 ################################################
139 if re.match(r'(GOOD|FAIL|WARN) ', line):
140 (status, testname, reason) = line.split(None, 2)
141 if testname.startswith('kernel.'):
142 subdir = 'build'
143 else:
144 subdir = testname
145 if testname.startswith('completed'):
146 raise 'testname is crap'
147 ################################################
148 if subdir == '----':
149 subdir = None
150 if line.startswith('END'):
151 subdir = group_subdir
152 if line.startswith('\t'): # we're in a block group
153 if subdir:
154 group_subdir = subdir
155 continue
156 debug = str((status, subdir, testname, reason))
157 dprint('GROPE_STATUS: ' + debug)
158 if not re.match(r'(boot$|kernel\.)', testname):
159 # This is a real test
160 if subdir and subdir.count('.'):
161 # eg dbench.ext3
162 testname = subdir
163 self.tests.append(test(subdir, testname, status, reason, self.kernel, self))
164 dprint('')
mblighe9cf9d42007-08-31 08:56:00 +0000165
166
167class kernel:
mbligh049f5e62007-09-30 02:00:14 +0000168 def __init__(self, topdir):
mblighe9cf9d42007-08-31 08:56:00 +0000169 self.base = None
170 self.patches = []
mblighe9cf9d42007-08-31 08:56:00 +0000171 patch_hashes = []
mbligh049f5e62007-09-30 02:00:14 +0000172 # HACK. we don't have proper build tags in the status file yet
173 # so we hardcode build/ and do it at the start of the job
mbligh9c39d152007-11-24 19:11:58 +0000174 build_log = os.path.join(topdir, 'build/debug/build_log')
mbligh049f5e62007-09-30 02:00:14 +0000175
mbligh9c39d152007-11-24 19:11:58 +0000176 if os.path.exists(build_log):
177 for line in open(build_log, 'r'):
mbligh049f5e62007-09-30 02:00:14 +0000178 print line
179 (type, rest) = line.split(': ', 1)
180 words = rest.split()
181 if type == 'BASE':
182 self.base = words[0]
183 if type == 'PATCH':
184 print words
185 self.patches.append(patch(*words[0:]))
186 # patch_hashes.append(words[2])
mbligh9c39d152007-11-24 19:11:58 +0000187 else:
188 for sysinfo in ['sysinfo/reboot1', 'sysinfo']:
189 uname_file = os.path.join(topdir, sysinfo, 'uname_-a')
190 if not os.path.exists(uname_file):
191 continue
192 uname = open(uname_file, 'r').readline().split()
193 self.base = uname[2]
194 break
195 print 'kernel.__init__() found kernel version %s' % self.base
mbligh52f97442007-09-14 17:43:28 +0000196 if self.base:
197 self.kernel_hash = self.get_kver_hash(self.base, patch_hashes)
mblighe9cf9d42007-08-31 08:56:00 +0000198
199
mbligh237bed32007-09-05 13:05:57 +0000200 def get_kver_hash(self, base, patch_hashes):
mblighe9cf9d42007-08-31 08:56:00 +0000201 """\
202 Calculate a hash representing the unique combination of
203 the kernel base version plus
204 """
205 key_string = ','.join([base] + patch_hashes)
206 return md5.new(key_string).hexdigest()
207
208
mbligh237bed32007-09-05 13:05:57 +0000209class patch:
210 def __init__(self, spec, reference=None, hash=None):
211 # NEITHER OF THE ABOVE SHOULD HAVE DEFAULTS!!!! HACK HACK
212 if not reference:
213 reference = spec
214 print 'PATCH::%s %s %s' % (spec, reference, hash)
215 self.spec = spec
216 self.reference = reference
217 self.hash = hash
218
219
mblighe9cf9d42007-08-31 08:56:00 +0000220class test:
mblighde7335d2007-09-26 16:53:20 +0000221 def __init__(self, subdir, testname, status, reason, kernel, job):
mblighde940942007-11-05 17:25:56 +0000222 # NOTE: subdir may be none here for lines that aren't an
223 # actual test
mbligh2bd48872007-09-20 18:32:25 +0000224 self.subdir = subdir
mblighde7335d2007-09-26 16:53:20 +0000225 self.testname = testname
mblighe9cf9d42007-08-31 08:56:00 +0000226 self.status = status
227 self.reason = reason
mblighde940942007-11-05 17:25:56 +0000228 self.version = None
229 self.keyval = None
mbligh994a23d2007-10-25 15:28:58 +0000230
mblighde7335d2007-09-26 16:53:20 +0000231 if subdir:
mblighde940942007-11-05 17:25:56 +0000232 keyval = os.path.join(job.dir, subdir, 'results/keyval')
233 if os.path.exists(keyval):
234 self.keyval = keyval
235 keyval2 = os.path.join(job.dir, subdir, 'keyval')
236 if os.path.exists(keyval2):
237 self.version = open(keyval2, 'r').readline().split('=')[1]
mblighde7335d2007-09-26 16:53:20 +0000238 else:
239 self.keyval = None
mblighe9cf9d42007-08-31 08:56:00 +0000240 self.iterations = []
mbligh237bed32007-09-05 13:05:57 +0000241 self.kernel = kernel
mbligh8e1ab172007-09-13 17:29:56 +0000242 self.machine = job.machine
mblighe9cf9d42007-08-31 08:56:00 +0000243
mblighde7335d2007-09-26 16:53:20 +0000244 dprint("PARSING TEST %s %s %s" % (subdir, testname, self.keyval))
mbligh994a23d2007-10-25 15:28:58 +0000245
mblighde7335d2007-09-26 16:53:20 +0000246 if not self.keyval:
mblighe9cf9d42007-08-31 08:56:00 +0000247 return
248 count = 1
249 lines = []
250 for line in open(self.keyval, 'r').readlines():
mbligh2bd48872007-09-20 18:32:25 +0000251 if not re.search('\S', line): # blank line
mblighe9cf9d42007-08-31 08:56:00 +0000252 self.iterations.append(iteration(count, lines))
253 lines = []
254 count += 1
mblighe9cf9d42007-08-31 08:56:00 +0000255 else:
256 lines.append(line)
257 if lines:
258 self.iterations.append(iteration(count, lines))
259
260
261class iteration:
262 def __init__(self, index, lines):
263 self.index = index
264 self.keyval = {}
265
mbligh2bd48872007-09-20 18:32:25 +0000266 dprint("ADDING ITERATION %d" % index)
mblighe9cf9d42007-08-31 08:56:00 +0000267 for line in lines:
268 (key, value) = line.split('=', 1)
269 self.keyval[key] = value