blob: 4af44ad55e76d6183396213969c2a204ddc560ba [file] [log] [blame]
mbligh2e4e5df2007-11-05 17:22:46 +00001#!/usr/bin/python
2
3"""
4Selects all rows and columns that satisfy the condition specified
5and draws the matrix. There is a seperate SQL query made for every (x,y)
6in the matrix.
7"""
8
9
10print "Content-type: text/html\n"
11import cgi, cgitb, re
mbligha4266932007-11-05 18:12:16 +000012import sys, os
mblighb180f6c2008-01-04 20:24:41 +000013import urllib
mbligh2e4e5df2007-11-05 17:22:46 +000014
15tko = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0])))
16sys.path.insert(0, tko)
17
mbligh2b672532007-11-05 19:24:51 +000018import display, frontend, db, query_lib
mbligh12eebfa2008-01-03 02:01:53 +000019client_bin = os.path.abspath(os.path.join(tko, '../client/bin'))
20sys.path.insert(0, client_bin)
21import kernel_versions
22
mbligh2e4e5df2007-11-05 17:22:46 +000023
mbligh190a81d2007-11-05 20:40:38 +000024html_header = """\
25<form action="compose_query.cgi" method="get">
26<table border="0">
27<tr>
28 <td>Column: </td>
29 <td>Row: </td>
30 <td>Condition: </td>
31 <td align="center"><a href="index.html">Help</a></td>
32</tr>
33<tr>
34 <td>
35 <SELECT NAME="columns">
36 %s
37 </SELECT>
38 </td>
39 <td>
40 <SELECT NAME="rows">
41 %s
42 </SELECT>
43 </td>
44 <td>
mbligh12eebfa2008-01-03 02:01:53 +000045 <input type="text" name="condition" size="30" maxlength="200" value="%s">
mbligh190a81d2007-11-05 20:40:38 +000046 <input type="hidden" name="title" value="Report">
47 </td>
48 <td align="center"><input type="submit" value="Submit">
49 </td>
50</tr>
51</table>
52</form>
53"""
54
mbligh12eebfa2008-01-03 02:01:53 +000055
mbligh5dd503b2008-01-03 16:35:27 +000056next_field = {
57 'machine_group': 'hostname',
58 'hostname': 'tag',
59 'tag': 'tag',
60
61 'kernel': 'test',
mbligh439661b2008-02-19 15:57:53 +000062 'test': 'test',
mbligh5dd503b2008-01-03 16:35:27 +000063 'label': 'label',
64
65 'reason': 'reason',
66 'user': 'user',
67 'status': 'status',
68}
69
70
mbligh12eebfa2008-01-03 02:01:53 +000071
72def parse_field(form, form_field, field_default):
73 if not form_field in form:
74 return field_default
75 field_input = form[form_field].value.lower()
mbligh2ba3e732008-01-16 01:30:19 +000076 if field_input and field_input in frontend.test_view_field_dict:
mbligh12eebfa2008-01-03 02:01:53 +000077 return field_input
78 return field_default
79
80
81def parse_condition(form, form_field, field_default):
82 if not form_field in form:
83 return field_default
84 return form[form_field].value
85
86
87form = cgi.FieldStorage()
mbligh2ba3e732008-01-16 01:30:19 +000088row = parse_field(form, 'rows', 'kernel')
89column = parse_field(form, 'columns', 'machine_group')
mbligh12eebfa2008-01-03 02:01:53 +000090condition_field = parse_condition(form, 'condition', '')
mbligh439661b2008-02-19 15:57:53 +000091## caller can specify rows and columns that shall be included into the report
92## regardless of whether actual test data is available yet
93force_row_field = parse_condition(form,'force_row','')
94force_column_field = parse_condition(form,'force_column','')
mbligh190a81d2007-11-05 20:40:38 +000095
mbligh439661b2008-02-19 15:57:53 +000096def split_forced_fields(force_field):
97 if force_field:
98 return force_field.split()
99 else:
100 return []
101
102force_row = split_forced_fields(force_row_field)
103force_column = split_forced_fields(force_column_field)
104
mbligh2e4e5df2007-11-05 17:22:46 +0000105cgitb.enable()
106db = db.db()
107
mbligh12eebfa2008-01-03 02:01:53 +0000108
mbligh2ba3e732008-01-16 01:30:19 +0000109def construct_link(x, y):
110 next_row = row
111 next_column = column
mbligh5dd503b2008-01-03 16:35:27 +0000112 condition_list = []
113 if condition_field != '':
114 condition_list.append(condition_field)
mbligh2ba3e732008-01-16 01:30:19 +0000115 if y:
116 next_row = next_field[row]
117 condition_list.append("%s='%s'" % (row, y))
118 if x:
119 next_column = next_field[column]
120 condition_list.append("%s='%s'" % (column, x))
mblighb180f6c2008-01-04 20:24:41 +0000121 next_condition = '&'.join(condition_list)
122 return 'compose_query.cgi?' + urllib.urlencode({'columns': next_column,
123 'rows': next_row, 'condition': next_condition})
mbligh5dd503b2008-01-03 16:35:27 +0000124
125
mbligh12eebfa2008-01-03 02:01:53 +0000126def create_select_options(selected_val):
mbligh190a81d2007-11-05 20:40:38 +0000127 ret = ""
mbligh190a81d2007-11-05 20:40:38 +0000128
mbligh2ba3e732008-01-16 01:30:19 +0000129 for option in sorted(frontend.test_view_field_dict.keys()):
mbligh190a81d2007-11-05 20:40:38 +0000130 if selected_val == option:
131 selected = " SELECTED"
132 else:
133 selected = ""
134
mbligh2ba3e732008-01-16 01:30:19 +0000135 ret += '<OPTION VALUE="%s"%s>%s</OPTION>\n' % \
136 (option, selected, option)
mbligh190a81d2007-11-05 20:40:38 +0000137
138 return ret
139
140
apw7a7316b2008-02-21 17:42:05 +0000141def map_kernel_base(kernel_name):
mbligh439661b2008-02-19 15:57:53 +0000142 ## insert <br> after each / in kernel name
143 ## but spare consequtive //
mbligh8e7c78e2008-02-20 21:18:49 +0000144 kernel_name = kernel_name.replace('/','/<br>')
145 kernel_name = kernel_name.replace('/<br>/<br>','//')
mbligh439661b2008-02-19 15:57:53 +0000146 return kernel_name
147
148
apw7a7316b2008-02-21 17:42:05 +0000149# Kernel name mappings -- the kernels table 'printable' field is
150# effectively a sortable identifier for the kernel It encodes the base
151# release which is used for overall sorting, plus where patches are
152# applied it adds an increasing pNNN patch combination identifier
153# (actually the kernel_idx for the entry). This allows sorting
154# as normal by the base kernel version and then sub-sorting by the
155# "first time we saw" a patch combination which should keep them in
156# approximatly date order. This patch identifier is not suitable
157# for display, so we have to map it to a suitable html fragment for
158# display. This contains the kernel base version plus the truncated
159# names of all the patches,
160#
161# 2.6.24-mm1 p112
162# +add-new-string-functions-
163# +x86-amd-thermal-interrupt
164#
165# This mapping is produced when the first mapping is request, with
166# a single query over the patches table; the result is then cached.
167#
168# Note: that we only count a base version as patched if it contains
169# patches which are not already "expressed" in the base version.
170# This includes both -gitN and -mmN kernels.
171map_kernel_map = None
172
173
174def map_kernel_init():
175 fields = ['base', 'k.kernel_idx', 'name', 'url']
176 map = {}
177 for (base, idx, name, url) in db.select(','.join(fields),
178 'kernels k,patches p', 'k.kernel_idx=p.kernel_idx'):
179 match = re.match(r'.*(-mm[0-9]+|-git[0-9]+)\.(bz2|gz)$', url)
180 if match:
181 continue
182
183 key = base + ' p%d' % (idx)
184 if not map.has_key(key):
185 map[key] = map_kernel_base(base) + ' p%d' % (idx)
186 map[key] += '<br>+<span title="' + name + '">' + name[0:25] + '</span>'
187
188 return map
189
190
191def map_kernel(name):
192 global map_kernel_map
193 if map_kernel_map == None:
194 map_kernel_map = map_kernel_init()
195
196 if map_kernel_map.has_key(name):
197 return map_kernel_map[name]
198
199 return map_kernel_base(name.split(' ')[0])
200
201
202field_map = {
203 'kernel':map_kernel
204}
205
206
mbligh12eebfa2008-01-03 02:01:53 +0000207def gen_matrix():
mbligh12eebfa2008-01-03 02:01:53 +0000208 where = None
209 if condition_field.strip() != '':
210 where = query_lib.parse_scrub_and_gen_condition(
mbligh2ba3e732008-01-16 01:30:19 +0000211 condition_field, frontend.test_view_field_dict)
mbligh12eebfa2008-01-03 02:01:53 +0000212 print "<!-- where clause: %s -->" % (where,)
mbligh2e4e5df2007-11-05 17:22:46 +0000213
mbligh2ba3e732008-01-16 01:30:19 +0000214 test_data = frontend.get_matrix_data(db, column, row, where)
mbligh439661b2008-02-19 15:57:53 +0000215
216 for f_row in force_row:
217 if not f_row in test_data.y_values:
218 test_data.y_values.append(f_row)
219 for f_column in force_column:
220 if not f_column in test_data.x_values:
221 test_data.x_values.append(f_column)
mbligh2e4e5df2007-11-05 17:22:46 +0000222
mbligh2ba3e732008-01-16 01:30:19 +0000223 if not test_data.y_values:
mbligh12eebfa2008-01-03 02:01:53 +0000224 msg = "There are no results for this query (yet?)."
225 return [[display.box(msg)]]
mbligh2e4e5df2007-11-05 17:22:46 +0000226
mbligh5dd503b2008-01-03 16:35:27 +0000227 link = 'compose_query.cgi?columns=%s&rows=%s&condition=%s' % (
mbligh2ba3e732008-01-16 01:30:19 +0000228 row, column, condition_field)
mbligh5dd503b2008-01-03 16:35:27 +0000229 header_row = [display.box("<center>(Flip Axis)</center>", link=link)]
230
mbligh2ba3e732008-01-16 01:30:19 +0000231 for x in test_data.x_values:
232 link = construct_link(x, None)
apw7a7316b2008-02-21 17:42:05 +0000233 dx = x
234 if field_map.has_key(column):
235 dx = field_map[column](x)
236 header_row.append(display.box(dx, header=True, link=link))
mbligh2e4e5df2007-11-05 17:22:46 +0000237
238 matrix = [header_row]
mbligh2ba3e732008-01-16 01:30:19 +0000239 for y in test_data.y_values:
240 link = construct_link(None, y)
apw7a7316b2008-02-21 17:42:05 +0000241 dy = y
242 if field_map.has_key(row):
243 dy = field_map[row](y)
244 cur_row = [display.box(dy, header=True, link=link)]
mbligh2ba3e732008-01-16 01:30:19 +0000245 for x in test_data.x_values:
mbligh12eebfa2008-01-03 02:01:53 +0000246 try:
mbligh2ba3e732008-01-16 01:30:19 +0000247 box_data = test_data.data[x][y].status_count
mbligh12eebfa2008-01-03 02:01:53 +0000248 except:
249 cur_row.append(display.box(None, None))
250 continue
mbligh2ba3e732008-01-16 01:30:19 +0000251 job_tag = test_data.data[x][y].job_tag
mbligh5dd503b2008-01-03 16:35:27 +0000252 if job_tag:
mblighe47ff2a2008-02-28 00:44:11 +0000253 link = frontend.html_root + job_tag + '/'
mbligh439661b2008-02-19 15:57:53 +0000254 if (row == 'test' and
255 not 'boot' in y and
256 not 'build' in y and
257 not 'install' in y ):
258 link += y + '/'
259 if (column == 'test' and
260 not 'boot' in x and
261 not 'build' in x and
262 not 'install' in x):
263 link += x + '/'
mbligh5dd503b2008-01-03 16:35:27 +0000264 else:
mbligh2ba3e732008-01-16 01:30:19 +0000265 link = construct_link(x, y)
mbligh12eebfa2008-01-03 02:01:53 +0000266 cur_row.append(display.status_precounted_box(db,
mbligh5dd503b2008-01-03 16:35:27 +0000267 box_data,
268 link))
mbligh12eebfa2008-01-03 02:01:53 +0000269 matrix.append(cur_row)
mbligh2e4e5df2007-11-05 17:22:46 +0000270
mbligh12eebfa2008-01-03 02:01:53 +0000271 return matrix
mbligh2b672532007-11-05 19:24:51 +0000272
mbligh2b672532007-11-05 19:24:51 +0000273
mbligh12eebfa2008-01-03 02:01:53 +0000274def main():
mbligh190a81d2007-11-05 20:40:38 +0000275 # create the actual page
mbligh190a81d2007-11-05 20:40:38 +0000276 print '<html><head><title>'
277 print 'Filtered Autotest Results'
278 print '</title></head><body>'
mbligh14671622008-01-11 16:49:54 +0000279 display.print_main_header()
mbligh2ba3e732008-01-16 01:30:19 +0000280 print html_header % (create_select_options(column),
281 create_select_options(row),
mbligh12eebfa2008-01-03 02:01:53 +0000282 condition_field)
mbligh439661b2008-02-19 15:57:53 +0000283 print display.color_keys_row()
mbligh12eebfa2008-01-03 02:01:53 +0000284 display.print_table(gen_matrix())
mbligh439661b2008-02-19 15:57:53 +0000285 print display.color_keys_row()
mbligh190a81d2007-11-05 20:40:38 +0000286 print '</body></html>'
mbligh2e4e5df2007-11-05 17:22:46 +0000287
288
289main()