blob: d81b2375c96996d9e636bc1eb637b0a25d0c4ec2 [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
mbligh432bad42007-10-09 19:56:07 +0000310 self.insert('kernels',
311 {'base':kernel.base,
312 'kernel_hash':kernel.kernel_hash,
313 'printable':kernel.base},
314 commit=commit)
mbligh9bb92fe2007-09-12 15:54:23 +0000315 # WARNING - incorrectly shoving base into printable here.
mblighe12b8612008-02-12 20:58:14 +0000316 kver = self.get_last_autonumber_value()
mbligh237bed32007-09-05 13:05:57 +0000317 for patch in kernel.patches:
mbligh432bad42007-10-09 19:56:07 +0000318 self.insert_patch(kver, patch, commit=commit)
mbligh237bed32007-09-05 13:05:57 +0000319 return kver
320
321
mbligh432bad42007-10-09 19:56:07 +0000322 def insert_patch(self, kver, patch, commit = None):
mbligh237bed32007-09-05 13:05:57 +0000323 print patch.reference
324 name = os.path.basename(patch.reference)[:80]
mbligh432bad42007-10-09 19:56:07 +0000325 self.insert('patches',
326 {'kernel_idx': kver,
327 'name':name,
328 'url':patch.reference,
329 'hash':patch.hash},
330 commit=commit)
mbligh056d0d32006-10-08 22:31:10 +0000331
mbligh048e1c92007-10-07 00:10:33 +0000332
mbligh2bd48872007-09-20 18:32:25 +0000333 def find_test(self, job_idx, subdir):
334 where = { 'job_idx':job_idx , 'subdir':subdir }
335 rows = self.select('test_idx', 'tests', where)
336 if rows:
337 return rows[0][0]
338 else:
339 return None
340
mbligh056d0d32006-10-08 22:31:10 +0000341
mbligh96b9a5a2007-11-24 19:32:20 +0000342 def find_tests(self, job_idx):
343 where = { 'job_idx':job_idx }
344 rows = self.select('test_idx', 'tests', where)
345 if rows:
346 return [row[0] for row in rows]
347 else:
mbligh2e57e7b2007-11-29 16:10:50 +0000348 return []
mbligh96b9a5a2007-11-24 19:32:20 +0000349
350
mbligh056d0d32006-10-08 22:31:10 +0000351 def find_job(self, tag):
mbligh608c3252007-08-31 13:53:00 +0000352 rows = self.select('job_idx', 'jobs', {'tag': tag})
353 if rows:
354 return rows[0][0]
355 else:
356 return None
mblighaf25f062007-12-03 17:48:35 +0000357
358
359# Use a class method as a class factory, generating a relevant database object.
360def db(*args, **dargs):
mbligh6f075f02008-01-25 16:36:16 +0000361 path = os.path.dirname(__file__)
mbligha044e562007-12-07 16:26:13 +0000362 db_type = None
mblighaf25f062007-12-03 17:48:35 +0000363 try:
mbligha044e562007-12-07 16:26:13 +0000364 db_file = os.path.join(path, '.database')
365 db_prefs = open(db_file, 'r')
mblighaf25f062007-12-03 17:48:35 +0000366 host = db_prefs.readline().rstrip()
367 database = db_prefs.readline().rstrip()
mbligha044e562007-12-07 16:26:13 +0000368 db_type = db_prefs.readline().rstrip()
369 except:
370 pass
mblighaf25f062007-12-03 17:48:35 +0000371
mbligha044e562007-12-07 16:26:13 +0000372 if not db_type:
373 db_type = 'mysql'
374
375 db_type = 'db_' + db_type
376 exec 'import %s; db = %s.%s(*args, **dargs)' % (db_type, db_type, db_type)
mblighaf25f062007-12-03 17:48:35 +0000377
378 return db