1 import os
, re
, db
, sys
, datetime
3 from autotest_lib
.client
.common_lib
import kernel_versions
8 tko
= os
.path
.dirname(os
.path
.realpath(os
.path
.abspath(__file__
)))
9 root_url_file
= os
.path
.join(tko
, '.root_url')
10 if os
.path
.exists(root_url_file
):
11 html_root
= open(root_url_file
, 'r').readline().rstrip()
13 html_root
= '/results/'
17 # One cell in the matrix of status data.
19 # Count is a dictionary: status -> count of tests with status
20 self
.status_count
= {}
21 self
.reasons_list
= []
23 self
.job_tag_count
= 0
26 def add(self
, status
, count
, job_tags
, reasons
= None):
29 self
.job_tag
= job_tags
30 self
.job_tag_count
+= count
31 if self
.job_tag_count
> 1:
34 self
.status_count
[status
] = count
35 ### status == 6 means 'GOOD'
37 ## None implies sorting problems and extra CRs in a cell
39 self
.reasons_list
.append(reasons
)
43 def __init__(self
, sql_rows
, x_field
, y_field
, query_reasons
= False):
47 # Walk through the query, filing all results by x, y info
50 (x
,y
, status
, count
, job_tags
, reasons
) = row
52 (x
,y
, status
, count
, job_tags
) = row
54 if not data
.has_key(x
):
56 if not data
[x
].has_key(y
):
58 data
[x
][y
] = status_cell()
59 data
[x
][y
].add(status
, count
, job_tags
, reasons
)
61 # 2-d hash of data - [x-value][y-value]
63 # List of possible columns (x-values)
64 self
.x_values
= smart_sort(data
.keys(), x_field
)
65 # List of rows columns (y-values)
66 self
.y_values
= smart_sort(list(y_values
), y_field
)
67 nCells
= len(self
.y_values
)*len(self
.x_values
)
68 if nCells
> MAX_CELLS
:
69 msg
= 'Exceeded allowed number of cells in a table'
70 raise db
.MySQLTooManyRows(msg
)
73 def get_matrix_data(db_obj
, x_axis
, y_axis
, where
= None,
74 query_reasons
= False):
75 # Searches on the test_view table - x_axis and y_axis must both be
76 # column names in that table.
77 x_field
= test_view_field_dict
[x_axis
]
78 y_field
= test_view_field_dict
[y_axis
]
79 query_fields_list
= [x_field
, y_field
, 'status','COUNT(status)']
80 query_fields_list
.append("LEFT(GROUP_CONCAT(job_tag),100)")
82 query_fields_list
.append(
83 "LEFT(GROUP_CONCAT(DISTINCT reason SEPARATOR '|'),500)"
85 fields
= ','.join(query_fields_list
)
87 group_by
= '%s, %s, status' % (x_field
, y_field
)
88 rows
= db_obj
.select(fields
, 'tko_test_view',
89 where
=where
, group_by
=group_by
, max_rows
= MAX_RECORDS
)
90 return status_data(rows
, x_field
, y_field
, query_reasons
)
93 # Dictionary used simply for fast lookups from short reference names for users
94 # to fieldnames in test_view
95 test_view_field_dict
= {
96 'kernel' : 'kernel_printable',
97 'hostname' : 'machine_hostname',
99 'label' : 'job_label',
100 'machine_group' : 'machine_group',
103 'user' : 'job_username',
104 'status' : 'status_word',
105 'time' : 'test_finished_time',
106 'start_time' : 'test_started_time',
107 'time_daily' : 'DATE(test_finished_time)'
111 def smart_sort(list, field
):
112 if field
== 'kernel_printable':
113 def kernel_encode(kernel
):
114 return kernel_versions
.version_encode(kernel
)
115 list.sort(key
= kernel_encode
, reverse
= True)
117 ## old records may contain time=None
118 ## make None comparable with timestamp datetime or date
119 elif field
== 'test_finished_time':
120 def convert_None_to_datetime(date_time
):
122 return datetime
.datetime(1970, 1, 1, 0, 0, 0)
125 list = map(convert_None_to_datetime
, list)
126 elif field
== 'DATE(test_finished_time)':
127 def convert_None_to_date(date
):
129 return datetime
.date(1970, 1, 1)
132 list = map(convert_None_to_date
, list)
139 def select(klass
, db
):
140 """Return all possible machine groups"""
141 rows
= db
.select('distinct machine_group', 'tko_machines',
142 'machine_group is not null')
143 groupnames
= sorted([row
[0] for row
in rows
])
144 return [klass(db
, groupname
) for groupname
in groupnames
]
147 def __init__(self
, db
, name
):
153 return machine
.select(self
.db
, { 'machine_group' : self
.name
})
156 def tests(self
, where
= {}):
158 sql
= 't inner join tko_machines m on m.machine_idx=t.machine_idx'
159 sql
+= ' where m.machine_group=%s'
160 for key
in where
.keys():
161 sql
+= ' and %s=%%s' % key
162 values
.append(where
[key
])
163 return test
.select_sql(self
.db
, sql
, values
)
168 def select(klass
, db
, where
= {}):
169 fields
= ['machine_idx', 'hostname', 'machine_group', 'owner']
171 for row
in db
.select(','.join(fields
), 'tko_machines', where
):
172 machines
.append(klass(db
, *row
))
176 def __init__(self
, db
, idx
, hostname
, group
, owner
):
179 self
.hostname
= hostname
186 def select(klass
, db
, where
= {}):
187 fields
= ['kernel_idx', 'kernel_hash', 'base', 'printable']
188 rows
= db
.select(','.join(fields
), 'tko_kernels', where
)
189 return [klass(db
, *row
) for row
in rows
]
192 def __init__(self
, db
, idx
, hash, base
, printable
):
197 self
.printable
= printable
198 self
.patches
= [] # THIS SHOULD PULL IN PATCHES!
203 def select(klass
, db
, where
={}, distinct
=False):
204 fields
= ['test_idx', 'job_idx', 'test', 'subdir',
205 'kernel_idx', 'status', 'reason', 'machine_idx']
207 for row
in db
.select(','.join(fields
), 'tko_tests', where
,
209 tests
.append(klass(db
, *row
))
214 def select_sql(klass
, db
, sql
, values
):
215 fields
= ['test_idx', 'job_idx', 'test', 'subdir',
216 'kernel_idx', 'status', 'reason', 'machine_idx']
217 fields
= ['t.'+field
for field
in fields
]
218 rows
= db
.select_sql(','.join(fields
), 'tko_tests', sql
, values
)
219 return [klass(db
, *row
) for row
in rows
]
222 def __init__(self
, db
, test_idx
, job_idx
, testname
, subdir
, kernel_idx
,
223 status_num
, reason
, machine_idx
):
225 self
.job
= job(db
, job_idx
)
226 self
.testname
= testname
228 self
.kernel_idx
= kernel_idx
230 self
.__iterations
= None
231 self
.machine_idx
= machine_idx
232 self
.__machine
= None
233 self
.status_num
= status_num
234 self
.status_word
= db
.status_word
[status_num
]
238 self
.url
= html_root
+ self
.job
.tag
+ '/' + self
.subdir
243 def iterations(self
):
245 Caching function for iterations
247 if not self
.__iterations
:
248 self
.__iterations
= {}
249 # A dictionary - dict{key} = [value1, value2, ....]
250 where
= {'test_idx' : self
.idx
}
251 for i
in iteration
.select(self
.db
, where
):
252 if self
.__iterations
.has_key(i
.key
):
253 self
.__iterations
[i
.key
].append(i
.value
)
255 self
.__iterations
[i
.key
] = [i
.value
]
256 return self
.__iterations
261 Caching function for kernels
263 if not self
.__kernel
:
264 where
= {'kernel_idx' : self
.kernel_idx
}
265 self
.__kernel
= kernel
.select(self
.db
, where
)[0]
271 Caching function for kernels
273 if not self
.__machine
:
274 where
= {'machine_idx' : self
.machine_idx
}
275 self
.__machine
= machine
.select(self
.db
, where
)[0]
276 return self
.__machine
280 def __init__(self
, db
, job_idx
):
281 where
= {'job_idx' : job_idx
}
282 rows
= db
.select('tag, machine_idx', 'tko_jobs', where
)
284 self
.tag
, self
.machine_idx
= rows
[0]
285 self
.job_idx
= job_idx
290 def select(klass
, db
, where
):
291 fields
= ['iteration', 'attribute', 'value']
293 rows
= db
.select(','.join(fields
), 'tko_iteration_result', where
)
295 iterations
.append(klass(*row
))
299 def __init__(self
, iteration
, key
, value
):
300 self
.iteration
= iteration
305 # def __init__(self):