blob: 9886d5bda22e278721451e0fdea5a4a23c91fc1f [file] [log] [blame]
mbligh65acae52008-04-24 20:21:55 +00001import re, os, sys, types, time, random
Jakob Jueliche2bf3962014-10-02 11:33:17 -07002from django.conf import settings
mbligh96cf0512008-04-17 15:25:38 +00003
4import common
5from autotest_lib.client.common_lib import global_config
jamesrena12b8a02010-06-16 23:28:23 +00006from autotest_lib.tko import utils
mbligh96cf0512008-04-17 15:25:38 +00007
mblighed4d6dd2008-02-27 16:49:43 +00008
mblighaea09602008-04-16 22:59:37 +00009class MySQLTooManyRows(Exception):
jadmanski0afbb632008-06-06 21:10:57 +000010 pass
mblighaea09602008-04-16 22:59:37 +000011
mblighd5c33db2006-10-08 21:34:16 +000012
mbligh7636b3a2008-06-11 15:44:01 +000013class db_sql(object):
jadmanski0afbb632008-06-06 21:10:57 +000014 def __init__(self, debug=False, autocommit=True, host=None,
15 database=None, user=None, password=None):
16 self.debug = debug
17 self.autocommit = autocommit
18 self._load_config(host, database, user, password)
mbligh96cf0512008-04-17 15:25:38 +000019
jadmanski0afbb632008-06-06 21:10:57 +000020 self.con = None
21 self._init_db()
mblighd5c33db2006-10-08 21:34:16 +000022
jadmanski0afbb632008-06-06 21:10:57 +000023 # if not present, insert statuses
24 self.status_idx = {}
25 self.status_word = {}
showardeab66ce2009-12-23 00:03:56 +000026 status_rows = self.select('status_idx, word', 'tko_status', None)
jadmanski0afbb632008-06-06 21:10:57 +000027 for s in status_rows:
28 self.status_idx[s[1]] = s[0]
29 self.status_word[s[0]] = s[1]
mbligh048e1c92007-10-07 00:10:33 +000030
jadmanski0afbb632008-06-06 21:10:57 +000031 machine_map = os.path.join(os.path.dirname(__file__),
32 'machines')
33 if os.path.exists(machine_map):
34 self.machine_map = machine_map
35 else:
36 self.machine_map = None
37 self.machine_group = {}
mbligh048e1c92007-10-07 00:10:33 +000038
mbligh8e1ab172007-09-13 17:29:56 +000039
jadmanski0afbb632008-06-06 21:10:57 +000040 def _load_config(self, host, database, user, password):
Jakob Jueliche2bf3962014-10-02 11:33:17 -070041 """Loads configuration settings required to connect to the database.
42
43 This will try to connect to use the settings prefixed with global_db_.
44 If they do not exist, they un-prefixed settings will be used.
45
46 If parameters are supplied, these will be taken instead of the values
47 in global_config.
48
49 @param host: If set, this host will be used, if not, the host will be
50 retrieved from global_config.
51 @param database: If set, this database will be used, if not, the
52 database will be retrieved from global_config.
53 @param user: If set, this user will be used, if not, the
54 user will be retrieved from global_config.
55 @param password: If set, this password will be used, if not, the
56 password will be retrieved from global_config.
57 """
58 DATABASE_SETTINGS = settings.DATABASES['global']
mbligh65acae52008-04-24 20:21:55 +000059
jadmanski0afbb632008-06-06 21:10:57 +000060 # grab the host, database
61 if host:
62 self.host = host
63 else:
Jakob Jueliche2bf3962014-10-02 11:33:17 -070064 self.host = DATABASE_SETTINGS['HOST']
jadmanski0afbb632008-06-06 21:10:57 +000065 if database:
66 self.database = database
67 else:
Jakob Jueliche2bf3962014-10-02 11:33:17 -070068 self.database = DATABASE_SETTINGS['NAME']
mbligh65acae52008-04-24 20:21:55 +000069
jadmanski0afbb632008-06-06 21:10:57 +000070 # grab the user and password
71 if user:
72 self.user = user
73 else:
Jakob Jueliche2bf3962014-10-02 11:33:17 -070074 self.user = DATABASE_SETTINGS['USER']
mblighdc2c9bb2008-12-22 14:47:35 +000075 if password is not None:
jadmanski0afbb632008-06-06 21:10:57 +000076 self.password = password
77 else:
Jakob Jueliche2bf3962014-10-02 11:33:17 -070078 self.password = DATABASE_SETTINGS['PASSWORD']
mbligh65acae52008-04-24 20:21:55 +000079
Jakob Jueliche2bf3962014-10-02 11:33:17 -070080 # Using fallback to non-global in order to work without configuration
81 # overhead on non-shard instances.
82 get_value = global_config.global_config.get_config_value_with_fallback
Jakob Juelich87c15512014-10-07 18:11:28 -070083
84 # grab the timeout configuration
85 self.query_timeout = get_value(
86 "AUTOTEST_WEB", "global_db_query_timeout", "query_timeout",
87 type=int, default=3600)
Jakob Juelich475b82b2014-09-30 11:17:07 -070088 self.min_delay = get_value("AUTOTEST_WEB", "global_db_min_retry_delay",
Jakob Jueliche2bf3962014-10-02 11:33:17 -070089 "min_retry_delay", type=int, default=20)
Jakob Juelich475b82b2014-09-30 11:17:07 -070090 self.max_delay = get_value("AUTOTEST_WEB", "global_db_max_retry_delay",
Jakob Jueliche2bf3962014-10-02 11:33:17 -070091 "max_retry_delay", type=int, default=60)
mbligh65acae52008-04-24 20:21:55 +000092
93
jadmanski0afbb632008-06-06 21:10:57 +000094 def _init_db(self):
95 # make sure we clean up any existing connection
96 if self.con:
97 self.con.close()
98 self.con = None
mbligh65acae52008-04-24 20:21:55 +000099
jadmanski0afbb632008-06-06 21:10:57 +0000100 # create the db connection and cursor
101 self.con = self.connect(self.host, self.database,
102 self.user, self.password)
103 self.cur = self.con.cursor()
mbligh96cf0512008-04-17 15:25:38 +0000104
105
jadmanski0afbb632008-06-06 21:10:57 +0000106 def _random_delay(self):
107 delay = random.randint(self.min_delay, self.max_delay)
108 time.sleep(delay)
mbligh65acae52008-04-24 20:21:55 +0000109
110
jadmanski0afbb632008-06-06 21:10:57 +0000111 def run_with_retry(self, function, *args, **dargs):
112 """Call function(*args, **dargs) until either it passes
113 without an operational error, or a timeout is reached.
114 This will re-connect to the database, so it is NOT safe
115 to use this inside of a database transaction.
jadmanskie7a69092008-05-29 21:03:13 +0000116
jadmanski0afbb632008-06-06 21:10:57 +0000117 It can be safely used with transactions, but the
118 transaction start & end must be completely contained
119 within the call to 'function'."""
120 OperationalError = _get_error_class("OperationalError")
mbligh65acae52008-04-24 20:21:55 +0000121
jadmanski0afbb632008-06-06 21:10:57 +0000122 success = False
123 start_time = time.time()
124 while not success:
125 try:
126 result = function(*args, **dargs)
127 except OperationalError, e:
128 self._log_operational_error(e)
129 stop_time = time.time()
130 elapsed_time = stop_time - start_time
131 if elapsed_time > self.query_timeout:
132 raise
133 else:
134 try:
135 self._random_delay()
136 self._init_db()
137 except OperationalError, e:
138 self._log_operational_error(e)
139 else:
140 success = True
141 return result
mbligh96cf0512008-04-17 15:25:38 +0000142
143
jadmanski0afbb632008-06-06 21:10:57 +0000144 def _log_operational_error(self, e):
mbligh097407d2009-02-17 15:49:37 +0000145 msg = ("%s: An operational error occured during a database "
jadmanski5d4c27e2009-03-02 16:45:42 +0000146 "operation: %s" % (time.strftime("%X %x"), str(e)))
jadmanski0afbb632008-06-06 21:10:57 +0000147 print >> sys.stderr, msg
148 sys.stderr.flush() # we want these msgs to show up immediately
jadmanski60d4fa62008-05-06 22:49:41 +0000149
150
jadmanski0afbb632008-06-06 21:10:57 +0000151 def dprint(self, value):
152 if self.debug:
153 sys.stdout.write('SQL: ' + str(value) + '\n')
mbligh8e1ab172007-09-13 17:29:56 +0000154
mblighd5c33db2006-10-08 21:34:16 +0000155
jadmanski0afbb632008-06-06 21:10:57 +0000156 def commit(self):
157 self.con.commit()
mbligh432bad42007-10-09 19:56:07 +0000158
159
Simran Basie129a962012-08-31 13:03:53 -0700160 def rollback(self):
161 self.con.rollback()
162
163
jadmanski0afbb632008-06-06 21:10:57 +0000164 def get_last_autonumber_value(self):
165 self.cur.execute('SELECT LAST_INSERT_ID()', [])
166 return self.cur.fetchall()[0][0]
mblighe12b8612008-02-12 20:58:14 +0000167
168
showardc1a98d12010-01-15 00:22:22 +0000169 def _quote(self, field):
170 return '`%s`' % field
171
172
173 def _where_clause(self, where):
174 if not where:
175 return '', []
176
177 if isinstance(where, dict):
178 # key/value pairs (which should be equal, or None for null)
179 keys, values = [], []
180 for field, value in where.iteritems():
181 quoted_field = self._quote(field)
182 if value is None:
183 keys.append(quoted_field + ' is null')
184 else:
185 keys.append(quoted_field + '=%s')
186 values.append(value)
187 where_clause = ' and '.join(keys)
188 elif isinstance(where, basestring):
189 # the exact string
190 where_clause = where
191 values = []
192 elif isinstance(where, tuple):
193 # preformatted where clause + values
194 where_clause, values = where
195 assert where_clause
196 else:
197 raise ValueError('Invalid "where" value: %r' % where)
198
199 return ' WHERE ' + where_clause, values
200
201
202
203 def select(self, fields, table, where, distinct=False, group_by=None,
204 max_rows=None):
jadmanski0afbb632008-06-06 21:10:57 +0000205 """\
206 This selects all the fields requested from a
207 specific table with a particular where clause.
208 The where clause can either be a dictionary of
209 field=value pairs, a string, or a tuple of (string,
210 a list of values). The last option is what you
211 should use when accepting user input as it'll
212 protect you against sql injection attacks (if
213 all user data is placed in the array rather than
214 the raw SQL).
mbligh12eebfa2008-01-03 02:01:53 +0000215
jadmanski0afbb632008-06-06 21:10:57 +0000216 For example:
217 where = ("a = %s AND b = %s", ['val', 'val'])
218 is better than
219 where = "a = 'val' AND b = 'val'"
220 """
221 cmd = ['select']
222 if distinct:
223 cmd.append('distinct')
224 cmd += [fields, 'from', table]
mbligh608c3252007-08-31 13:53:00 +0000225
showardc1a98d12010-01-15 00:22:22 +0000226 where_clause, values = self._where_clause(where)
227 cmd.append(where_clause)
mbligh96cf0512008-04-17 15:25:38 +0000228
jadmanski0afbb632008-06-06 21:10:57 +0000229 if group_by:
230 cmd.append(' GROUP BY ' + group_by)
mbligh83f63a02007-12-12 19:13:04 +0000231
jadmanski0afbb632008-06-06 21:10:57 +0000232 self.dprint('%s %s' % (' '.join(cmd), values))
mbligh96cf0512008-04-17 15:25:38 +0000233
jadmanski0afbb632008-06-06 21:10:57 +0000234 # create a re-runable function for executing the query
235 def exec_sql():
236 sql = ' '.join(cmd)
237 numRec = self.cur.execute(sql, values)
mblighd876f452008-12-03 15:09:17 +0000238 if max_rows is not None and numRec > max_rows:
jadmanski0afbb632008-06-06 21:10:57 +0000239 msg = 'Exceeded allowed number of records'
240 raise MySQLTooManyRows(msg)
241 return self.cur.fetchall()
mbligh96cf0512008-04-17 15:25:38 +0000242
jadmanski0afbb632008-06-06 21:10:57 +0000243 # run the query, re-trying after operational errors
244 if self.autocommit:
245 return self.run_with_retry(exec_sql)
246 else:
247 return exec_sql()
mblighd5c33db2006-10-08 21:34:16 +0000248
mbligh056d0d32006-10-08 22:31:10 +0000249
jadmanski0afbb632008-06-06 21:10:57 +0000250 def select_sql(self, fields, table, sql, values):
251 """\
252 select fields from table "sql"
253 """
254 cmd = 'select %s from %s %s' % (fields, table, sql)
255 self.dprint(cmd)
mbligh414c69e2007-10-05 15:13:06 +0000256
jadmanski0afbb632008-06-06 21:10:57 +0000257 # create a -re-runable function for executing the query
258 def exec_sql():
259 self.cur.execute(cmd, values)
260 return self.cur.fetchall()
mbligh96b9a5a2007-11-24 19:32:20 +0000261
jadmanski0afbb632008-06-06 21:10:57 +0000262 # run the query, re-trying after operational errors
263 if self.autocommit:
264 return self.run_with_retry(exec_sql)
265 else:
266 return exec_sql()
mbligh96b9a5a2007-11-24 19:32:20 +0000267
mbligh608c3252007-08-31 13:53:00 +0000268
jadmanski0afbb632008-06-06 21:10:57 +0000269 def _exec_sql_with_commit(self, sql, values, commit):
270 if self.autocommit:
271 # re-run the query until it succeeds
272 def exec_sql():
273 self.cur.execute(sql, values)
274 self.con.commit()
275 self.run_with_retry(exec_sql)
276 else:
277 # take one shot at running the query
278 self.cur.execute(sql, values)
279 if commit:
280 self.con.commit()
mbligh96b9a5a2007-11-24 19:32:20 +0000281
mbligh2bd48872007-09-20 18:32:25 +0000282
jadmanskib591fba2008-09-10 16:19:22 +0000283 def insert(self, table, data, commit=None):
jadmanski0afbb632008-06-06 21:10:57 +0000284 """\
285 'insert into table (keys) values (%s ... %s)', values
mbligh96cf0512008-04-17 15:25:38 +0000286
jadmanski0afbb632008-06-06 21:10:57 +0000287 data:
288 dictionary of fields and data
289 """
290 fields = data.keys()
291 refs = ['%s' for field in fields]
292 values = [data[field] for field in fields]
showardc1a98d12010-01-15 00:22:22 +0000293 cmd = ('insert into %s (%s) values (%s)' %
294 (table, ','.join(self._quote(field) for field in fields),
295 ','.join(refs)))
jadmanski0afbb632008-06-06 21:10:57 +0000296 self.dprint('%s %s' % (cmd, values))
mblighe9cf9d42007-08-31 08:56:00 +0000297
jadmanski0afbb632008-06-06 21:10:57 +0000298 self._exec_sql_with_commit(cmd, values, commit)
mblighe9cf9d42007-08-31 08:56:00 +0000299
mbligh048e1c92007-10-07 00:10:33 +0000300
jadmanski0afbb632008-06-06 21:10:57 +0000301 def delete(self, table, where, commit = None):
302 cmd = ['delete from', table]
mblighd876f452008-12-03 15:09:17 +0000303 if commit is None:
jadmanski0afbb632008-06-06 21:10:57 +0000304 commit = self.autocommit
showardc1a98d12010-01-15 00:22:22 +0000305 where_clause, values = self._where_clause(where)
306 cmd.append(where_clause)
jadmanski0afbb632008-06-06 21:10:57 +0000307 sql = ' '.join(cmd)
308 self.dprint('%s %s' % (sql, values))
mbligh048e1c92007-10-07 00:10:33 +0000309
jadmanski0afbb632008-06-06 21:10:57 +0000310 self._exec_sql_with_commit(sql, values, commit)
mbligh048e1c92007-10-07 00:10:33 +0000311
mbligh7a41a862007-11-30 17:44:24 +0000312
jadmanski0afbb632008-06-06 21:10:57 +0000313 def update(self, table, data, where, commit = None):
314 """\
315 'update table set data values (%s ... %s) where ...'
mbligh2aaeb672007-10-01 14:54:18 +0000316
jadmanski0afbb632008-06-06 21:10:57 +0000317 data:
318 dictionary of fields and data
319 """
mblighd876f452008-12-03 15:09:17 +0000320 if commit is None:
jadmanski0afbb632008-06-06 21:10:57 +0000321 commit = self.autocommit
322 cmd = 'update %s ' % table
323 fields = data.keys()
showardc1a98d12010-01-15 00:22:22 +0000324 data_refs = [self._quote(field) + '=%s' for field in fields]
jadmanski0afbb632008-06-06 21:10:57 +0000325 data_values = [data[field] for field in fields]
jadmanski74eebf32008-07-15 20:04:42 +0000326 cmd += ' set ' + ', '.join(data_refs)
mbligh2aaeb672007-10-01 14:54:18 +0000327
showardc1a98d12010-01-15 00:22:22 +0000328 where_clause, where_values = self._where_clause(where)
329 cmd += where_clause
mbligh2aaeb672007-10-01 14:54:18 +0000330
jadmanski0afbb632008-06-06 21:10:57 +0000331 values = data_values + where_values
jadmanski74eebf32008-07-15 20:04:42 +0000332 self.dprint('%s %s' % (cmd, values))
mbligh2aaeb672007-10-01 14:54:18 +0000333
jadmanski0afbb632008-06-06 21:10:57 +0000334 self._exec_sql_with_commit(cmd, values, commit)
mblighe9cf9d42007-08-31 08:56:00 +0000335
336
jadmanski0afbb632008-06-06 21:10:57 +0000337 def delete_job(self, tag, commit = None):
338 job_idx = self.find_job(tag)
339 for test_idx in self.find_tests(job_idx):
340 where = {'test_idx' : test_idx}
showardeab66ce2009-12-23 00:03:56 +0000341 self.delete('tko_iteration_result', where)
Dennis Jeffrey368c54b2013-07-24 11:19:03 -0700342 self.delete('tko_iteration_perf_value', where)
showardeab66ce2009-12-23 00:03:56 +0000343 self.delete('tko_iteration_attributes', where)
344 self.delete('tko_test_attributes', where)
345 self.delete('tko_test_labels_tests', {'test_id': test_idx})
jadmanski0afbb632008-06-06 21:10:57 +0000346 where = {'job_idx' : job_idx}
showardeab66ce2009-12-23 00:03:56 +0000347 self.delete('tko_tests', where)
348 self.delete('tko_jobs', where)
apw7a7316b2008-02-21 17:42:05 +0000349
apw7a7316b2008-02-21 17:42:05 +0000350
jadmanski0afbb632008-06-06 21:10:57 +0000351 def insert_job(self, tag, job, commit = None):
352 job.machine_idx = self.lookup_machine(job.machine)
353 if not job.machine_idx:
showard71b94312009-08-20 23:40:02 +0000354 job.machine_idx = self.insert_machine(job, commit=commit)
355 else:
356 self.update_machine_information(job, commit=commit)
357
jamesrena12b8a02010-06-16 23:28:23 +0000358 afe_job_id = utils.get_afe_job_id(tag)
showardc1c1caf2009-09-08 16:26:50 +0000359
showard0fec8a02009-12-04 01:19:54 +0000360 data = {'tag':tag,
361 'label': job.label,
362 'username': job.user,
363 'machine_idx': job.machine_idx,
364 'queued_time': job.queued_time,
365 'started_time': job.started_time,
366 'finished_time': job.finished_time,
367 'afe_job_id': afe_job_id}
368 is_update = hasattr(job, 'index')
369 if is_update:
showardeab66ce2009-12-23 00:03:56 +0000370 self.update('tko_jobs', data, {'job_idx': job.index}, commit=commit)
showard0fec8a02009-12-04 01:19:54 +0000371 else:
showardeab66ce2009-12-23 00:03:56 +0000372 self.insert('tko_jobs', data, commit=commit)
showard0fec8a02009-12-04 01:19:54 +0000373 job.index = self.get_last_autonumber_value()
showardc1a98d12010-01-15 00:22:22 +0000374 self.update_job_keyvals(job, commit=commit)
jadmanski0afbb632008-06-06 21:10:57 +0000375 for test in job.tests:
376 self.insert_test(job, test, commit=commit)
apw7a7316b2008-02-21 17:42:05 +0000377
mbligh237bed32007-09-05 13:05:57 +0000378
showardc1a98d12010-01-15 00:22:22 +0000379 def update_job_keyvals(self, job, commit=None):
380 for key, value in job.keyval_dict.iteritems():
381 where = {'job_id': job.index, 'key': key}
382 data = dict(where, value=value)
383 exists = self.select('id', 'tko_job_keyvals', where=where)
384
385 if exists:
386 self.update('tko_job_keyvals', data, where=where, commit=commit)
387 else:
388 self.insert('tko_job_keyvals', data, commit=commit)
389
390
jadmanski0afbb632008-06-06 21:10:57 +0000391 def insert_test(self, job, test, commit = None):
392 kver = self.insert_kernel(test.kernel, commit=commit)
393 data = {'job_idx':job.index, 'test':test.testname,
394 'subdir':test.subdir, 'kernel_idx':kver,
395 'status':self.status_idx[test.status],
396 'reason':test.reason, 'machine_idx':job.machine_idx,
397 'started_time': test.started_time,
398 'finished_time':test.finished_time}
jadmanski9b6babf2009-04-21 17:57:40 +0000399 is_update = hasattr(test, "test_idx")
400 if is_update:
jadmanski74eebf32008-07-15 20:04:42 +0000401 test_idx = test.test_idx
showardeab66ce2009-12-23 00:03:56 +0000402 self.update('tko_tests', data,
403 {'test_idx': test_idx}, commit=commit)
jadmanskib591fba2008-09-10 16:19:22 +0000404 where = {'test_idx': test_idx}
showardeab66ce2009-12-23 00:03:56 +0000405 self.delete('tko_iteration_result', where)
Dennis Jeffrey368c54b2013-07-24 11:19:03 -0700406 self.delete('tko_iteration_perf_value', where)
showardeab66ce2009-12-23 00:03:56 +0000407 self.delete('tko_iteration_attributes', where)
showard0fec8a02009-12-04 01:19:54 +0000408 where['user_created'] = 0
showardeab66ce2009-12-23 00:03:56 +0000409 self.delete('tko_test_attributes', where)
jadmanski74eebf32008-07-15 20:04:42 +0000410 else:
showardeab66ce2009-12-23 00:03:56 +0000411 self.insert('tko_tests', data, commit=commit)
jadmanski74eebf32008-07-15 20:04:42 +0000412 test_idx = test.test_idx = self.get_last_autonumber_value()
413 data = {'test_idx': test_idx}
mbligh237bed32007-09-05 13:05:57 +0000414
jadmanski0afbb632008-06-06 21:10:57 +0000415 for i in test.iterations:
416 data['iteration'] = i.index
417 for key, value in i.attr_keyval.iteritems():
418 data['attribute'] = key
419 data['value'] = value
showardeab66ce2009-12-23 00:03:56 +0000420 self.insert('tko_iteration_attributes', data,
jadmanski0afbb632008-06-06 21:10:57 +0000421 commit=commit)
422 for key, value in i.perf_keyval.iteritems():
423 data['attribute'] = key
424 data['value'] = value
showardeab66ce2009-12-23 00:03:56 +0000425 self.insert('tko_iteration_result', data,
mbligh432bad42007-10-09 19:56:07 +0000426 commit=commit)
mbligh056d0d32006-10-08 22:31:10 +0000427
Dennis Jeffrey368c54b2013-07-24 11:19:03 -0700428 data = {'test_idx': test_idx}
429 for i in test.perf_values:
430 data['iteration'] = i.index
431 for perf_dict in i.perf_measurements:
432 data['description'] = perf_dict['description']
433 data['value'] = perf_dict['value']
434 data['stddev'] = perf_dict['stddev']
435 data['units'] = perf_dict['units']
436 data['higher_is_better'] = perf_dict['higher_is_better']
Fang Deng7f24f0b2013-11-12 11:22:16 -0800437 data['graph'] = perf_dict['graph']
Dennis Jeffrey368c54b2013-07-24 11:19:03 -0700438 self.insert('tko_iteration_perf_value', data, commit=commit)
439
jadmanski0afbb632008-06-06 21:10:57 +0000440 for key, value in test.attributes.iteritems():
441 data = {'test_idx': test_idx, 'attribute': key,
442 'value': value}
showardeab66ce2009-12-23 00:03:56 +0000443 self.insert('tko_test_attributes', data, commit=commit)
mbligh2bd48872007-09-20 18:32:25 +0000444
jadmanski9b6babf2009-04-21 17:57:40 +0000445 if not is_update:
446 for label_index in test.labels:
447 data = {'test_id': test_idx, 'testlabel_id': label_index}
showardeab66ce2009-12-23 00:03:56 +0000448 self.insert('tko_test_labels_tests', data, commit=commit)
jadmanski9b6babf2009-04-21 17:57:40 +0000449
mbligh056d0d32006-10-08 22:31:10 +0000450
jadmanski0afbb632008-06-06 21:10:57 +0000451 def read_machine_map(self):
showard71b94312009-08-20 23:40:02 +0000452 if self.machine_group or not self.machine_map:
453 return
jadmanski0afbb632008-06-06 21:10:57 +0000454 for line in open(self.machine_map, 'r').readlines():
455 (machine, group) = line.split()
456 self.machine_group[machine] = group
mbligh96b9a5a2007-11-24 19:32:20 +0000457
458
showard71b94312009-08-20 23:40:02 +0000459 def machine_info_dict(self, job):
jadmanski0afbb632008-06-06 21:10:57 +0000460 hostname = job.machine
showard71b94312009-08-20 23:40:02 +0000461 group = job.machine_group
462 owner = job.machine_owner
jadmanski0afbb632008-06-06 21:10:57 +0000463
464 if not group:
showard71b94312009-08-20 23:40:02 +0000465 self.read_machine_map()
jadmanski0afbb632008-06-06 21:10:57 +0000466 group = self.machine_group.get(hostname, hostname)
showard71b94312009-08-20 23:40:02 +0000467 if group == hostname and owner:
468 group = owner + '/' + hostname
jadmanski0afbb632008-06-06 21:10:57 +0000469
showard71b94312009-08-20 23:40:02 +0000470 return {'hostname': hostname, 'machine_group': group, 'owner': owner}
471
472
473 def insert_machine(self, job, commit = None):
474 machine_info = self.machine_info_dict(job)
showardeab66ce2009-12-23 00:03:56 +0000475 self.insert('tko_machines', machine_info, commit=commit)
jadmanski0afbb632008-06-06 21:10:57 +0000476 return self.get_last_autonumber_value()
477
478
showard71b94312009-08-20 23:40:02 +0000479 def update_machine_information(self, job, commit = None):
480 machine_info = self.machine_info_dict(job)
showardeab66ce2009-12-23 00:03:56 +0000481 self.update('tko_machines', machine_info,
showard71b94312009-08-20 23:40:02 +0000482 where={'hostname': machine_info['hostname']},
483 commit=commit)
484
485
jadmanski0afbb632008-06-06 21:10:57 +0000486 def lookup_machine(self, hostname):
487 where = { 'hostname' : hostname }
showardeab66ce2009-12-23 00:03:56 +0000488 rows = self.select('machine_idx', 'tko_machines', where)
jadmanski0afbb632008-06-06 21:10:57 +0000489 if rows:
490 return rows[0][0]
491 else:
492 return None
493
494
495 def lookup_kernel(self, kernel):
showardeab66ce2009-12-23 00:03:56 +0000496 rows = self.select('kernel_idx', 'tko_kernels',
jadmanski0afbb632008-06-06 21:10:57 +0000497 {'kernel_hash':kernel.kernel_hash})
498 if rows:
499 return rows[0][0]
500 else:
501 return None
502
503
504 def insert_kernel(self, kernel, commit = None):
505 kver = self.lookup_kernel(kernel)
506 if kver:
507 return kver
508
509 # If this kernel has any significant patches, append their hash
510 # as diferentiator.
511 printable = kernel.base
512 patch_count = 0
513 for patch in kernel.patches:
514 match = re.match(r'.*(-mm[0-9]+|-git[0-9]+)\.(bz2|gz)$',
515 patch.reference)
516 if not match:
517 patch_count += 1
518
showardeab66ce2009-12-23 00:03:56 +0000519 self.insert('tko_kernels',
jadmanski0afbb632008-06-06 21:10:57 +0000520 {'base':kernel.base,
521 'kernel_hash':kernel.kernel_hash,
522 'printable':printable},
523 commit=commit)
524 kver = self.get_last_autonumber_value()
525
526 if patch_count > 0:
527 printable += ' p%d' % (kver)
showardeab66ce2009-12-23 00:03:56 +0000528 self.update('tko_kernels',
jadmanski0afbb632008-06-06 21:10:57 +0000529 {'printable':printable},
530 {'kernel_idx':kver})
531
532 for patch in kernel.patches:
533 self.insert_patch(kver, patch, commit=commit)
534 return kver
535
536
537 def insert_patch(self, kver, patch, commit = None):
538 print patch.reference
539 name = os.path.basename(patch.reference)[:80]
showardeab66ce2009-12-23 00:03:56 +0000540 self.insert('tko_patches',
jadmanski0afbb632008-06-06 21:10:57 +0000541 {'kernel_idx': kver,
542 'name':name,
543 'url':patch.reference,
544 'hash':patch.hash},
545 commit=commit)
546
547
jadmanski74eebf32008-07-15 20:04:42 +0000548 def find_test(self, job_idx, testname, subdir):
549 where = {'job_idx': job_idx , 'test': testname, 'subdir': subdir}
showardeab66ce2009-12-23 00:03:56 +0000550 rows = self.select('test_idx', 'tko_tests', where)
jadmanski0afbb632008-06-06 21:10:57 +0000551 if rows:
552 return rows[0][0]
553 else:
554 return None
555
556
557 def find_tests(self, job_idx):
558 where = { 'job_idx':job_idx }
showardeab66ce2009-12-23 00:03:56 +0000559 rows = self.select('test_idx', 'tko_tests', where)
jadmanski0afbb632008-06-06 21:10:57 +0000560 if rows:
561 return [row[0] for row in rows]
562 else:
563 return []
564
565
566 def find_job(self, tag):
showardeab66ce2009-12-23 00:03:56 +0000567 rows = self.select('job_idx', 'tko_jobs', {'tag': tag})
jadmanski0afbb632008-06-06 21:10:57 +0000568 if rows:
569 return rows[0][0]
570 else:
571 return None
mblighaf25f062007-12-03 17:48:35 +0000572
573
mbligh96cf0512008-04-17 15:25:38 +0000574def _get_db_type():
jadmanski0afbb632008-06-06 21:10:57 +0000575 """Get the database type name to use from the global config."""
Jakob Jueliche2bf3962014-10-02 11:33:17 -0700576 get_value = global_config.global_config.get_config_value_with_fallback
577 return "db_" + get_value("AUTOTEST_WEB", "global_db_type", "db_type",
578 default="mysql")
mblighaf25f062007-12-03 17:48:35 +0000579
mbligh96cf0512008-04-17 15:25:38 +0000580
581def _get_error_class(class_name):
jadmanski0afbb632008-06-06 21:10:57 +0000582 """Retrieves the appropriate error class by name from the database
583 module."""
584 db_module = __import__("autotest_lib.tko." + _get_db_type(),
585 globals(), locals(), ["driver"])
586 return getattr(db_module.driver, class_name)
mbligh96cf0512008-04-17 15:25:38 +0000587
588
589def db(*args, **dargs):
jadmanski0afbb632008-06-06 21:10:57 +0000590 """Creates an instance of the database class with the arguments
591 provided in args and dargs, using the database type specified by
592 the global configuration (defaulting to mysql)."""
593 db_type = _get_db_type()
594 db_module = __import__("autotest_lib.tko." + db_type, globals(),
595 locals(), [db_type])
596 db = getattr(db_module, db_type)(*args, **dargs)
597 return db