VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/testmanager/webui/wuiadminsystemchangelog.py@ 65040

Last change on this file since 65040 was 65040, checked in by vboxsync, 8 years ago

testmanager: More details in the system wide changelog.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.5 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: wuiadminsystemchangelog.py 65040 2016-12-31 02:29:50Z vboxsync $
3
4"""
5Test Manager WUI - Admin - System changelog.
6"""
7
8__copyright__ = \
9"""
10Copyright (C) 2012-2016 Oracle Corporation
11
12This file is part of VirtualBox Open Source Edition (OSE), as
13available from http://www.virtualbox.org. This file is free software;
14you can redistribute it and/or modify it under the terms of the GNU
15General Public License (GPL) as published by the Free Software
16Foundation, in version 2 as it comes in the "COPYING" file of the
17VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19
20The contents of this file may alternatively be used under the terms
21of the Common Development and Distribution License Version 1.0
22(CDDL) only, as it comes in the "COPYING.CDDL" file of the
23VirtualBox OSE distribution, in which case the provisions of the
24CDDL are applicable instead of those of the GPL.
25
26You may elect to license modified versions of this file under the
27terms and conditions of either the GPL or the CDDL or both.
28"""
29__version__ = "$Revision: 65040 $"
30
31
32from common import webutils;
33
34# Validation Kit imports.
35from testmanager.webui.wuicontentbase import WuiListContentBase, WuiHtmlKeeper, WuiAdminLink, \
36 WuiMainLink, WuiElementText, WuiHtmlBase;
37
38from testmanager.core.base import AttributeChangeEntryPre;
39from testmanager.core.buildblacklist import BuildBlacklistLogic, BuildBlacklistData;
40from testmanager.core.build import BuildLogic, BuildData;
41from testmanager.core.buildsource import BuildSourceLogic, BuildSourceData;
42from testmanager.core.globalresource import GlobalResourceLogic, GlobalResourceData;
43from testmanager.core.failurecategory import FailureCategoryLogic, FailureCategoryData;
44from testmanager.core.failurereason import FailureReasonLogic, FailureReasonData;
45from testmanager.core.systemlog import SystemLogData;
46from testmanager.core.systemchangelog import SystemChangelogLogic;
47from testmanager.core.schedgroup import SchedGroupLogic, SchedGroupData;
48from testmanager.core.testbox import TestBoxLogic, TestBoxData;
49from testmanager.core.testcase import TestCaseLogic, TestCaseData;
50from testmanager.core.testgroup import TestGroupLogic, TestGroupData;
51from testmanager.core.testset import TestSetData;
52from testmanager.core.useraccount import UserAccountLogic, UserAccountData;
53
54
55class WuiAdminSystemChangelogList(WuiListContentBase):
56 """
57 WUI System Changelog Content Generator.
58 """
59
60 def __init__(self, aoEntries, iPage, cItemsPerPage, tsEffective, fnDPrint, oDisp, cDaysBack):
61 WuiListContentBase.__init__(self, aoEntries, iPage, cItemsPerPage, tsEffective, 'System Changelog',
62 fnDPrint = fnDPrint, oDisp = oDisp);
63 self._asColumnHeaders = [ 'When', 'User', 'Event', 'Details' ];
64 self._asColumnAttribs = [ 'align="center"', 'align="center"', '', '' ];
65 self._oBuildBlacklistLogic = BuildBlacklistLogic(oDisp.getDb());
66 self._oBuildLogic = BuildLogic(oDisp.getDb());
67 self._oBuildSourceLogic = BuildSourceLogic(oDisp.getDb());
68 self._oFailureCategoryLogic = FailureCategoryLogic(oDisp.getDb());
69 self._oFailureReasonLogic = FailureReasonLogic(oDisp.getDb());
70 self._oGlobalResourceLogic = GlobalResourceLogic(oDisp.getDb());
71 self._oSchedGroupLogic = SchedGroupLogic(oDisp.getDb());
72 self._oTestBoxLogic = TestBoxLogic(oDisp.getDb());
73 self._oTestCaseLogic = TestCaseLogic(oDisp.getDb());
74 self._oTestGroupLogic = TestGroupLogic(oDisp.getDb());
75 self._oUserAccountLogic = UserAccountLogic(oDisp.getDb());
76 self._sPrevDate = '';
77 _ = cDaysBack;
78
79 # oDetails = self._createBlacklistingDetailsLink(oEntry.idWhat, oEntry.tsEffective);
80 def _createBlacklistingDetailsLink(self, idBlacklisting, tsEffective):
81 """ Creates a link to the build source details. """
82 oBlacklisting = self._oBuildBlacklistLogic.cachedLookup(idBlacklisting);
83 if oBlacklisting is not None:
84 from testmanager.webui.wuiadmin import WuiAdmin;
85 return WuiAdminLink('Blacklisting #%u' % (oBlacklisting.idBlacklisting,),
86 WuiAdmin.ksActionBuildBlacklistDetails, tsEffective,
87 { BuildBlacklistData.ksParam_idBlacklisting: oBlacklisting.idBlacklisting },
88 fBracketed = False);
89 return WuiElementText('[blacklisting #%u not found]' % (idBlacklisting,));
90
91 def _createBuildDetailsLink(self, idBuild, tsEffective):
92 """ Creates a link to the build details. """
93 oBuild = self._oBuildLogic.cachedLookup(idBuild);
94 if oBuild is not None:
95 from testmanager.webui.wuiadmin import WuiAdmin;
96 return WuiAdminLink('%s %sr%u' % ( oBuild.oCat.sProduct, oBuild.sVersion, oBuild.iRevision),
97 WuiAdmin.ksActionBuildDetails, tsEffective,
98 { BuildData.ksParam_idBuild: oBuild.idBuild },
99 fBracketed = False,
100 sTitle = 'build #%u for %s, type %s'
101 % (oBuild.idBuild, ' & '.join(oBuild.oCat.asOsArches), oBuild.oCat.sType));
102 return WuiElementText('[build #%u not found]' % (idBuild,));
103
104 def _createBuildSourceDetailsLink(self, idBuildSrc, tsEffective):
105 """ Creates a link to the build source details. """
106 oBuildSource = self._oBuildSourceLogic.cachedLookup(idBuildSrc);
107 if oBuildSource is not None:
108 from testmanager.webui.wuiadmin import WuiAdmin;
109 return WuiAdminLink(oBuildSource.sName, WuiAdmin.ksActionBuildSrcDetails, tsEffective,
110 { BuildSourceData.ksParam_idBuildSrc: oBuildSource.idBuildSrc },
111 fBracketed = False,
112 sTitle = 'Build source #%u' % (oBuildSource.idBuildSrc,));
113 return WuiElementText('[build source #%u not found]' % (idBuildSrc,));
114
115 def _createFailureCategoryDetailsLink(self, idFailureCategory, tsEffective):
116 """ Creates a link to the failure category details. """
117 oFailureCategory = self._oFailureCategoryLogic.cachedLookup(idFailureCategory);
118 if oFailureCategory is not None:
119 from testmanager.webui.wuiadmin import WuiAdmin;
120 return WuiAdminLink(oFailureCategory.sShort, WuiAdmin.ksActionFailureCategoryDetails, tsEffective,
121 { FailureCategoryData.ksParam_idFailureCategory: oFailureCategory.idFailureCategory },
122 fBracketed = False,
123 sTitle = 'Failure category #%u' % (oFailureCategory.idFailureCategory,));
124 return WuiElementText('[failure category #%u not found]' % (idFailureCategory,));
125
126 def _createFailureReasonDetailsLink(self, idFailureReason, tsEffective):
127 """ Creates a link to the failure reason details. """
128 oFailureReason = self._oFailureReasonLogic.cachedLookup(idFailureReason);
129 if oFailureReason is not None:
130 from testmanager.webui.wuiadmin import WuiAdmin;
131 return WuiAdminLink(oFailureReason.sShort, WuiAdmin.ksActionFailureReasonDetails, tsEffective,
132 { FailureReasonData.ksParam_idFailureReason: oFailureReason.idFailureReason },
133 fBracketed = False,
134 sTitle = 'Failure reason #%u, category %s'
135 % (oFailureReason.idFailureReason, oFailureReason.oCategory.sShort));
136 return WuiElementText('[failure reason #%u not found]' % (idFailureReason,));
137
138 def _createGlobalResourceDetailsLink(self, idGlobalRsrc, tsEffective):
139 """ Creates a link to the global resource details. """
140 oGlobalResource = self._oGlobalResourceLogic.cachedLookup(idGlobalRsrc);
141 if oGlobalResource is not None:
142 from testmanager.webui.wuiadmin import WuiAdmin;
143 return WuiAdminLink(oGlobalResource.sName, '@todo', tsEffective,
144 { GlobalResourceData.ksParam_idGlobalRsrc: oGlobalResource.idGlobalRsrc },
145 fBracketed = False,
146 sTitle = 'Global resource #%u' % (oGlobalResource.idGlobalRsrc,));
147 return WuiElementText('[global resource #%u not found]' % (idGlobalRsrc,));
148
149 def _createSchedGroupDetailsLink(self, idSchedGroup, tsEffective):
150 """ Creates a link to the scheduling group details. """
151 oSchedGroup = self._oSchedGroupLogic.cachedLookup(idSchedGroup);
152 if oSchedGroup is not None:
153 from testmanager.webui.wuiadmin import WuiAdmin;
154 return WuiAdminLink(oSchedGroup.sName, WuiAdmin.ksActionSchedGroupDetails, tsEffective,
155 { SchedGroupData.ksParam_idSchedGroup: oSchedGroup.idSchedGroup },
156 fBracketed = False,
157 sTitle = 'Scheduling group #%u' % (oSchedGroup.idSchedGroup,));
158 return WuiElementText('[scheduling group #%u not found]' % (idSchedGroup,));
159
160 def _createTestBoxDetailsLink(self, idTestBox, tsEffective):
161 """ Creates a link to the testbox details. """
162 oTestBox = self._oTestBoxLogic.cachedLookup(idTestBox);
163 if oTestBox is not None:
164 from testmanager.webui.wuiadmin import WuiAdmin;
165 return WuiAdminLink(oTestBox.sName, WuiAdmin.ksActionTestBoxDetails, tsEffective,
166 { TestBoxData.ksParam_idTestBox: oTestBox.idTestBox },
167 fBracketed = False, sTitle = 'Testbox #%u' % (oTestBox.idTestBox,));
168 return WuiElementText('[testbox #%u not found]' % (idTestBox,));
169
170 def _createTestCaseDetailsLink(self, idTestCase, tsEffective):
171 """ Creates a link to the test case details. """
172 oTestCase = self._oTestCaseLogic.cachedLookup(idTestCase);
173 if oTestCase is not None:
174 from testmanager.webui.wuiadmin import WuiAdmin;
175 return WuiAdminLink(oTestCase.sName, WuiAdmin.ksActionTestCaseDetails, tsEffective,
176 { TestCaseData.ksParam_idTestCase: oTestCase.idTestCase },
177 fBracketed = False, sTitle = 'Test case #%u' % (oTestCase.idTestCase,));
178 return WuiElementText('[test case #%u not found]' % (idTestCase,));
179
180 def _createTestGroupDetailsLink(self, idTestGroup, tsEffective):
181 """ Creates a link to the test group details. """
182 oTestGroup = self._oTestGroupLogic.cachedLookup(idTestGroup);
183 if oTestGroup is not None:
184 from testmanager.webui.wuiadmin import WuiAdmin;
185 return WuiAdminLink(oTestGroup.sName, WuiAdmin.ksActionTestGroupDetails, tsEffective,
186 { TestGroupData.ksParam_idTestGroup: oTestGroup.idTestGroup },
187 fBracketed = False, sTitle = 'Test group #%u' % (oTestGroup.idTestGroup,));
188 return WuiElementText('[test group #%u not found]' % (idTestGroup,));
189
190 def _createTestSetResultsDetailsLink(self, idTestSet, tsEffective):
191 """ Creates a link to the test set results. """
192 _ = tsEffective;
193 from testmanager.webui.wuimain import WuiMain;
194 return WuiMainLink('test set #%u' % idTestSet, WuiMain.ksActionTestSetDetails,
195 { TestSetData.ksParam_idTestSet: idTestSet }, fBracketed = False);
196
197 def _createTestSetDetailsLinkByResult(self, idTestResult, tsEffective):
198 """ Creates a link to the test set results. """
199 _ = tsEffective;
200 from testmanager.webui.wuimain import WuiMain;
201 return WuiMainLink('test result #%u' % idTestResult, WuiMain.ksActionTestSetDetailsFromResult,
202 { TestSetData.ksParam_idTestResult: idTestResult }, fBracketed = False);
203
204 def _createUserAccountDetailsLink(self, uid, tsEffective):
205 """ Creates a link to the user account details. """
206 oUser = self._oUserAccountLogic.cachedLookup(uid);
207 if oUser is not None:
208 from testmanager.webui.wuiadmin import WuiAdmin;
209 return WuiAdminLink(oUser.sUsername, '@todo', tsEffective, { UserAccountData.ksParam_uid: oUser.uid },
210 fBracketed = False, sTitle = '%s (#%u)' % (oUser.sFullName, oUser.uid));
211 return WuiElementText('[user #%u not found]' % (uid,));
212
213 def _formatDescGeneric(self, sDesc, oEntry):
214 """
215 Generically format system log the description.
216 """
217 oRet = WuiHtmlKeeper();
218 asWords = sDesc.split();
219 for sWord in asWords:
220 offEqual = sWord.find('=');
221 if offEqual > 0:
222 sKey = sWord[:offEqual];
223 try: idValue = int(sWord[offEqual+1:].rstrip('.,'));
224 except: pass;
225 else:
226 if sKey == 'idTestSet':
227 oRet.append(self._createTestSetResultsDetailsLink(idValue, oEntry.tsEffective));
228 continue;
229 if sKey == 'idTestBox':
230 oRet.append(self._createTestBoxDetailsLink(idValue, oEntry.tsEffective));
231 continue;
232 if sKey == 'idSchedGroup':
233 oRet.append(self._createSchedGroupDetailsLink(idValue, oEntry.tsEffective));
234 continue;
235
236 oRet.append(WuiElementText(sWord));
237 return oRet;
238
239 def _formatListEntryHtml(self, iEntry):
240 """
241 Overridden parent method.
242 """
243 oEntry = self._aoEntries[iEntry];
244
245 #
246 # Format the timestamp.
247 #
248 sDate = self.formatTsShort(oEntry.tsEffective);
249 if sDate[:10] == self._sPrevDate:
250 sDate = sDate[11:]
251 else:
252 self._sPrevDate = sDate[:10];
253 sDate = '<b>' + sDate[:10] + '</b><br>' + sDate[11:];
254
255 #
256 # System log events.
257 # pylint: disable=redefined-variable-type
258 #
259 aoChanges = None;
260 if oEntry.sEvent == SystemLogData.ksEvent_CmdNacked:
261 sEvent = 'Command not acknowleged';
262 oDetails = oEntry.sDesc;
263
264 elif oEntry.sEvent == SystemLogData.ksEvent_TestBoxUnknown:
265 sEvent = 'Unknown testbox';
266 oDetails = oEntry.sDesc;
267
268 elif oEntry.sEvent == SystemLogData.ksEvent_TestSetAbandoned:
269 sEvent = 'Abandoned test set';
270 oDetails = self._formatDescGeneric(oEntry.sDesc, oEntry);
271
272 elif oEntry.sEvent == SystemLogData.ksEvent_UserAccountUnknown:
273 sEvent = 'Unknown user account';
274 oDetails = oEntry.sDesc;
275
276 elif oEntry.sEvent == SystemLogData.ksEvent_XmlResultMalformed:
277 sEvent = 'Malformed XML result';
278 oDetails = oEntry.sDesc;
279
280 elif oEntry.sEvent == SystemLogData.ksEvent_SchedQueueRecreate:
281 sEvent = 'Recreating scheduling queue';
282 asWords = oEntry.sDesc.split();
283 if len(asWords) > 3 and asWords[0] == 'User' and asWords[1][0] == '#':
284 try: idAuthor = int(asWords[1][1:]);
285 except: pass;
286 else:
287 oEntry.oAuthor = self._oUserAccountLogic.cachedLookup(idAuthor);
288 if oEntry.oAuthor is not None:
289 i = 2;
290 if asWords[i] == 'recreated': i += 1;
291 oEntry.sDesc = ' '.join(asWords[i:]);
292 oDetails = self._formatDescGeneric(oEntry.sDesc.replace('sched queue #', 'for scheduling group idSchedGroup='),
293 oEntry);
294 #
295 # System changelog events.
296 #
297 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_Blacklisting:
298 sEvent = 'Modified blacklisting';
299 oDetails = self._createBlacklistingDetailsLink(oEntry.idWhat, oEntry.tsEffective);
300
301 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_Build:
302 sEvent = 'Modified build';
303 oDetails = self._createBuildDetailsLink(oEntry.idWhat, oEntry.tsEffective);
304
305 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_BuildSource:
306 sEvent = 'Modified build source';
307 oDetails = self._createBuildSourceDetailsLink(oEntry.idWhat, oEntry.tsEffective);
308
309 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_GlobalRsrc:
310 sEvent = 'Modified global resource';
311 oDetails = self._createGlobalResourceDetailsLink(oEntry.idWhat, oEntry.tsEffective);
312
313 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_FailureCategory:
314 sEvent = 'Modified failure category';
315 oDetails = self._createFailureCategoryDetailsLink(oEntry.idWhat, oEntry.tsEffective);
316 (aoChanges, _) = self._oFailureCategoryLogic.fetchForChangeLog(oEntry.idWhat, 0, 1, oEntry.tsEffective);
317
318 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_FailureReason:
319 sEvent = 'Modified failure reason';
320 oDetails = self._createFailureReasonDetailsLink(oEntry.idWhat, oEntry.tsEffective);
321 (aoChanges, _) = self._oFailureReasonLogic.fetchForChangeLog(oEntry.idWhat, 0, 1, oEntry.tsEffective);
322
323 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_SchedGroup:
324 sEvent = 'Modified scheduling group';
325 oDetails = self._createSchedGroupDetailsLink(oEntry.idWhat, oEntry.tsEffective);
326
327 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_TestBox:
328 sEvent = 'Modified testbox';
329 oDetails = self._createTestBoxDetailsLink(oEntry.idWhat, oEntry.tsEffective);
330 (aoChanges, _) = self._oTestBoxLogic.fetchForChangeLog(oEntry.idWhat, 0, 1, oEntry.tsEffective);
331
332 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_TestCase:
333 sEvent = 'Modified test case';
334 oDetails = self._createTestCaseDetailsLink(oEntry.idWhat, oEntry.tsEffective);
335 (aoChanges, _) = self._oTestCaseLogic.fetchForChangeLog(oEntry.idWhat, 0, 1, oEntry.tsEffective);
336
337 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_TestGroup:
338 sEvent = 'Modified test group';
339 oDetails = self._createTestGroupDetailsLink(oEntry.idWhat, oEntry.tsEffective);
340
341 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_TestResult:
342 sEvent = 'Modified test failure reason';
343 oDetails = self._createTestSetDetailsLinkByResult(oEntry.idWhat, oEntry.tsEffective);
344
345 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_User:
346 sEvent = 'Modified user account';
347 oDetails = self._createUserAccountDetailsLink(oEntry.idWhat, oEntry.tsEffective);
348
349 else:
350 sEvent = '%s(%s)' % (oEntry.sEvent, oEntry.idWhat,);
351 oDetails = '!Unknown event!' + (oEntry.sDesc if oEntry.sDesc else '');
352
353 #
354 # Do the formatting.
355 #
356 sRowClass = 'tmodd' if (iEntry + 1) & 1 else 'tmeven';
357
358 if aoChanges is not None and len(aoChanges) > 0:
359 oChangeEntry = aoChanges[0];
360 cAttribsChanged = len(oChangeEntry.aoChanges) + 1;
361 else:
362 oChangeEntry = None;
363 cAttribsChanged = 1;
364
365 sHtml = u' <tr class="%s">\n' \
366 u' <td rowspan="%d">%s</td>\n' \
367 u' <td rowspan="%d">%s</td>\n' \
368 u' <td rowspan="%d">%s</td>\n' \
369 u' <td colspan="3">%s</td>\n' \
370 u' </tr>\n' \
371 % ( sRowClass,
372 cAttribsChanged, sDate,
373 cAttribsChanged, webutils.escapeElem(oEntry.oAuthor.sUsername if oEntry.oAuthor is not None else ''),
374 cAttribsChanged, webutils.escapeElem(sEvent),
375 oDetails.toHtml() if isinstance(oDetails, WuiHtmlBase) else oDetails,
376 );
377
378 if oChangeEntry is not None:
379 for j, oChange in enumerate(oChangeEntry.aoChanges):
380 if isinstance(oChange, AttributeChangeEntryPre):
381 sHtml += ' <tr class="%s%s tmsyschlogattr"><td>%s</td>'\
382 '<td><div class="tdpre"><pre>%s</pre></div></td>' \
383 '<td><div class="tdpre"><pre>%s</pre></div></td></tr>\n' \
384 % ( sRowClass, 'odd' if j & 1 else 'even',
385 webutils.escapeElem(oChange.sAttr),
386 webutils.escapeElem(oChange.sOldText),
387 webutils.escapeElem(oChange.sNewText), );
388 else:
389 sHtml += ' <tr class="%s%s tmsyschlogattr"><td>%s</td><td>%s</td><td>%s</td></tr>\n' \
390 % ( sRowClass, 'odd' if j & 1 else 'even',
391 webutils.escapeElem(oChange.sAttr),
392 webutils.escapeElem(oChange.sOldText),
393 webutils.escapeElem(oChange.sNewText), );
394 sHtml += u' </tr>\n'
395 return sHtml;
396
397
398 def _generateTableHeaders(self):
399 """
400 Overridden parent method.
401 """
402
403 sHtml = u'<thead class="tmheader">\n' \
404 u' <tr>\n' \
405 u' <th rowspan="2">When</th>\n' \
406 u' <th rowspan="2">Who</th>\n' \
407 u' <th rowspan="2">Event</th>\n' \
408 u' <th colspan="3">Details</th>\n' \
409 u' </tr>\n' \
410 u' <tr>\n' \
411 u' <th>Attribute</th>\n' \
412 u' <th>Old Value</th>\n' \
413 u' <th>New Value</th>\n' \
414 u' </tr>\n' \
415 u'</thead>\n';
416 return sHtml;
417
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette