mbligh | 9bb92fe | 2007-09-12 15:54:23 +0000 | [diff] [blame] | 1 | #!/usr/bin/python |
mbligh | 2aaeb67 | 2007-10-01 14:54:18 +0000 | [diff] [blame] | 2 | import os, re, db, sys |
mbligh | 9bb92fe | 2007-09-12 15:54:23 +0000 | [diff] [blame] | 3 | |
mbligh | 2aaeb67 | 2007-10-01 14:54:18 +0000 | [diff] [blame] | 4 | tko = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0]))) |
| 5 | root_url_file = os.path.join(tko, '.root_url') |
| 6 | if os.path.exists(root_url_file): |
| 7 | html_root = open(root_url_file, 'r').readline().rstrip() |
| 8 | else: |
mbligh | c959f4f | 2007-10-25 14:47:17 +0000 | [diff] [blame] | 9 | html_root = '/results/' |
mbligh | 2aaeb67 | 2007-10-01 14:54:18 +0000 | [diff] [blame] | 10 | |
mbligh | 2e4e5df | 2007-11-05 17:22:46 +0000 | [diff] [blame] | 11 | def select(db, field, value=None, distinct=False): |
| 12 | """ returns the relevant index values where the field value matches the |
| 13 | input value to the function. |
| 14 | If there is no value passed, then it returns the index values and the |
| 15 | field values corresponsing to them. """ |
| 16 | |
| 17 | fields = { 'kernel': ['printable', 'kernel_idx', 'kernel_idx'], |
| 18 | 'machine_group': ['machine_group', 'machine_idx', 'machine_idx'], |
| 19 | 'hostname': ['hostname', 'machine_idx', 'machine_idx'], |
| 20 | 'label': ['label', 'job_idx', 'job_idx'], |
mbligh | e6413db | 2007-12-13 16:07:26 +0000 | [diff] [blame] | 21 | 'tag': ['tag', 'job_idx', 'job_idx'], |
| 22 | 'job': ['job_idx', 'job_idx', 'job_idx'], |
mbligh | 05067a3 | 2007-12-03 17:48:04 +0000 | [diff] [blame] | 23 | 'user': ['username', 'job_idx', 'job_idx'], |
mbligh | 2e4e5df | 2007-11-05 17:22:46 +0000 | [diff] [blame] | 24 | 'test': ['test', 'test', 'test'], |
| 25 | 'status': ['word', 'status_idx', 'status'], |
| 26 | 'reason': ['reason', 'test_idx', 'test_idx'] } |
| 27 | table = { 'kernel': 'kernels', |
| 28 | 'machine_group': 'machines', |
| 29 | 'hostname': 'machines', |
| 30 | 'label': 'jobs', |
mbligh | e6413db | 2007-12-13 16:07:26 +0000 | [diff] [blame] | 31 | 'tag': 'jobs', |
| 32 | 'job': 'jobs', |
mbligh | 2e4e5df | 2007-11-05 17:22:46 +0000 | [diff] [blame] | 33 | 'user': 'jobs', |
| 34 | 'test': 'tests', |
| 35 | 'status': 'status', |
| 36 | 'reason': 'tests' } |
| 37 | |
| 38 | lookup_field, idx_field, field_name_in_main_table = fields[field] |
| 39 | tablename = table[field] |
| 40 | # select all the index values that match the given field name. |
| 41 | sql = "" |
| 42 | if distinct: |
| 43 | sql += " distinct " |
| 44 | if not value: |
| 45 | sql += " %s , %s " % (lookup_field, idx_field) |
| 46 | where = " %s is not null " % lookup_field |
| 47 | else: |
| 48 | sql += "%s " % idx_field |
mbligh | e6413db | 2007-12-13 16:07:26 +0000 | [diff] [blame] | 49 | if field == 'tag': |
| 50 | where = " %s LIKE %s " % (lookup_field, value) |
| 51 | else: |
| 52 | where = " %s = %s " % (lookup_field, value) |
mbligh | 2e4e5df | 2007-11-05 17:22:46 +0000 | [diff] [blame] | 53 | |
| 54 | match = db.select(sql, tablename, where) |
| 55 | # returns the value and its field name |
| 56 | return match, field_name_in_main_table |
| 57 | |
mbligh | 83f63a0 | 2007-12-12 19:13:04 +0000 | [diff] [blame] | 58 | |
| 59 | def get_axis_data(axis): |
| 60 | rows = db.select(axis , 'test_view', distinct = True) |
| 61 | # Need to do a magic sort here if axis == 'kernel_printable' |
| 62 | return sorted([row[0] for row in rows]) |
| 63 | |
| 64 | |
| 65 | def get_matrix_data(db, x_axis, y_axis, where = None): |
| 66 | # Return a 3-d hash of data - [x-value][y-value][status_word] |
| 67 | # Searches on the test_view table - x_axis and y_axis must both be |
| 68 | # column names in that table. |
mbligh | 5dd503b | 2008-01-03 16:35:27 +0000 | [diff] [blame] | 69 | fields = ('%s, %s, status, COUNT(status_word), ' + |
| 70 | 'LEFT(GROUP_CONCAT(job_tag), 100)' # limit what's returned |
| 71 | ) % (x_axis, y_axis) |
mbligh | 83f63a0 | 2007-12-12 19:13:04 +0000 | [diff] [blame] | 72 | group_by = '%s, %s, status' % (x_axis, y_axis) |
| 73 | rows = db.select(fields, 'test_view', where=where, group_by=group_by) |
| 74 | |
| 75 | data = {} |
mbligh | 5dd503b | 2008-01-03 16:35:27 +0000 | [diff] [blame] | 76 | job_tags = {} |
mbligh | 12eebfa | 2008-01-03 02:01:53 +0000 | [diff] [blame] | 77 | x_set = set() |
| 78 | y_set = set() |
| 79 | status_set = set() |
mbligh | 5dd503b | 2008-01-03 16:35:27 +0000 | [diff] [blame] | 80 | for (x, y, status, count, job_tag) in rows: |
mbligh | 83f63a0 | 2007-12-12 19:13:04 +0000 | [diff] [blame] | 81 | if not data.has_key(x): |
| 82 | data[x] = {} |
mbligh | 5dd503b | 2008-01-03 16:35:27 +0000 | [diff] [blame] | 83 | job_tags[x] = {} |
mbligh | 83f63a0 | 2007-12-12 19:13:04 +0000 | [diff] [blame] | 84 | if not data[x].has_key(y): |
| 85 | data[x][y] = {} |
| 86 | data[x][y][status] = count |
mbligh | 5dd503b | 2008-01-03 16:35:27 +0000 | [diff] [blame] | 87 | if job_tags[x].has_key(y) or count != 1: |
| 88 | job_tags[x][y] = None |
| 89 | else: |
| 90 | job_tags[x][y] = job_tag |
mbligh | 12eebfa | 2008-01-03 02:01:53 +0000 | [diff] [blame] | 91 | x_set.add(x) |
| 92 | y_set.add(y) |
| 93 | status_set.add(status) |
mbligh | 5dd503b | 2008-01-03 16:35:27 +0000 | [diff] [blame] | 94 | return (data, list(x_set), list(y_set), list(status_set), job_tags) |
mbligh | 83f63a0 | 2007-12-12 19:13:04 +0000 | [diff] [blame] | 95 | |
| 96 | |
mbligh | 2e4e5df | 2007-11-05 17:22:46 +0000 | [diff] [blame] | 97 | class anygroup: |
| 98 | @classmethod |
| 99 | def selectunique(klass, db, field): |
| 100 | """Return unique values for all possible groups within |
| 101 | the table.""" |
| 102 | rows, field_name_in_main_table = select(db, field, value=None, distinct=True) |
| 103 | groupnames = sorted([row for row in rows]) |
mbligh | 2b67253 | 2007-11-05 19:24:51 +0000 | [diff] [blame] | 104 | |
| 105 | # collapse duplicates where records have the same name but |
| 106 | # multiple index values |
| 107 | headers = {} |
| 108 | for field_name, idx_value in groupnames: |
| 109 | if headers.has_key(field_name): |
| 110 | headers[field_name].append(idx_value) |
| 111 | else: |
| 112 | headers[field_name] = [idx_value] |
| 113 | headers = headers.items() |
| 114 | headers.sort() |
| 115 | return [klass(db, field_name_in_main_table, groupname) for groupname in headers] |
mbligh | 2e4e5df | 2007-11-05 17:22:46 +0000 | [diff] [blame] | 116 | |
| 117 | |
| 118 | def __init__(self, db, idx_name, name): |
| 119 | self.db = db |
| 120 | self.name = name[0] |
| 121 | self.idx_name = idx_name |
| 122 | self.idx_value = name[1] |
| 123 | |
mbligh | 2aaeb67 | 2007-10-01 14:54:18 +0000 | [diff] [blame] | 124 | |
mbligh | cff2d21 | 2007-10-07 00:11:10 +0000 | [diff] [blame] | 125 | class group: |
| 126 | @classmethod |
| 127 | def select(klass, db): |
| 128 | """Return all possible machine groups""" |
| 129 | rows = db.select('distinct machine_group', 'machines', |
| 130 | 'machine_group is not null') |
| 131 | groupnames = sorted([row[0] for row in rows]) |
| 132 | return [klass(db, groupname) for groupname in groupnames] |
mbligh | 83f63a0 | 2007-12-12 19:13:04 +0000 | [diff] [blame] | 133 | |
| 134 | |
mbligh | cff2d21 | 2007-10-07 00:11:10 +0000 | [diff] [blame] | 135 | def __init__(self, db, name): |
| 136 | self.name = name |
| 137 | self.db = db |
| 138 | |
| 139 | |
| 140 | def machines(self): |
| 141 | return machine.select(self.db, { 'machine_group' : self.name }) |
mbligh | 2e4e5df | 2007-11-05 17:22:46 +0000 | [diff] [blame] | 142 | |
mbligh | cff2d21 | 2007-10-07 00:11:10 +0000 | [diff] [blame] | 143 | |
| 144 | def tests(self, where = {}): |
| 145 | values = [self.name] |
| 146 | sql = 't inner join machines m on m.machine_idx=t.machine_idx where m.machine_group=%s' |
| 147 | for key in where.keys(): |
| 148 | sql += ' and %s=%%s' % key |
| 149 | values.append(where[key]) |
| 150 | return test.select_sql(self.db, sql, values) |
| 151 | |
mbligh | 2e4e5df | 2007-11-05 17:22:46 +0000 | [diff] [blame] | 152 | |
mbligh | 2aaeb67 | 2007-10-01 14:54:18 +0000 | [diff] [blame] | 153 | class machine: |
| 154 | @classmethod |
| 155 | def select(klass, db, where = {}): |
| 156 | fields = ['machine_idx', 'hostname', 'machine_group', 'owner'] |
| 157 | machines = [] |
| 158 | for row in db.select(','.join(fields), 'machines', where): |
| 159 | machines.append(klass(db, *row)) |
| 160 | return machines |
| 161 | |
| 162 | |
| 163 | def __init__(self, db, idx, hostname, group, owner): |
| 164 | self.db = db |
| 165 | self.idx = idx |
| 166 | self.hostname = hostname |
| 167 | self.group = group |
mbligh | f736b33 | 2007-12-18 20:56:51 +0000 | [diff] [blame] | 168 | self.owner = owner |
mbligh | 2e4e5df | 2007-11-05 17:22:46 +0000 | [diff] [blame] | 169 | |
mbligh | 250300e | 2007-09-18 00:50:57 +0000 | [diff] [blame] | 170 | |
mbligh | 9bb92fe | 2007-09-12 15:54:23 +0000 | [diff] [blame] | 171 | class kernel: |
mbligh | 8e1ab17 | 2007-09-13 17:29:56 +0000 | [diff] [blame] | 172 | @classmethod |
| 173 | def select(klass, db, where = {}): |
| 174 | fields = ['kernel_idx', 'kernel_hash', 'base', 'printable'] |
mbligh | 83f63a0 | 2007-12-12 19:13:04 +0000 | [diff] [blame] | 175 | rows = db.select(','.join(fields), 'kernels', where) |
| 176 | return [klass(db, *row) for row in rows] |
mbligh | 9bb92fe | 2007-09-12 15:54:23 +0000 | [diff] [blame] | 177 | |
mbligh | 8e1ab17 | 2007-09-13 17:29:56 +0000 | [diff] [blame] | 178 | |
| 179 | def __init__(self, db, idx, hash, base, printable): |
mbligh | 9bb92fe | 2007-09-12 15:54:23 +0000 | [diff] [blame] | 180 | self.db = db |
mbligh | 8e1ab17 | 2007-09-13 17:29:56 +0000 | [diff] [blame] | 181 | self.idx = idx |
mbligh | 9bb92fe | 2007-09-12 15:54:23 +0000 | [diff] [blame] | 182 | self.hash = hash |
mbligh | 8e1ab17 | 2007-09-13 17:29:56 +0000 | [diff] [blame] | 183 | self.base = base |
| 184 | self.printable = printable |
| 185 | self.patches = [] # THIS SHOULD PULL IN PATCHES! |
mbligh | 9bb92fe | 2007-09-12 15:54:23 +0000 | [diff] [blame] | 186 | |
| 187 | |
| 188 | class test: |
mbligh | 8e1ab17 | 2007-09-13 17:29:56 +0000 | [diff] [blame] | 189 | @classmethod |
mbligh | 85952b4 | 2007-12-07 16:28:33 +0000 | [diff] [blame] | 190 | def select(klass, db, where = {}, wherein = {}, distinct = False): |
mbligh | 8e1ab17 | 2007-09-13 17:29:56 +0000 | [diff] [blame] | 191 | fields = ['test_idx', 'job_idx', 'test', 'subdir', |
mbligh | 2aaeb67 | 2007-10-01 14:54:18 +0000 | [diff] [blame] | 192 | 'kernel_idx', 'status', 'reason', 'machine_idx'] |
mbligh | 8e1ab17 | 2007-09-13 17:29:56 +0000 | [diff] [blame] | 193 | tests = [] |
mbligh | 85952b4 | 2007-12-07 16:28:33 +0000 | [diff] [blame] | 194 | for row in db.select(','.join(fields), 'tests', where, wherein,distinct): |
mbligh | 8e1ab17 | 2007-09-13 17:29:56 +0000 | [diff] [blame] | 195 | tests.append(klass(db, *row)) |
| 196 | return tests |
| 197 | |
| 198 | |
mbligh | 414c69e | 2007-10-05 15:13:06 +0000 | [diff] [blame] | 199 | @classmethod |
| 200 | def select_sql(klass, db, sql, values): |
| 201 | fields = ['test_idx', 'job_idx', 'test', 'subdir', |
| 202 | 'kernel_idx', 'status', 'reason', 'machine_idx'] |
| 203 | fields = ['t.'+field for field in fields] |
| 204 | rows = db.select_sql(','.join(fields), 'tests', sql, values) |
| 205 | return [klass(db, *row) for row in rows] |
| 206 | |
| 207 | |
mbligh | 2aaeb67 | 2007-10-01 14:54:18 +0000 | [diff] [blame] | 208 | def __init__(self, db, test_idx, job_idx, testname, subdir, kernel_idx, status_num, reason, machine_idx): |
mbligh | 8e1ab17 | 2007-09-13 17:29:56 +0000 | [diff] [blame] | 209 | self.idx = test_idx |
mbligh | 250300e | 2007-09-18 00:50:57 +0000 | [diff] [blame] | 210 | self.job = job(db, job_idx) |
mbligh | de7335d | 2007-09-26 16:53:20 +0000 | [diff] [blame] | 211 | self.testname = testname |
mbligh | 8e1ab17 | 2007-09-13 17:29:56 +0000 | [diff] [blame] | 212 | self.subdir = subdir |
mbligh | 50a2525 | 2007-09-27 15:26:17 +0000 | [diff] [blame] | 213 | self.kernel_idx = kernel_idx |
| 214 | self.__kernel = None |
| 215 | self.__iterations = None |
mbligh | 2aaeb67 | 2007-10-01 14:54:18 +0000 | [diff] [blame] | 216 | self.machine_idx = machine_idx |
| 217 | self.__machine = None |
mbligh | 8e1ab17 | 2007-09-13 17:29:56 +0000 | [diff] [blame] | 218 | self.status_num = status_num |
| 219 | self.status_word = db.status_word[status_num] |
mbligh | 9bb92fe | 2007-09-12 15:54:23 +0000 | [diff] [blame] | 220 | self.reason = reason |
mbligh | 50a2525 | 2007-09-27 15:26:17 +0000 | [diff] [blame] | 221 | self.db = db |
mbligh | de7335d | 2007-09-26 16:53:20 +0000 | [diff] [blame] | 222 | if self.subdir: |
| 223 | self.url = html_root + self.job.tag + '/' + self.subdir |
| 224 | else: |
mbligh | 676510c | 2007-09-28 01:28:12 +0000 | [diff] [blame] | 225 | self.url = None |
mbligh | 16ae926 | 2007-09-21 00:53:08 +0000 | [diff] [blame] | 226 | |
mbligh | 50a2525 | 2007-09-27 15:26:17 +0000 | [diff] [blame] | 227 | |
| 228 | |
| 229 | def iterations(self): |
| 230 | """ |
| 231 | Caching function for iterations |
| 232 | """ |
| 233 | if not self.__iterations: |
| 234 | self.__iterations = {} |
| 235 | # A dictionary - dict{key} = [value1, value2, ....] |
| 236 | where = {'test_idx' : self.idx} |
| 237 | for i in iteration.select(self.db, where): |
| 238 | if self.__iterations.has_key(i.key): |
| 239 | self.__iterations[i.key].append(i.value) |
| 240 | else: |
| 241 | self.__iterations[i.key] = [i.value] |
| 242 | return self.__iterations |
| 243 | |
| 244 | |
| 245 | def kernel(self): |
| 246 | """ |
| 247 | Caching function for kernels |
| 248 | """ |
| 249 | if not self.__kernel: |
| 250 | where = {'kernel_idx' : self.kernel_idx} |
| 251 | self.__kernel = kernel.select(self.db, where)[0] |
| 252 | return self.__kernel |
| 253 | |
mbligh | 250300e | 2007-09-18 00:50:57 +0000 | [diff] [blame] | 254 | |
mbligh | 2aaeb67 | 2007-10-01 14:54:18 +0000 | [diff] [blame] | 255 | def machine(self): |
| 256 | """ |
| 257 | Caching function for kernels |
| 258 | """ |
| 259 | if not self.__machine: |
| 260 | where = {'machine_idx' : self.machine_idx} |
| 261 | self.__machine = machine.select(self.db, where)[0] |
| 262 | return self.__machine |
| 263 | |
| 264 | |
mbligh | 250300e | 2007-09-18 00:50:57 +0000 | [diff] [blame] | 265 | class job: |
| 266 | def __init__(self, db, job_idx): |
| 267 | where = {'job_idx' : job_idx} |
mbligh | 2aaeb67 | 2007-10-01 14:54:18 +0000 | [diff] [blame] | 268 | rows = db.select('tag, machine_idx', 'jobs', where) |
mbligh | 250300e | 2007-09-18 00:50:57 +0000 | [diff] [blame] | 269 | if not rows: |
| 270 | return None |
mbligh | 2aaeb67 | 2007-10-01 14:54:18 +0000 | [diff] [blame] | 271 | (self.tag, self.machine_idx) = rows[0] |
mbligh | 2b67253 | 2007-11-05 19:24:51 +0000 | [diff] [blame] | 272 | self.job_idx = job_idx |
mbligh | 250300e | 2007-09-18 00:50:57 +0000 | [diff] [blame] | 273 | |
mbligh | 8e1ab17 | 2007-09-13 17:29:56 +0000 | [diff] [blame] | 274 | |
mbligh | 16ae926 | 2007-09-21 00:53:08 +0000 | [diff] [blame] | 275 | class iteration: |
| 276 | @classmethod |
| 277 | def select(klass, db, where): |
| 278 | fields = ['iteration', 'attribute', 'value'] |
| 279 | iterations = [] |
| 280 | rows = db.select(','.join(fields), 'iteration_result', where) |
| 281 | for row in rows: |
| 282 | iterations.append(klass(*row)) |
| 283 | return iterations |
| 284 | |
| 285 | |
| 286 | def __init__(self, iteration, key, value): |
| 287 | self.iteration = iteration |
| 288 | self.key = key |
| 289 | self.value = value |
| 290 | |
mbligh | 8e1ab17 | 2007-09-13 17:29:56 +0000 | [diff] [blame] | 291 | # class patch: |
| 292 | # def __init__(self): |
| 293 | # self.spec = None |