blob: 2cf13ad1478ddca7086faf588fa7288bb125bad7 [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')
mbligh2bb6dfd2008-01-10 16:38:30 +000013 if not host:
14 host = db_prefs.readline().rstrip()
15 if not database:
16 database = db_prefs.readline().rstrip()
mbligh728ff0a2007-09-27 17:05:12 +000017 except:
mbligh2bb6dfd2008-01-10 16:38:30 +000018 if not host:
19 host = 'localhost'
20 if not database:
21 database = 'tko'
mbligh728ff0a2007-09-27 17:05:12 +000022
23 try:
mbligha218d112007-10-03 20:15:09 +000024 file = os.path.join(path, '.priv_login')
25 login = open(file, 'r')
mbligh2bb6dfd2008-01-10 16:38:30 +000026 if not user:
27 user = login.readline().rstrip()
28 if not password:
29 password = login.readline().rstrip()
mbligh95fca572007-09-27 17:11:00 +000030 except:
31 try:
mbligha218d112007-10-03 20:15:09 +000032 file = os.path.join(path, '.unpriv_login')
mbligh432bad42007-10-09 19:56:07 +000033 login = open(file, 'r')
mbligh2bb6dfd2008-01-10 16:38:30 +000034 if not user:
35 user = login.readline().rstrip()
36 if not password:
37 password = login.readline().rstrip()
mbligh95fca572007-09-27 17:11:00 +000038 except:
mbligh2bb6dfd2008-01-10 16:38:30 +000039 if not user:
40 user = 'nobody'
41 if not password:
42 password = ''
mblighb32cd432007-09-25 18:20:04 +000043
mblighaf25f062007-12-03 17:48:35 +000044 self.con = self.connect(host, database, user, password)
mblighd5c33db2006-10-08 21:34:16 +000045 self.cur = self.con.cursor()
46
mbligh8e1ab172007-09-13 17:29:56 +000047 # if not present, insert statuses
48 self.status_idx = {}
49 self.status_word = {}
mblighc82f2462007-10-02 19:19:17 +000050 status_rows = self.select('status_idx, word', 'status', None)
51 for s in status_rows:
mbligh97894452007-10-05 15:10:33 +000052 self.status_idx[s[1]] = s[0]
mblighc82f2462007-10-02 19:19:17 +000053 self.status_word[s[0]] = s[1]
mbligh048e1c92007-10-07 00:10:33 +000054
mbligh6f075f02008-01-25 16:36:16 +000055 dir = os.path.dirname(__file__)
mbligh048e1c92007-10-07 00:10:33 +000056 machine_map = os.path.join(dir, 'machines')
57 if os.path.exists(machine_map):
58 self.machine_map = machine_map
mblighba9c54c2007-10-26 16:41:26 +000059 else:
60 self.machine_map = None
mbligh048e1c92007-10-07 00:10:33 +000061 self.machine_group = {}
62
mbligh8e1ab172007-09-13 17:29:56 +000063
mbligh8e1ab172007-09-13 17:29:56 +000064 def dprint(self, value):
65 if self.debug:
mbligh83f63a02007-12-12 19:13:04 +000066 sys.stdout.write('SQL: ' + str(value) + '\n')
mbligh8e1ab172007-09-13 17:29:56 +000067
mblighd5c33db2006-10-08 21:34:16 +000068
mbligh432bad42007-10-09 19:56:07 +000069 def commit(self):
70 self.con.commit()
71
72
mbligh83f63a02007-12-12 19:13:04 +000073 def select(self, fields, table, where, wherein={}, distinct = False,
74 group_by = None):
mbligh608c3252007-08-31 13:53:00 +000075 """\
mbligh12eebfa2008-01-03 02:01:53 +000076 This selects all the fields requested from a
77 specific table with a particular where clause.
78 The where clause can either be a dictionary of
79 field=value pairs, a string, or a tuple of (string,
80 a list of values). The last option is what you
81 should use when accepting user input as it'll
82 protect you against sql injection attacks (if
83 all user data is placed in the array rather than
84 the raw SQL).
85
86 For example:
87 where = ("a = %s AND b = %s", ['val', 'val'])
88 is better than
89 where = "a = 'val' AND b = 'val'"
mbligh608c3252007-08-31 13:53:00 +000090 """
mbligh31d29c42007-09-27 00:51:33 +000091 cmd = ['select']
92 if distinct:
93 cmd.append('distinct')
94 cmd += [fields, 'from', table]
mbligh608c3252007-08-31 13:53:00 +000095
mbligh31d29c42007-09-27 00:51:33 +000096 values = []
mbligh414c69e2007-10-05 15:13:06 +000097 if where and isinstance(where, types.DictionaryType):
mbligh12eebfa2008-01-03 02:01:53 +000098 # key/value pairs (which should be equal)
mbligh53d14252007-09-12 16:33:14 +000099 keys = [field + '=%s' for field in where.keys()]
100 values = [where[field] for field in where.keys()]
101
mbligh31d29c42007-09-27 00:51:33 +0000102 cmd.append(' where ' + ' and '.join(keys))
mbligh414c69e2007-10-05 15:13:06 +0000103 elif where and isinstance(where, types.StringTypes):
mbligh12eebfa2008-01-03 02:01:53 +0000104 # the exact string
mbligh414c69e2007-10-05 15:13:06 +0000105 cmd.append(' where ' + where)
mbligh12eebfa2008-01-03 02:01:53 +0000106 elif where and isinstance(where, types.TupleType):
107 # preformatted where clause + values
108 (sql, vals) = where
109 values = vals
110 cmd.append(' where (%s) ' % sql)
mbligh53d14252007-09-12 16:33:14 +0000111
mbligh12eebfa2008-01-03 02:01:53 +0000112 # TODO: this assumes there's a where clause...bad
mbligh85952b42007-12-07 16:28:33 +0000113 if wherein and isinstance(wherein, types.DictionaryType):
114 keys_in = []
115 for field_in in wherein.keys():
116 keys_in += [field_in + ' in (' + ','.join(wherein[field_in])+') ']
117
118 cmd.append(' and '+' and '.join(keys_in))
mbligh83f63a02007-12-12 19:13:04 +0000119 if group_by:
120 cmd.append(' GROUP BY ' + group_by)
121
122 self.dprint('%s %s' % (' '.join(cmd), values))
mbligh31d29c42007-09-27 00:51:33 +0000123 self.cur.execute(' '.join(cmd), values)
mblighd5c33db2006-10-08 21:34:16 +0000124 return self.cur.fetchall()
125
mbligh056d0d32006-10-08 22:31:10 +0000126
mbligh414c69e2007-10-05 15:13:06 +0000127 def select_sql(self, fields, table, sql, values):
128 """\
129 select fields from table "sql"
130 """
131 cmd = 'select %s from %s %s' % (fields, table, sql)
132 self.dprint(cmd)
133 self.cur.execute(cmd, values)
134 return self.cur.fetchall()
135
136
mbligh432bad42007-10-09 19:56:07 +0000137 def insert(self, table, data, commit = None):
mbligh608c3252007-08-31 13:53:00 +0000138 """\
139 'insert into table (keys) values (%s ... %s)', values
140
141 data:
142 dictionary of fields and data
143 """
mbligh432bad42007-10-09 19:56:07 +0000144 if commit == None:
145 commit = self.autocommit
mbligh608c3252007-08-31 13:53:00 +0000146 fields = data.keys()
147 refs = ['%s' for field in fields]
148 values = [data[field] for field in fields]
149 cmd = 'insert into %s (%s) values (%s)' % \
150 (table, ','.join(fields), ','.join(refs))
mbligh53d14252007-09-12 16:33:14 +0000151
mbligh8e1ab172007-09-13 17:29:56 +0000152 self.dprint('%s %s' % (cmd,values))
mbligh608c3252007-08-31 13:53:00 +0000153 self.cur.execute(cmd, values)
mbligh432bad42007-10-09 19:56:07 +0000154 if commit:
155 self.con.commit()
mbligh608c3252007-08-31 13:53:00 +0000156
157
mbligh96b9a5a2007-11-24 19:32:20 +0000158 def delete(self, table, where, commit = None):
159 cmd = ['delete from', table]
160 if commit == None:
161 commit = self.autocommit
162 if where and isinstance(where, types.DictionaryType):
163 keys = [field + '=%s' for field in where.keys()]
164 values = [where[field] for field in where.keys()]
165 cmd += ['where', ' and '.join(keys)]
166 self.dprint('%s %s' % (' '.join(cmd),values))
167 self.cur.execute(' '.join(cmd), values)
168 if commit:
169 self.con.commit()
170
171
mbligh432bad42007-10-09 19:56:07 +0000172 def update(self, table, data, where, commit = None):
mbligh414c69e2007-10-05 15:13:06 +0000173 """\
174 'update table set data values (%s ... %s) where ...'
175
176 data:
177 dictionary of fields and data
178 """
mbligh432bad42007-10-09 19:56:07 +0000179 if commit == None:
180 commit = self.autocommit
mbligh414c69e2007-10-05 15:13:06 +0000181 cmd = 'update %s ' % table
182 fields = data.keys()
183 data_refs = [field + '=%s' for field in fields]
184 data_values = [data[field] for field in fields]
185 cmd += ' set ' + ' and '.join(data_refs)
186
187 where_keys = [field + '=%s' for field in where.keys()]
188 where_values = [where[field] for field in where.keys()]
189 cmd += ' where ' + ' and '.join(where_keys)
190
191 print '%s %s' % (cmd, data_values + where_values)
192 self.cur.execute(cmd, data_values + where_values)
mbligh432bad42007-10-09 19:56:07 +0000193 if commit:
194 self.con.commit()
mbligh414c69e2007-10-05 15:13:06 +0000195
196
mbligh96b9a5a2007-11-24 19:32:20 +0000197 def delete_job(self, tag, commit = None):
198 job_idx = self.find_job(tag)
199 for test_idx in self.find_tests(job_idx):
200 where = {'test_idx' : test_idx}
201 self.delete('iteration_result', where)
202 self.delete('test_attributes', where)
203 where = {'job_idx' : job_idx}
204 self.delete('tests', where)
205 self.delete('jobs', where)
206
207
mbligh432bad42007-10-09 19:56:07 +0000208 def insert_job(self, tag, job, commit = None):
mbligh2aaeb672007-10-01 14:54:18 +0000209 job.machine_idx = self.lookup_machine(job.machine)
210 if not job.machine_idx:
mbligh7a41a862007-11-30 17:44:24 +0000211 job.machine_idx = self.insert_machine(job,
mbligh432bad42007-10-09 19:56:07 +0000212 commit=commit)
mblighb10a60f2007-10-17 00:03:32 +0000213 self.insert('jobs', {'tag':tag,
214 'label': job.label,
mbligh05067a32007-12-03 17:48:04 +0000215 'username': job.user,
mblighb10a60f2007-10-17 00:03:32 +0000216 'machine_idx':job.machine_idx},
217 commit=commit)
mbligh608c3252007-08-31 13:53:00 +0000218 job.index = self.find_job(tag)
219 for test in job.tests:
mbligh432bad42007-10-09 19:56:07 +0000220 self.insert_test(job, test, commit=commit)
mbligh608c3252007-08-31 13:53:00 +0000221
mbligh96b9a5a2007-11-24 19:32:20 +0000222
mbligh432bad42007-10-09 19:56:07 +0000223 def insert_test(self, job, test, commit = None):
224 kver = self.insert_kernel(test.kernel, commit=commit)
mbligh608c3252007-08-31 13:53:00 +0000225 data = {'job_idx':job.index, 'test':test.testname,
mbligh2bd48872007-09-20 18:32:25 +0000226 'subdir':test.subdir, 'kernel_idx':kver,
mbligh8e1ab172007-09-13 17:29:56 +0000227 'status':self.status_idx[test.status],
mbligh2aaeb672007-10-01 14:54:18 +0000228 'reason':test.reason, 'machine_idx':job.machine_idx }
mbligh432bad42007-10-09 19:56:07 +0000229 self.insert('tests', data, commit=commit)
mbligh2bd48872007-09-20 18:32:25 +0000230 test_idx = self.find_test(job.index, test.subdir)
231 data = { 'test_idx':test_idx }
232
233 for i in test.iterations:
234 data['iteration'] = i.index
235 for key in i.keyval:
236 data['attribute'] = key
237 data['value'] = i.keyval[key]
mbligh432bad42007-10-09 19:56:07 +0000238 self.insert('iteration_result',
239 data,
240 commit=commit)
mbligh994a23d2007-10-25 15:28:58 +0000241 data = {'test_idx':test_idx, 'attribute':'version', 'value':test.version}
242 self.insert('test_attributes', data, commit=commit)
mblighe9cf9d42007-08-31 08:56:00 +0000243
244
mbligh048e1c92007-10-07 00:10:33 +0000245 def read_machine_map(self):
246 self.machine_group = {}
247 for line in open(self.machine_map, 'r').readlines():
248 (machine, group) = line.split()
249 self.machine_group[machine] = group
250
251
mbligh7a41a862007-11-30 17:44:24 +0000252 def insert_machine(self, job, group = None, commit = None):
253 hostname = job.machine
mbligh048e1c92007-10-07 00:10:33 +0000254 if self.machine_map and not self.machine_group:
255 self.read_machine_map()
256
257 if not group:
258 group = self.machine_group.get(hostname, hostname)
mbligh7a41a862007-11-30 17:44:24 +0000259 if group == hostname and job.machine_owner:
260 group = job.machine_owner + '/' + hostname
261
mbligh432bad42007-10-09 19:56:07 +0000262 self.insert('machines',
263 { 'hostname' : hostname ,
mbligh7a41a862007-11-30 17:44:24 +0000264 'machine_group' : group ,
265 'owner' : job.machine_owner },
mbligh432bad42007-10-09 19:56:07 +0000266 commit=commit)
mbligh2aaeb672007-10-01 14:54:18 +0000267 return self.lookup_machine(hostname)
268
269
270 def lookup_machine(self, hostname):
271 where = { 'hostname' : hostname }
272 rows = self.select('machine_idx', 'machines', where)
273 if rows:
274 return rows[0][0]
275 else:
276 return None
277
278
mbligh9bb92fe2007-09-12 15:54:23 +0000279 def lookup_kernel(self, kernel):
280 rows = self.select('kernel_idx', 'kernels',
mbligh048e1c92007-10-07 00:10:33 +0000281 {'kernel_hash':kernel.kernel_hash})
mbligh237bed32007-09-05 13:05:57 +0000282 if rows:
283 return rows[0][0]
284 else:
285 return None
mblighe9cf9d42007-08-31 08:56:00 +0000286
287
mbligh432bad42007-10-09 19:56:07 +0000288 def insert_kernel(self, kernel, commit = None):
mbligh9bb92fe2007-09-12 15:54:23 +0000289 kver = self.lookup_kernel(kernel)
mbligh237bed32007-09-05 13:05:57 +0000290 if kver:
291 return kver
mbligh432bad42007-10-09 19:56:07 +0000292 self.insert('kernels',
293 {'base':kernel.base,
294 'kernel_hash':kernel.kernel_hash,
295 'printable':kernel.base},
296 commit=commit)
mbligh9bb92fe2007-09-12 15:54:23 +0000297 # WARNING - incorrectly shoving base into printable here.
298 kver = self.lookup_kernel(kernel)
mbligh237bed32007-09-05 13:05:57 +0000299 for patch in kernel.patches:
mbligh432bad42007-10-09 19:56:07 +0000300 self.insert_patch(kver, patch, commit=commit)
mbligh237bed32007-09-05 13:05:57 +0000301 return kver
302
303
mbligh432bad42007-10-09 19:56:07 +0000304 def insert_patch(self, kver, patch, commit = None):
mbligh237bed32007-09-05 13:05:57 +0000305 print patch.reference
306 name = os.path.basename(patch.reference)[:80]
mbligh432bad42007-10-09 19:56:07 +0000307 self.insert('patches',
308 {'kernel_idx': kver,
309 'name':name,
310 'url':patch.reference,
311 'hash':patch.hash},
312 commit=commit)
mbligh056d0d32006-10-08 22:31:10 +0000313
mbligh048e1c92007-10-07 00:10:33 +0000314
mbligh2bd48872007-09-20 18:32:25 +0000315 def find_test(self, job_idx, subdir):
316 where = { 'job_idx':job_idx , 'subdir':subdir }
317 rows = self.select('test_idx', 'tests', where)
318 if rows:
319 return rows[0][0]
320 else:
321 return None
322
mbligh056d0d32006-10-08 22:31:10 +0000323
mbligh96b9a5a2007-11-24 19:32:20 +0000324 def find_tests(self, job_idx):
325 where = { 'job_idx':job_idx }
326 rows = self.select('test_idx', 'tests', where)
327 if rows:
328 return [row[0] for row in rows]
329 else:
mbligh2e57e7b2007-11-29 16:10:50 +0000330 return []
mbligh96b9a5a2007-11-24 19:32:20 +0000331
332
mbligh056d0d32006-10-08 22:31:10 +0000333 def find_job(self, tag):
mbligh608c3252007-08-31 13:53:00 +0000334 rows = self.select('job_idx', 'jobs', {'tag': tag})
335 if rows:
336 return rows[0][0]
337 else:
338 return None
mblighaf25f062007-12-03 17:48:35 +0000339
340
341# Use a class method as a class factory, generating a relevant database object.
342def db(*args, **dargs):
mbligh6f075f02008-01-25 16:36:16 +0000343 path = os.path.dirname(__file__)
mbligha044e562007-12-07 16:26:13 +0000344 db_type = None
mblighaf25f062007-12-03 17:48:35 +0000345 try:
mbligha044e562007-12-07 16:26:13 +0000346 db_file = os.path.join(path, '.database')
347 db_prefs = open(db_file, 'r')
mblighaf25f062007-12-03 17:48:35 +0000348 host = db_prefs.readline().rstrip()
349 database = db_prefs.readline().rstrip()
mbligha044e562007-12-07 16:26:13 +0000350 db_type = db_prefs.readline().rstrip()
351 except:
352 pass
mblighaf25f062007-12-03 17:48:35 +0000353
mbligha044e562007-12-07 16:26:13 +0000354 if not db_type:
355 db_type = 'mysql'
356
357 db_type = 'db_' + db_type
358 exec 'import %s; db = %s.%s(*args, **dargs)' % (db_type, db_type, db_type)
mblighaf25f062007-12-03 17:48:35 +0000359
360 return db