blob: 92f2d2af35e9317ca121337711f2fcbd1a738ce2 [file] [log] [blame]
mblighaf25f062007-12-03 17:48:35 +00001import re, os, sys, types
mblighd5c33db2006-10-08 21:34:16 +00002
mblighaf25f062007-12-03 17:48:35 +00003class db_sql:
mbligh2bb6dfd2008-01-10 16:38:30 +00004 def __init__(self, debug = False, autocommit=True, host = None,
5 database = None, user = None, password = None):
mbligh8e1ab172007-09-13 17:29:56 +00006 self.debug = debug
mbligh432bad42007-10-09 19:56:07 +00007 self.autocommit = autocommit
mbligha218d112007-10-03 20:15:09 +00008
mbligh6f075f02008-01-25 16:36:16 +00009 path = os.path.dirname(__file__)
mblighb32cd432007-09-25 18:20:04 +000010 try:
mbligha218d112007-10-03 20:15:09 +000011 file = os.path.join(path, '.database')
mbligh432bad42007-10-09 19:56:07 +000012 db_prefs = open(file, 'r')
mbligh73f38a32008-02-21 16:21:35 +000013 file_host = db_prefs.readline().rstrip()
14 file_database = db_prefs.readline().rstrip()
mbligh2bb6dfd2008-01-10 16:38:30 +000015 if not host:
mbligh73f38a32008-02-21 16:21:35 +000016 host = file_host
mbligh2bb6dfd2008-01-10 16:38:30 +000017 if not database:
mbligh73f38a32008-02-21 16:21:35 +000018 database = file_database
19 db_prefs.close()
mbligh728ff0a2007-09-27 17:05:12 +000020 except:
mbligh2bb6dfd2008-01-10 16:38:30 +000021 if not host:
22 host = 'localhost'
23 if not database:
24 database = 'tko'
mbligh728ff0a2007-09-27 17:05:12 +000025
26 try:
mbligha218d112007-10-03 20:15:09 +000027 file = os.path.join(path, '.priv_login')
28 login = open(file, 'r')
mbligh73f38a32008-02-21 16:21:35 +000029 file_user = login.readline().rstrip()
30 file_password = login.readline().rstrip()
mbligh2bb6dfd2008-01-10 16:38:30 +000031 if not user:
mbligh73f38a32008-02-21 16:21:35 +000032 user = file_user
mbligh2bb6dfd2008-01-10 16:38:30 +000033 if not password:
mbligh73f38a32008-02-21 16:21:35 +000034 password = file_password
35 login.close()
mbligh95fca572007-09-27 17:11:00 +000036 except:
37 try:
mbligha218d112007-10-03 20:15:09 +000038 file = os.path.join(path, '.unpriv_login')
mbligh432bad42007-10-09 19:56:07 +000039 login = open(file, 'r')
mbligh73f38a32008-02-21 16:21:35 +000040 file_user = login.readline().rstrip()
41 file_password = login.readline().rstrip()
mbligh2bb6dfd2008-01-10 16:38:30 +000042 if not user:
mbligh73f38a32008-02-21 16:21:35 +000043 user = file_user
mbligh2bb6dfd2008-01-10 16:38:30 +000044 if not password:
mbligh73f38a32008-02-21 16:21:35 +000045 password = file_password
46 login.close()
mbligh95fca572007-09-27 17:11:00 +000047 except:
mbligh2bb6dfd2008-01-10 16:38:30 +000048 if not user:
49 user = 'nobody'
50 if not password:
51 password = ''
mblighb32cd432007-09-25 18:20:04 +000052
mblighaf25f062007-12-03 17:48:35 +000053 self.con = self.connect(host, database, user, password)
mblighd5c33db2006-10-08 21:34:16 +000054 self.cur = self.con.cursor()
55
mbligh8e1ab172007-09-13 17:29:56 +000056 # if not present, insert statuses
57 self.status_idx = {}
58 self.status_word = {}
mblighc82f2462007-10-02 19:19:17 +000059 status_rows = self.select('status_idx, word', 'status', None)
60 for s in status_rows:
mbligh97894452007-10-05 15:10:33 +000061 self.status_idx[s[1]] = s[0]
mblighc82f2462007-10-02 19:19:17 +000062 self.status_word[s[0]] = s[1]
mbligh048e1c92007-10-07 00:10:33 +000063
mbligh6f075f02008-01-25 16:36:16 +000064 dir = os.path.dirname(__file__)
mbligh048e1c92007-10-07 00:10:33 +000065 machine_map = os.path.join(dir, 'machines')
66 if os.path.exists(machine_map):
67 self.machine_map = machine_map
mblighba9c54c2007-10-26 16:41:26 +000068 else:
69 self.machine_map = None
mbligh048e1c92007-10-07 00:10:33 +000070 self.machine_group = {}
71
mbligh8e1ab172007-09-13 17:29:56 +000072
mbligh8e1ab172007-09-13 17:29:56 +000073 def dprint(self, value):
74 if self.debug:
mbligh83f63a02007-12-12 19:13:04 +000075 sys.stdout.write('SQL: ' + str(value) + '\n')
mbligh8e1ab172007-09-13 17:29:56 +000076
mblighd5c33db2006-10-08 21:34:16 +000077
mbligh432bad42007-10-09 19:56:07 +000078 def commit(self):
79 self.con.commit()
80
81
mblighe12b8612008-02-12 20:58:14 +000082 def get_last_autonumber_value(self):
83 self.cur.execute('SELECT LAST_INSERT_ID()', [])
84 return self.cur.fetchall()[0][0]
85
86
mbligh83f63a02007-12-12 19:13:04 +000087 def select(self, fields, table, where, wherein={}, distinct = False,
88 group_by = None):
mbligh608c3252007-08-31 13:53:00 +000089 """\
mbligh12eebfa2008-01-03 02:01:53 +000090 This selects all the fields requested from a
91 specific table with a particular where clause.
92 The where clause can either be a dictionary of
93 field=value pairs, a string, or a tuple of (string,
94 a list of values). The last option is what you
95 should use when accepting user input as it'll
96 protect you against sql injection attacks (if
97 all user data is placed in the array rather than
98 the raw SQL).
99
100 For example:
101 where = ("a = %s AND b = %s", ['val', 'val'])
102 is better than
103 where = "a = 'val' AND b = 'val'"
mbligh608c3252007-08-31 13:53:00 +0000104 """
mbligh31d29c42007-09-27 00:51:33 +0000105 cmd = ['select']
106 if distinct:
107 cmd.append('distinct')
108 cmd += [fields, 'from', table]
mbligh608c3252007-08-31 13:53:00 +0000109
mbligh31d29c42007-09-27 00:51:33 +0000110 values = []
mbligh414c69e2007-10-05 15:13:06 +0000111 if where and isinstance(where, types.DictionaryType):
mbligh12eebfa2008-01-03 02:01:53 +0000112 # key/value pairs (which should be equal)
mbligh53d14252007-09-12 16:33:14 +0000113 keys = [field + '=%s' for field in where.keys()]
114 values = [where[field] for field in where.keys()]
115
mbligh31d29c42007-09-27 00:51:33 +0000116 cmd.append(' where ' + ' and '.join(keys))
mbligh414c69e2007-10-05 15:13:06 +0000117 elif where and isinstance(where, types.StringTypes):
mbligh12eebfa2008-01-03 02:01:53 +0000118 # the exact string
mbligh414c69e2007-10-05 15:13:06 +0000119 cmd.append(' where ' + where)
mbligh12eebfa2008-01-03 02:01:53 +0000120 elif where and isinstance(where, types.TupleType):
121 # preformatted where clause + values
122 (sql, vals) = where
123 values = vals
124 cmd.append(' where (%s) ' % sql)
mbligh53d14252007-09-12 16:33:14 +0000125
mbligh12eebfa2008-01-03 02:01:53 +0000126 # TODO: this assumes there's a where clause...bad
mbligh85952b42007-12-07 16:28:33 +0000127 if wherein and isinstance(wherein, types.DictionaryType):
128 keys_in = []
129 for field_in in wherein.keys():
130 keys_in += [field_in + ' in (' + ','.join(wherein[field_in])+') ']
131
132 cmd.append(' and '+' and '.join(keys_in))
mbligh83f63a02007-12-12 19:13:04 +0000133 if group_by:
134 cmd.append(' GROUP BY ' + group_by)
135
136 self.dprint('%s %s' % (' '.join(cmd), values))
mbligh31d29c42007-09-27 00:51:33 +0000137 self.cur.execute(' '.join(cmd), values)
mblighd5c33db2006-10-08 21:34:16 +0000138 return self.cur.fetchall()
139
mbligh056d0d32006-10-08 22:31:10 +0000140
mbligh414c69e2007-10-05 15:13:06 +0000141 def select_sql(self, fields, table, sql, values):
142 """\
143 select fields from table "sql"
144 """
145 cmd = 'select %s from %s %s' % (fields, table, sql)
146 self.dprint(cmd)
147 self.cur.execute(cmd, values)
148 return self.cur.fetchall()
149
150
mbligh432bad42007-10-09 19:56:07 +0000151 def insert(self, table, data, commit = None):
mbligh608c3252007-08-31 13:53:00 +0000152 """\
153 'insert into table (keys) values (%s ... %s)', values
154
155 data:
156 dictionary of fields and data
157 """
mbligh432bad42007-10-09 19:56:07 +0000158 if commit == None:
159 commit = self.autocommit
mbligh608c3252007-08-31 13:53:00 +0000160 fields = data.keys()
161 refs = ['%s' for field in fields]
162 values = [data[field] for field in fields]
163 cmd = 'insert into %s (%s) values (%s)' % \
164 (table, ','.join(fields), ','.join(refs))
mbligh53d14252007-09-12 16:33:14 +0000165
mbligh8e1ab172007-09-13 17:29:56 +0000166 self.dprint('%s %s' % (cmd,values))
mbligh608c3252007-08-31 13:53:00 +0000167 self.cur.execute(cmd, values)
mbligh432bad42007-10-09 19:56:07 +0000168 if commit:
169 self.con.commit()
mbligh608c3252007-08-31 13:53:00 +0000170
171
mbligh96b9a5a2007-11-24 19:32:20 +0000172 def delete(self, table, where, commit = None):
173 cmd = ['delete from', table]
174 if commit == None:
175 commit = self.autocommit
176 if where and isinstance(where, types.DictionaryType):
177 keys = [field + '=%s' for field in where.keys()]
178 values = [where[field] for field in where.keys()]
179 cmd += ['where', ' and '.join(keys)]
180 self.dprint('%s %s' % (' '.join(cmd),values))
181 self.cur.execute(' '.join(cmd), values)
182 if commit:
183 self.con.commit()
184
185
mbligh432bad42007-10-09 19:56:07 +0000186 def update(self, table, data, where, commit = None):
mbligh414c69e2007-10-05 15:13:06 +0000187 """\
188 'update table set data values (%s ... %s) where ...'
189
190 data:
191 dictionary of fields and data
192 """
mbligh432bad42007-10-09 19:56:07 +0000193 if commit == None:
194 commit = self.autocommit
mbligh414c69e2007-10-05 15:13:06 +0000195 cmd = 'update %s ' % table
196 fields = data.keys()
197 data_refs = [field + '=%s' for field in fields]
198 data_values = [data[field] for field in fields]
199 cmd += ' set ' + ' and '.join(data_refs)
200
201 where_keys = [field + '=%s' for field in where.keys()]
202 where_values = [where[field] for field in where.keys()]
203 cmd += ' where ' + ' and '.join(where_keys)
204
205 print '%s %s' % (cmd, data_values + where_values)
206 self.cur.execute(cmd, data_values + where_values)
mbligh432bad42007-10-09 19:56:07 +0000207 if commit:
208 self.con.commit()
mbligh414c69e2007-10-05 15:13:06 +0000209
210
mbligh96b9a5a2007-11-24 19:32:20 +0000211 def delete_job(self, tag, commit = None):
212 job_idx = self.find_job(tag)
213 for test_idx in self.find_tests(job_idx):
214 where = {'test_idx' : test_idx}
215 self.delete('iteration_result', where)
216 self.delete('test_attributes', where)
217 where = {'job_idx' : job_idx}
218 self.delete('tests', where)
219 self.delete('jobs', where)
220
221
mbligh432bad42007-10-09 19:56:07 +0000222 def insert_job(self, tag, job, commit = None):
mbligh2aaeb672007-10-01 14:54:18 +0000223 job.machine_idx = self.lookup_machine(job.machine)
224 if not job.machine_idx:
mbligh7a41a862007-11-30 17:44:24 +0000225 job.machine_idx = self.insert_machine(job,
mbligh432bad42007-10-09 19:56:07 +0000226 commit=commit)
mblighb10a60f2007-10-17 00:03:32 +0000227 self.insert('jobs', {'tag':tag,
228 'label': job.label,
mbligh05067a32007-12-03 17:48:04 +0000229 'username': job.user,
mbligh26b992b2008-02-19 15:46:21 +0000230 'machine_idx': job.machine_idx,
231 'queued_time': job.queued_time,
232 'started_time': job.started_time,
233 'finished_time': job.finished_time},
mblighb10a60f2007-10-17 00:03:32 +0000234 commit=commit)
mblighe12b8612008-02-12 20:58:14 +0000235 job.index = self.get_last_autonumber_value()
mbligh608c3252007-08-31 13:53:00 +0000236 for test in job.tests:
mbligh432bad42007-10-09 19:56:07 +0000237 self.insert_test(job, test, commit=commit)
mbligh608c3252007-08-31 13:53:00 +0000238
mbligh96b9a5a2007-11-24 19:32:20 +0000239
mbligh432bad42007-10-09 19:56:07 +0000240 def insert_test(self, job, test, commit = None):
241 kver = self.insert_kernel(test.kernel, commit=commit)
mbligh608c3252007-08-31 13:53:00 +0000242 data = {'job_idx':job.index, 'test':test.testname,
mbligh2bd48872007-09-20 18:32:25 +0000243 'subdir':test.subdir, 'kernel_idx':kver,
mbligh8e1ab172007-09-13 17:29:56 +0000244 'status':self.status_idx[test.status],
mblighc2514542008-02-19 15:54:26 +0000245 'reason':test.reason, 'machine_idx':job.machine_idx,
246 'finished_time':test.finished_time}
mbligh432bad42007-10-09 19:56:07 +0000247 self.insert('tests', data, commit=commit)
mblighe12b8612008-02-12 20:58:14 +0000248 test_idx = self.get_last_autonumber_value()
mbligh2bd48872007-09-20 18:32:25 +0000249 data = { 'test_idx':test_idx }
250
251 for i in test.iterations:
252 data['iteration'] = i.index
253 for key in i.keyval:
254 data['attribute'] = key
255 data['value'] = i.keyval[key]
mbligh432bad42007-10-09 19:56:07 +0000256 self.insert('iteration_result',
257 data,
258 commit=commit)
mbligh994a23d2007-10-25 15:28:58 +0000259 data = {'test_idx':test_idx, 'attribute':'version', 'value':test.version}
260 self.insert('test_attributes', data, commit=commit)
mblighe9cf9d42007-08-31 08:56:00 +0000261
262
mbligh048e1c92007-10-07 00:10:33 +0000263 def read_machine_map(self):
264 self.machine_group = {}
265 for line in open(self.machine_map, 'r').readlines():
266 (machine, group) = line.split()
267 self.machine_group[machine] = group
268
269
mbligh7a41a862007-11-30 17:44:24 +0000270 def insert_machine(self, job, group = None, commit = None):
271 hostname = job.machine
mbligh048e1c92007-10-07 00:10:33 +0000272 if self.machine_map and not self.machine_group:
273 self.read_machine_map()
274
275 if not group:
276 group = self.machine_group.get(hostname, hostname)
mbligh7a41a862007-11-30 17:44:24 +0000277 if group == hostname and job.machine_owner:
278 group = job.machine_owner + '/' + hostname
279
mbligh432bad42007-10-09 19:56:07 +0000280 self.insert('machines',
281 { 'hostname' : hostname ,
mbligh7a41a862007-11-30 17:44:24 +0000282 'machine_group' : group ,
283 'owner' : job.machine_owner },
mbligh432bad42007-10-09 19:56:07 +0000284 commit=commit)
mblighe12b8612008-02-12 20:58:14 +0000285 return self.get_last_autonumber_value()
mbligh2aaeb672007-10-01 14:54:18 +0000286
287
288 def lookup_machine(self, hostname):
289 where = { 'hostname' : hostname }
290 rows = self.select('machine_idx', 'machines', where)
291 if rows:
292 return rows[0][0]
293 else:
294 return None
295
296
mbligh9bb92fe2007-09-12 15:54:23 +0000297 def lookup_kernel(self, kernel):
298 rows = self.select('kernel_idx', 'kernels',
mbligh048e1c92007-10-07 00:10:33 +0000299 {'kernel_hash':kernel.kernel_hash})
mbligh237bed32007-09-05 13:05:57 +0000300 if rows:
301 return rows[0][0]
302 else:
303 return None
mblighe9cf9d42007-08-31 08:56:00 +0000304
305
mbligh432bad42007-10-09 19:56:07 +0000306 def insert_kernel(self, kernel, commit = None):
mbligh9bb92fe2007-09-12 15:54:23 +0000307 kver = self.lookup_kernel(kernel)
mbligh237bed32007-09-05 13:05:57 +0000308 if kver:
309 return kver
apw7a7316b2008-02-21 17:42:05 +0000310
311 # If this kernel has any significant patches, append their hash
312 # as diferentiator.
313 printable = kernel.base
314 patch_count = 0
315 for patch in kernel.patches:
316 match = re.match(r'.*(-mm[0-9]+|-git[0-9]+)\.(bz2|gz)$',
317 patch.reference)
318 if not match:
319 patch_count += 1
320
mbligh432bad42007-10-09 19:56:07 +0000321 self.insert('kernels',
322 {'base':kernel.base,
323 'kernel_hash':kernel.kernel_hash,
apw7a7316b2008-02-21 17:42:05 +0000324 'printable':printable},
mbligh432bad42007-10-09 19:56:07 +0000325 commit=commit)
mblighe12b8612008-02-12 20:58:14 +0000326 kver = self.get_last_autonumber_value()
apw7a7316b2008-02-21 17:42:05 +0000327
328 if patch_count > 0:
329 printable += ' p%d' % (kver)
330 self.update('kernels',
331 {'printable':printable},
332 {'kernel_idx':kver})
333
mbligh237bed32007-09-05 13:05:57 +0000334 for patch in kernel.patches:
mbligh432bad42007-10-09 19:56:07 +0000335 self.insert_patch(kver, patch, commit=commit)
mbligh237bed32007-09-05 13:05:57 +0000336 return kver
337
338
mbligh432bad42007-10-09 19:56:07 +0000339 def insert_patch(self, kver, patch, commit = None):
mbligh237bed32007-09-05 13:05:57 +0000340 print patch.reference
341 name = os.path.basename(patch.reference)[:80]
mbligh432bad42007-10-09 19:56:07 +0000342 self.insert('patches',
343 {'kernel_idx': kver,
344 'name':name,
345 'url':patch.reference,
346 'hash':patch.hash},
347 commit=commit)
mbligh056d0d32006-10-08 22:31:10 +0000348
mbligh048e1c92007-10-07 00:10:33 +0000349
mbligh2bd48872007-09-20 18:32:25 +0000350 def find_test(self, job_idx, subdir):
351 where = { 'job_idx':job_idx , 'subdir':subdir }
352 rows = self.select('test_idx', 'tests', where)
353 if rows:
354 return rows[0][0]
355 else:
356 return None
357
mbligh056d0d32006-10-08 22:31:10 +0000358
mbligh96b9a5a2007-11-24 19:32:20 +0000359 def find_tests(self, job_idx):
360 where = { 'job_idx':job_idx }
361 rows = self.select('test_idx', 'tests', where)
362 if rows:
363 return [row[0] for row in rows]
364 else:
mbligh2e57e7b2007-11-29 16:10:50 +0000365 return []
mbligh96b9a5a2007-11-24 19:32:20 +0000366
367
mbligh056d0d32006-10-08 22:31:10 +0000368 def find_job(self, tag):
mbligh608c3252007-08-31 13:53:00 +0000369 rows = self.select('job_idx', 'jobs', {'tag': tag})
370 if rows:
371 return rows[0][0]
372 else:
373 return None
mblighaf25f062007-12-03 17:48:35 +0000374
375
376# Use a class method as a class factory, generating a relevant database object.
377def db(*args, **dargs):
mbligh6f075f02008-01-25 16:36:16 +0000378 path = os.path.dirname(__file__)
mbligha044e562007-12-07 16:26:13 +0000379 db_type = None
mblighaf25f062007-12-03 17:48:35 +0000380 try:
mbligha044e562007-12-07 16:26:13 +0000381 db_file = os.path.join(path, '.database')
382 db_prefs = open(db_file, 'r')
mblighaf25f062007-12-03 17:48:35 +0000383 host = db_prefs.readline().rstrip()
384 database = db_prefs.readline().rstrip()
mbligha044e562007-12-07 16:26:13 +0000385 db_type = db_prefs.readline().rstrip()
386 except:
387 pass
mblighaf25f062007-12-03 17:48:35 +0000388
mbligha044e562007-12-07 16:26:13 +0000389 if not db_type:
390 db_type = 'mysql'
391
392 db_type = 'db_' + db_type
393 exec 'import %s; db = %s.%s(*args, **dargs)' % (db_type, db_type, db_type)
mblighaf25f062007-12-03 17:48:35 +0000394
395 return db