def __init__(self, aoEntries, iPage, cItemsPerPage, tsEffective, fnDPrint, oDisp, cDaysBack, aiSelectedSortColumns=None): WuiListContentBase.__init__( self, aoEntries, iPage, cItemsPerPage, tsEffective, 'System Changelog', fnDPrint=fnDPrint, oDisp=oDisp, aiSelectedSortColumns=aiSelectedSortColumns) self._asColumnHeaders = ['When', 'User', 'Event', 'Details'] self._asColumnAttribs = ['align="center"', 'align="center"', '', ''] self._oBuildBlacklistLogic = BuildBlacklistLogic(oDisp.getDb()) self._oBuildLogic = BuildLogic(oDisp.getDb()) self._oBuildSourceLogic = BuildSourceLogic(oDisp.getDb()) self._oFailureCategoryLogic = FailureCategoryLogic(oDisp.getDb()) self._oFailureReasonLogic = FailureReasonLogic(oDisp.getDb()) self._oGlobalResourceLogic = GlobalResourceLogic(oDisp.getDb()) self._oSchedGroupLogic = SchedGroupLogic(oDisp.getDb()) self._oTestBoxLogic = TestBoxLogic(oDisp.getDb()) self._oTestCaseLogic = TestCaseLogic(oDisp.getDb()) self._oTestGroupLogic = TestGroupLogic(oDisp.getDb()) self._oUserAccountLogic = UserAccountLogic(oDisp.getDb()) self._sPrevDate = '' _ = cDaysBack
def removeEntry(self, uidAuthor, idSchedGroup, fCascade = False, fCommit = False): """ Deletes a scheduling group. """ # # Input validation and retrival of current data. # if idSchedGroup == 1: raise TMExceptionBase('Cannot remove the default scheduling group (id 1).'); oData = SchedGroupDataEx().initFromDbWithId(self._oDb, idSchedGroup); # # We use cascade a little different here... We don't actually delete # associated testboxes or testgroups. # if len(oData.aoTestBoxes) > 0: if fCascade is not True: # Complain about there being associated testboxes. asTestBoxes = ['%s (#%d)' % (oTestBox.sName, oTestBox.idTestBox) for oTestBox in oData.aoTestBoxes]; raise TMExceptionBase('Scheduling group #%d is associated with one or more test boxes: %s' % (idSchedGroup, ', '.join(asTestBoxes),)); else: # Reassign testboxes to scheduling group #1 (the default group). oTbLogic = TestBoxLogic(self._oDb); for oTestBox in oData.aoTestBoxes: oTbCopy = TestBoxData().initFromOther(oTestBox); oTbCopy.idSchedGroup = 1; oTbLogic.editEntry(oTbCopy, uidAuthor, fCommit = False); oData = SchedGroupDataEx().initFromDbWithId(self._oDb, idSchedGroup); if len(oData.aoTestBoxes) != 0: raise TMExceptionBase('More testboxes was added to the scheduling group as we were trying to delete it.'); # # Remove the group and all member records. # for oMember in oData.aoMembers: self._removeSchedGroupMember(uidAuthor, oMember); self._oDb.execute('UPDATE SchedGroupMembers\n' 'SET tsExpire = CURRENT_TIMESTAMP\n' 'WHERE idSchedGroup = %s\n' ' AND tsExpire = \'infinity\'::TIMESTAMP\n' , (idSchedGroup,)); (tsCur, tsCurMinusOne) = self._oDb.getCurrentTimestamps(); if oData.tsEffective != tsCur and oData.tsEffective != tsCurMinusOne: self._historizeEntry(idSchedGroup, tsCurMinusOne); self._readdEntry(uidAuthor, oData, tsCurMinusOne); self._historizeEntry(idSchedGroup); self._oDb.execute('UPDATE SchedGroups\n' 'SET tsExpire = CURRENT_TIMESTAMP\n' 'WHERE idSchedGroup = %s\n' ' AND tsExpire = \'infinity\'::TIMESTAMP\n' , (idSchedGroup,)) self._oDb.maybeCommit(fCommit) return True;
def removeEntry(self, uidAuthor, idSchedGroup, fCascade = False, fCommit = False): """ Deletes a scheduling group. """ # # Input validation and retrival of current data. # if idSchedGroup == 1: raise TMRowInUse('Cannot remove the default scheduling group (id 1).'); oData = SchedGroupDataEx().initFromDbWithId(self._oDb, idSchedGroup); # # We use cascade a little different here... We don't actually delete # associated testboxes or testgroups. # if oData.aoTestBoxes: if fCascade is not True: # Complain about there being associated testboxes. asTestBoxes = ['%s (#%d)' % (oTestBox.sName, oTestBox.idTestBox) for oTestBox in oData.aoTestBoxes]; raise TMRowInUse('Scheduling group #%d is associated with one or more test boxes: %s' % (idSchedGroup, ', '.join(asTestBoxes),)); else: # Reassign testboxes to scheduling group #1 (the default group). oTbLogic = TestBoxLogic(self._oDb); for oTestBox in oData.aoTestBoxes: oTbCopy = TestBoxData().initFromOther(oTestBox); oTbCopy.idSchedGroup = 1; oTbLogic.editEntry(oTbCopy, uidAuthor, fCommit = False); oData = SchedGroupDataEx().initFromDbWithId(self._oDb, idSchedGroup); if oData.aoTestBoxes: raise TMRowInUse('More testboxes was added to the scheduling group as we were trying to delete it.'); # # Remove the group and all member records. # for oMember in oData.aoMembers: self._removeSchedGroupMember(uidAuthor, oMember); self._oDb.execute('UPDATE SchedGroupMembers\n' 'SET tsExpire = CURRENT_TIMESTAMP\n' 'WHERE idSchedGroup = %s\n' ' AND tsExpire = \'infinity\'::TIMESTAMP\n' , (idSchedGroup,)); (tsCur, tsCurMinusOne) = self._oDb.getCurrentTimestamps(); if oData.tsEffective != tsCur and oData.tsEffective != tsCurMinusOne: self._historizeEntry(idSchedGroup, tsCurMinusOne); self._readdEntry(uidAuthor, oData, tsCurMinusOne); self._historizeEntry(idSchedGroup); self._oDb.execute('UPDATE SchedGroups\n' 'SET tsExpire = CURRENT_TIMESTAMP\n' 'WHERE idSchedGroup = %s\n' ' AND tsExpire = \'infinity\'::TIMESTAMP\n' , (idSchedGroup,)) self._oDb.maybeCommit(fCommit) return True;
def __init__(self, oData, sMode, oDisp): assert isinstance(oData, SchedGroupData) if sMode == WuiFormContentBase.ksMode_Add: sTitle = 'New Scheduling Group' elif sMode == WuiFormContentBase.ksMode_Edit: sTitle = 'Edit Scheduling Group' else: assert sMode == WuiFormContentBase.ksMode_Show sTitle = 'Scheduling Group' WuiFormContentBase.__init__(self, oData, sMode, 'SchedGroup', oDisp, sTitle) # Read additional bits form the DB, unless we're in if sMode != WuiFormContentBase.ksMode_Show: self._aoAllRelevantTestGroups = TestGroupLogic( oDisp.getDb()).getAll() self._aoAllRelevantTestBoxes = TestBoxLogic( oDisp.getDb()).getAll() else: self._aoAllRelevantTestGroups = [ oMember.oTestGroup for oMember in oData.aoMembers ] self._aoAllRelevantTestBoxes = [ oMember.oTestBox for oMember in oData.aoTestBoxes ]
def _actionTestBoxListPost(self): """Actions on a list of testboxes.""" # Parameters. aidTestBoxes = self.getListOfIntParams(TestBoxData.ksParam_idTestBox, iMin = 1, aiDefaults = []); sListAction = self.getStringParam(self.ksParamListAction); if sListAction in [asDesc[0] for asDesc in WuiTestBoxList.kasTestBoxActionDescs]: idAction = None; else: asActionPrefixes = [ 'setgroup-', ]; i = 0; while i < len(asActionPrefixes) and not sListAction.startswith(asActionPrefixes[i]): i += 1; if i >= len(asActionPrefixes): raise WuiException('Parameter "%s" has an invalid value: "%s"' % (self.ksParamListAction, sListAction,)); idAction = sListAction[len(asActionPrefixes[i]):]; if not idAction.isdigit(): raise WuiException('Parameter "%s" has an invalid value: "%s"' % (self.ksParamListAction, sListAction,)); idAction = int(idAction); sListAction = sListAction[:len(asActionPrefixes[i]) - 1]; self._checkForUnknownParameters(); # Take action. if sListAction is 'none': pass; else: oLogic = TestBoxLogic(self._oDb); aoTestBoxes = [] for idTestBox in aidTestBoxes: aoTestBoxes.append(TestBoxData().initFromDbWithId(self._oDb, idTestBox)); if sListAction in [ 'enable', 'disable' ]: fEnable = sListAction == 'enable'; for oTestBox in aoTestBoxes: if oTestBox.fEnabled != fEnable: oTestBox.fEnabled = fEnable; oLogic.editEntry(oTestBox, self._oCurUser.uid, fCommit = False); elif sListAction == 'setgroup': for oTestBox in aoTestBoxes: if oTestBox.idSchedGroup != idAction: oTestBox.idSchedGroup = idAction; oLogic.editEntry(oTestBox, self._oCurUser.uid, fCommit = False); else: for oTestBox in aoTestBoxes: if oTestBox.enmPendingCmd != sListAction: oTestBox.enmPendingCmd = sListAction; oLogic.editEntry(oTestBox, self._oCurUser.uid, fCommit = False); self._oDb.commit(); # Re-display the list. self._sPageTitle = None; self._sPageBody = None; self._sRedirectTo = self._sActionUrlBase + self.ksActionTestBoxList; return True;
def _doCommandAckNck(self, sCmd): """ Implements ACK, NACK and NACK(ENOTSUP). """ (oDb, _, _) = self._connectToDbAndValidateTb() if oDb is None: return False # # If the command maps to a TestBoxCmd_T value, it means we have to # check and update TestBoxes. If it's an ACK, the testbox status will # need updating as well. # sPendingCmd = TestBoxController.kdTbRespCmdToCmd[sCmd] if sPendingCmd is not None: oTestBoxLogic = TestBoxLogic(oDb) oTestBoxLogic.setCommand(self._idTestBox, sOldCommand=sPendingCmd, sNewCommand=TestBoxData.ksTestBoxCmd_None, fCommit=False) if self._sAction == constants.tbreq.COMMAND_ACK \ and TestBoxController.kdCmdToState[sPendingCmd] is not None: oStatusLogic = TestBoxStatusLogic(oDb) oStatusLogic.updateState( self._idTestBox, TestBoxController.kdCmdToState[sPendingCmd], fCommit=False) # Commit the two updates. oDb.commit() # # Log NACKs. # if self._sAction != constants.tbreq.COMMAND_ACK: oSysLogLogic = SystemLogLogic(oDb) oSysLogLogic.addEntry(SystemLogData.ksEvent_CmdNacked, 'idTestBox=%s sCmd=%s' % (self._idTestBox, sPendingCmd), 24, fCommit=True) return self._resultResponse(constants.tbresp.STATUS_ACK)
def _doCommandAckNck(self, sCmd): """ Implements ACK, NACK and NACK(ENOTSUP). """ (oDb, _, _) = self._connectToDbAndValidateTb(); if oDb is None: return False; # # If the command maps to a TestBoxCmd_T value, it means we have to # check and update TestBoxes. If it's an ACK, the testbox status will # need updating as well. # sPendingCmd = TestBoxController.kdTbRespCmdToCmd[sCmd]; if sPendingCmd is not None: oTestBoxLogic = TestBoxLogic(oDb) oTestBoxLogic.setCommand(self._idTestBox, sOldCommand = sPendingCmd, sNewCommand = TestBoxData.ksTestBoxCmd_None, fCommit = False); if self._sAction == constants.tbreq.COMMAND_ACK \ and TestBoxController.kdCmdToState[sPendingCmd] is not None: oStatusLogic = TestBoxStatusLogic(oDb); oStatusLogic.updateState(self._idTestBox, TestBoxController.kdCmdToState[sPendingCmd], fCommit = False); # Commit the two updates. oDb.commit(); # # Log NACKs. # if self._sAction != constants.tbreq.COMMAND_ACK: oSysLogLogic = SystemLogLogic(oDb); oSysLogLogic.addEntry(SystemLogData.ksEvent_CmdNacked, 'idTestBox=%s sCmd=%s' % (self._idTestBox, sPendingCmd), 24, fCommit = True); return self._resultResponse(constants.tbresp.STATUS_ACK);
def __init__(self, aoEntries, iPage, cItemsPerPage, tsEffective, fnDPrint, oDisp, cDaysBack, aiSelectedSortColumns = None): WuiListContentBase.__init__(self, aoEntries, iPage, cItemsPerPage, tsEffective, 'System Changelog', fnDPrint = fnDPrint, oDisp = oDisp, aiSelectedSortColumns = aiSelectedSortColumns); self._asColumnHeaders = [ 'When', 'User', 'Event', 'Details' ]; self._asColumnAttribs = [ 'align="center"', 'align="center"', '', '' ]; self._oBuildBlacklistLogic = BuildBlacklistLogic(oDisp.getDb()); self._oBuildLogic = BuildLogic(oDisp.getDb()); self._oBuildSourceLogic = BuildSourceLogic(oDisp.getDb()); self._oFailureCategoryLogic = FailureCategoryLogic(oDisp.getDb()); self._oFailureReasonLogic = FailureReasonLogic(oDisp.getDb()); self._oGlobalResourceLogic = GlobalResourceLogic(oDisp.getDb()); self._oSchedGroupLogic = SchedGroupLogic(oDisp.getDb()); self._oTestBoxLogic = TestBoxLogic(oDisp.getDb()); self._oTestCaseLogic = TestCaseLogic(oDisp.getDb()); self._oTestGroupLogic = TestGroupLogic(oDisp.getDb()); self._oUserAccountLogic = UserAccountLogic(oDisp.getDb()); self._sPrevDate = ''; _ = cDaysBack;
def _doRequestCommand(self, fIdle): """ Common code for handling command request. """ (oDb, oStatusData, oTestBoxData) = self._connectToDbAndValidateTb() if oDb is None: return False # # Status clean up. # # Only when BUSY will the TestBox Script request and execute commands # concurrently. So, it must be idle when sending REQUEST_COMMAND_IDLE. # if fIdle: if oStatusData.enmState == TestBoxStatusData.ksTestBoxState_GangGathering: self._doGangGathering(oDb, oStatusData) elif oStatusData.enmState == TestBoxStatusData.ksTestBoxState_GangGatheringTimedOut: self._doGangGatheringTimedOut(oDb, oStatusData) elif oStatusData.enmState == TestBoxStatusData.ksTestBoxState_GangTesting: dResponse = SchedulerBase.composeExecResponse( oDb, oTestBoxData.idTestBox, self._oSrvGlue.getBaseUrl()) if dResponse is not None: return dResponse elif oStatusData.enmState == TestBoxStatusData.ksTestBoxState_GangCleanup: self._doGangCleanup(oDb, oStatusData) elif oStatusData.enmState != TestBoxStatusData.ksTestBoxState_Idle: # (includes ksTestBoxState_GangGatheringTimedOut) self._cleanupOldTest(oDb, oStatusData) # # Check for pending command. # if oTestBoxData.enmPendingCmd != TestBoxData.ksTestBoxCmd_None: asValidCmds = TestBoxController.kasIdleCmds if fIdle else TestBoxController.kasBusyCmds if oTestBoxData.enmPendingCmd in asValidCmds: dResponse = { constants.tbresp.ALL_PARAM_RESULT: TestBoxController.kdCmdToTbRespCmd[ oTestBoxData.enmPendingCmd] } if oTestBoxData.enmPendingCmd in [ TestBoxData.ksTestBoxCmd_Upgrade, TestBoxData.ksTestBoxCmd_UpgradeAndReboot ]: dResponse[constants.tbresp. UPGRADE_PARAM_URL] = self._oSrvGlue.getBaseUrl( ) + TestBoxController.ksUpgradeZip return self._writeResponse(dResponse) if oTestBoxData.enmPendingCmd == TestBoxData.ksTestBoxCmd_Abort and fIdle: TestBoxLogic(oDb).setCommand( self._idTestBox, sOldCommand=oTestBoxData.enmPendingCmd, sNewCommand=TestBoxData.ksTestBoxCmd_None, fCommit=True) # # If doing gang stuff, return 'CMD_WAIT'. # ## @todo r=bird: Why is GangTesting included here? Figure out when testing gang testing. if oStatusData.enmState in [ TestBoxStatusData.ksTestBoxState_GangGathering, TestBoxStatusData.ksTestBoxState_GangTesting, TestBoxStatusData.ksTestBoxState_GangCleanup ]: return self._resultResponse(constants.tbresp.CMD_WAIT) # # If idling and enabled try schedule a new task. # if fIdle \ and oTestBoxData.fEnabled \ and not TestSetLogic(oDb).isTestBoxExecutingToRapidly(oTestBoxData.idTestBox) \ and oStatusData.enmState == TestBoxStatusData.ksTestBoxState_Idle: # (paranoia) dResponse = SchedulerBase.scheduleNewTask( oDb, oTestBoxData, oStatusData.iWorkItem, self._oSrvGlue.getBaseUrl()) if dResponse is not None: return self._writeResponse(dResponse) # # Touch the status row every couple of mins so we can tell that the box is alive. # oStatusLogic = TestBoxStatusLogic(oDb) if oStatusData.enmState != TestBoxStatusData.ksTestBoxState_GangGathering \ and oStatusLogic.timeSinceLastChangeInSecs(oStatusData) >= TestBoxStatusLogic.kcSecIdleTouchStatus: oStatusLogic.touchStatus(oTestBoxData.idTestBox, fCommit=True) return self._idleResponse()
def _actionSignOn(self): # pylint: disable=R0914 """ Implement sign-on """ # # Validate parameters (raises exception on failure). # sOs = self._getStringParam(constants.tbreq.SIGNON_PARAM_OS, coreconsts.g_kasOses) sOsVersion = self._getStringParam( constants.tbreq.SIGNON_PARAM_OS_VERSION) sCpuVendor = self._getStringParam( constants.tbreq.SIGNON_PARAM_CPU_VENDOR) sCpuArch = self._getStringParam(constants.tbreq.SIGNON_PARAM_CPU_ARCH, coreconsts.g_kasCpuArches) sCpuName = self._getStringParam(constants.tbreq.SIGNON_PARAM_CPU_NAME, fStrip=True, sDefValue='') # new lCpuRevision = self._getLongParam( constants.tbreq.SIGNON_PARAM_CPU_REVISION, lMin=0, lDefValue=0) # new cCpus = self._getIntParam(constants.tbreq.SIGNON_PARAM_CPU_COUNT, 1, 16384) fCpuHwVirt = self._getBoolParam( constants.tbreq.SIGNON_PARAM_HAS_HW_VIRT) fCpuNestedPaging = self._getBoolParam( constants.tbreq.SIGNON_PARAM_HAS_NESTED_PAGING) fCpu64BitGuest = self._getBoolParam( constants.tbreq.SIGNON_PARAM_HAS_64_BIT_GUEST, fDefValue=True) fChipsetIoMmu = self._getBoolParam( constants.tbreq.SIGNON_PARAM_HAS_IOMMU) fRawMode = self._getBoolParam( constants.tbreq.SIGNON_PARAM_WITH_RAW_MODE, fDefValue=None) cMbMemory = self._getLongParam(constants.tbreq.SIGNON_PARAM_MEM_SIZE, 8, 1073741823) # 8MB..1PB cMbScratch = self._getLongParam( constants.tbreq.SIGNON_PARAM_SCRATCH_SIZE, 0, 1073741823) # 0..1PB sReport = self._getStringParam(constants.tbreq.SIGNON_PARAM_REPORT, fStrip=True, sDefValue='') # new iTestBoxScriptRev = self._getIntParam( constants.tbreq.SIGNON_PARAM_SCRIPT_REV, 1, 100000000) iPythonHexVersion = self._getIntParam( constants.tbreq.SIGNON_PARAM_PYTHON_VERSION, 0x020300f0, 0x030f00f0) self._checkForUnknownParameters() # Null conversions for new parameters. if not sReport: sReport = None if not sCpuName: sCpuName = None if lCpuRevision <= 0: lCpuRevision = None # # Connect to the database and validate the testbox. # oDb = TMDatabaseConnection(self._oSrvGlue.dprint) oTestBoxLogic = TestBoxLogic(oDb) oTestBox = oTestBoxLogic.tryFetchTestBoxByUuid(self._sTestBoxUuid) if oTestBox is None: oSystemLogLogic = SystemLogLogic(oDb) oSystemLogLogic.addEntry(SystemLogData.ksEvent_TestBoxUnknown, 'addr=%s uuid=%s os=%s %d cpus' \ % (self._sTestBoxAddr, self._sTestBoxUuid, sOs, cCpus), 24, fCommit = True) return self._resultResponse(constants.tbresp.STATUS_NACK) # # Update the row in TestBoxes if something changed. # if oTestBox.cMbScratch is not None and oTestBox.cMbScratch != 0: cPctScratchDiff = (cMbScratch - oTestBox.cMbScratch) * 100 / oTestBox.cMbScratch else: cPctScratchDiff = 100 # pylint: disable=R0916 if self._sTestBoxAddr != oTestBox.ip \ or sOs != oTestBox.sOs \ or sOsVersion != oTestBox.sOsVersion \ or sCpuVendor != oTestBox.sCpuVendor \ or sCpuArch != oTestBox.sCpuArch \ or sCpuName != oTestBox.sCpuName \ or lCpuRevision != oTestBox.lCpuRevision \ or cCpus != oTestBox.cCpus \ or fCpuHwVirt != oTestBox.fCpuHwVirt \ or fCpuNestedPaging != oTestBox.fCpuNestedPaging \ or fCpu64BitGuest != oTestBox.fCpu64BitGuest \ or fChipsetIoMmu != oTestBox.fChipsetIoMmu \ or fRawMode != oTestBox.fRawMode \ or cMbMemory != oTestBox.cMbMemory \ or abs(cPctScratchDiff) >= min(4 + cMbScratch / 10240, 12) \ or sReport != oTestBox.sReport \ or iTestBoxScriptRev != oTestBox.iTestBoxScriptRev \ or iPythonHexVersion != oTestBox.iPythonHexVersion: oTestBoxLogic.updateOnSignOn(oTestBox.idTestBox, oTestBox.idGenTestBox, sTestBoxAddr=self._sTestBoxAddr, sOs=sOs, sOsVersion=sOsVersion, sCpuVendor=sCpuVendor, sCpuArch=sCpuArch, sCpuName=sCpuName, lCpuRevision=lCpuRevision, cCpus=cCpus, fCpuHwVirt=fCpuHwVirt, fCpuNestedPaging=fCpuNestedPaging, fCpu64BitGuest=fCpu64BitGuest, fChipsetIoMmu=fChipsetIoMmu, fRawMode=fRawMode, cMbMemory=cMbMemory, cMbScratch=cMbScratch, sReport=sReport, iTestBoxScriptRev=iTestBoxScriptRev, iPythonHexVersion=iPythonHexVersion) # # Update the testbox status, making sure there is a status. # oStatusLogic = TestBoxStatusLogic(oDb) oStatusData = oStatusLogic.tryFetchStatus(oTestBox.idTestBox) if oStatusData is not None: self._cleanupOldTest(oDb, oStatusData) else: oStatusLogic.insertIdleStatus(oTestBox.idTestBox, oTestBox.idGenTestBox, fCommit=True) # # ACK the request. # dResponse = \ { constants.tbresp.ALL_PARAM_RESULT: constants.tbresp.STATUS_ACK, constants.tbresp.SIGNON_PARAM_ID: oTestBox.idTestBox, constants.tbresp.SIGNON_PARAM_NAME: oTestBox.sName, } return self._writeResponse(dResponse)
class WuiAdminSystemChangelogList(WuiListContentBase): """ WUI System Changelog Content Generator. """ def __init__(self, aoEntries, iPage, cItemsPerPage, tsEffective, fnDPrint, oDisp, cDaysBack, aiSelectedSortColumns = None): WuiListContentBase.__init__(self, aoEntries, iPage, cItemsPerPage, tsEffective, 'System Changelog', fnDPrint = fnDPrint, oDisp = oDisp, aiSelectedSortColumns = aiSelectedSortColumns); self._asColumnHeaders = [ 'When', 'User', 'Event', 'Details' ]; self._asColumnAttribs = [ 'align="center"', 'align="center"', '', '' ]; self._oBuildBlacklistLogic = BuildBlacklistLogic(oDisp.getDb()); self._oBuildLogic = BuildLogic(oDisp.getDb()); self._oBuildSourceLogic = BuildSourceLogic(oDisp.getDb()); self._oFailureCategoryLogic = FailureCategoryLogic(oDisp.getDb()); self._oFailureReasonLogic = FailureReasonLogic(oDisp.getDb()); self._oGlobalResourceLogic = GlobalResourceLogic(oDisp.getDb()); self._oSchedGroupLogic = SchedGroupLogic(oDisp.getDb()); self._oTestBoxLogic = TestBoxLogic(oDisp.getDb()); self._oTestCaseLogic = TestCaseLogic(oDisp.getDb()); self._oTestGroupLogic = TestGroupLogic(oDisp.getDb()); self._oUserAccountLogic = UserAccountLogic(oDisp.getDb()); self._sPrevDate = ''; _ = cDaysBack; # oDetails = self._createBlacklistingDetailsLink(oEntry.idWhat, oEntry.tsEffective); def _createBlacklistingDetailsLink(self, idBlacklisting, tsEffective): """ Creates a link to the build source details. """ oBlacklisting = self._oBuildBlacklistLogic.cachedLookup(idBlacklisting); if oBlacklisting is not None: from testmanager.webui.wuiadmin import WuiAdmin; return WuiAdminLink('Blacklisting #%u' % (oBlacklisting.idBlacklisting,), WuiAdmin.ksActionBuildBlacklistDetails, tsEffective, { BuildBlacklistData.ksParam_idBlacklisting: oBlacklisting.idBlacklisting }, fBracketed = False); return WuiElementText('[blacklisting #%u not found]' % (idBlacklisting,)); def _createBuildDetailsLink(self, idBuild, tsEffective): """ Creates a link to the build details. """ oBuild = self._oBuildLogic.cachedLookup(idBuild); if oBuild is not None: from testmanager.webui.wuiadmin import WuiAdmin; return WuiAdminLink('%s %sr%u' % ( oBuild.oCat.sProduct, oBuild.sVersion, oBuild.iRevision), WuiAdmin.ksActionBuildDetails, tsEffective, { BuildData.ksParam_idBuild: oBuild.idBuild }, fBracketed = False, sTitle = 'build #%u for %s, type %s' % (oBuild.idBuild, ' & '.join(oBuild.oCat.asOsArches), oBuild.oCat.sType)); return WuiElementText('[build #%u not found]' % (idBuild,)); def _createBuildSourceDetailsLink(self, idBuildSrc, tsEffective): """ Creates a link to the build source details. """ oBuildSource = self._oBuildSourceLogic.cachedLookup(idBuildSrc); if oBuildSource is not None: from testmanager.webui.wuiadmin import WuiAdmin; return WuiAdminLink(oBuildSource.sName, WuiAdmin.ksActionBuildSrcDetails, tsEffective, { BuildSourceData.ksParam_idBuildSrc: oBuildSource.idBuildSrc }, fBracketed = False, sTitle = 'Build source #%u' % (oBuildSource.idBuildSrc,)); return WuiElementText('[build source #%u not found]' % (idBuildSrc,)); def _createFailureCategoryDetailsLink(self, idFailureCategory, tsEffective): """ Creates a link to the failure category details. """ oFailureCategory = self._oFailureCategoryLogic.cachedLookup(idFailureCategory); if oFailureCategory is not None: from testmanager.webui.wuiadmin import WuiAdmin; return WuiAdminLink(oFailureCategory.sShort, WuiAdmin.ksActionFailureCategoryDetails, tsEffective, { FailureCategoryData.ksParam_idFailureCategory: oFailureCategory.idFailureCategory }, fBracketed = False, sTitle = 'Failure category #%u' % (oFailureCategory.idFailureCategory,)); return WuiElementText('[failure category #%u not found]' % (idFailureCategory,)); def _createFailureReasonDetailsLink(self, idFailureReason, tsEffective): """ Creates a link to the failure reason details. """ oFailureReason = self._oFailureReasonLogic.cachedLookup(idFailureReason); if oFailureReason is not None: from testmanager.webui.wuiadmin import WuiAdmin; return WuiAdminLink(oFailureReason.sShort, WuiAdmin.ksActionFailureReasonDetails, tsEffective, { FailureReasonData.ksParam_idFailureReason: oFailureReason.idFailureReason }, fBracketed = False, sTitle = 'Failure reason #%u, category %s' % (oFailureReason.idFailureReason, oFailureReason.oCategory.sShort)); return WuiElementText('[failure reason #%u not found]' % (idFailureReason,)); def _createGlobalResourceDetailsLink(self, idGlobalRsrc, tsEffective): """ Creates a link to the global resource details. """ oGlobalResource = self._oGlobalResourceLogic.cachedLookup(idGlobalRsrc); if oGlobalResource is not None: return WuiAdminLink(oGlobalResource.sName, '@todo', tsEffective, { GlobalResourceData.ksParam_idGlobalRsrc: oGlobalResource.idGlobalRsrc }, fBracketed = False, sTitle = 'Global resource #%u' % (oGlobalResource.idGlobalRsrc,)); return WuiElementText('[global resource #%u not found]' % (idGlobalRsrc,)); def _createSchedGroupDetailsLink(self, idSchedGroup, tsEffective): """ Creates a link to the scheduling group details. """ oSchedGroup = self._oSchedGroupLogic.cachedLookup(idSchedGroup); if oSchedGroup is not None: from testmanager.webui.wuiadmin import WuiAdmin; return WuiAdminLink(oSchedGroup.sName, WuiAdmin.ksActionSchedGroupDetails, tsEffective, { SchedGroupData.ksParam_idSchedGroup: oSchedGroup.idSchedGroup }, fBracketed = False, sTitle = 'Scheduling group #%u' % (oSchedGroup.idSchedGroup,)); return WuiElementText('[scheduling group #%u not found]' % (idSchedGroup,)); def _createTestBoxDetailsLink(self, idTestBox, tsEffective): """ Creates a link to the testbox details. """ oTestBox = self._oTestBoxLogic.cachedLookup(idTestBox); if oTestBox is not None: from testmanager.webui.wuiadmin import WuiAdmin; return WuiAdminLink(oTestBox.sName, WuiAdmin.ksActionTestBoxDetails, tsEffective, { TestBoxData.ksParam_idTestBox: oTestBox.idTestBox }, fBracketed = False, sTitle = 'Testbox #%u' % (oTestBox.idTestBox,)); return WuiElementText('[testbox #%u not found]' % (idTestBox,)); def _createTestCaseDetailsLink(self, idTestCase, tsEffective): """ Creates a link to the test case details. """ oTestCase = self._oTestCaseLogic.cachedLookup(idTestCase); if oTestCase is not None: from testmanager.webui.wuiadmin import WuiAdmin; return WuiAdminLink(oTestCase.sName, WuiAdmin.ksActionTestCaseDetails, tsEffective, { TestCaseData.ksParam_idTestCase: oTestCase.idTestCase }, fBracketed = False, sTitle = 'Test case #%u' % (oTestCase.idTestCase,)); return WuiElementText('[test case #%u not found]' % (idTestCase,)); def _createTestGroupDetailsLink(self, idTestGroup, tsEffective): """ Creates a link to the test group details. """ oTestGroup = self._oTestGroupLogic.cachedLookup(idTestGroup); if oTestGroup is not None: from testmanager.webui.wuiadmin import WuiAdmin; return WuiAdminLink(oTestGroup.sName, WuiAdmin.ksActionTestGroupDetails, tsEffective, { TestGroupData.ksParam_idTestGroup: oTestGroup.idTestGroup }, fBracketed = False, sTitle = 'Test group #%u' % (oTestGroup.idTestGroup,)); return WuiElementText('[test group #%u not found]' % (idTestGroup,)); def _createTestSetResultsDetailsLink(self, idTestSet, tsEffective): """ Creates a link to the test set results. """ _ = tsEffective; from testmanager.webui.wuimain import WuiMain; return WuiMainLink('test set #%u' % idTestSet, WuiMain.ksActionTestSetDetails, { TestSetData.ksParam_idTestSet: idTestSet }, fBracketed = False); def _createTestSetDetailsLinkByResult(self, idTestResult, tsEffective): """ Creates a link to the test set results. """ _ = tsEffective; from testmanager.webui.wuimain import WuiMain; return WuiMainLink('test result #%u' % idTestResult, WuiMain.ksActionTestSetDetailsFromResult, { TestSetData.ksParam_idTestResult: idTestResult }, fBracketed = False); def _createUserAccountDetailsLink(self, uid, tsEffective): """ Creates a link to the user account details. """ oUser = self._oUserAccountLogic.cachedLookup(uid); if oUser is not None: return WuiAdminLink(oUser.sUsername, '@todo', tsEffective, { UserAccountData.ksParam_uid: oUser.uid }, fBracketed = False, sTitle = '%s (#%u)' % (oUser.sFullName, oUser.uid)); return WuiElementText('[user #%u not found]' % (uid,)); def _formatDescGeneric(self, sDesc, oEntry): """ Generically format system log the description. """ oRet = WuiHtmlKeeper(); asWords = sDesc.split(); for sWord in asWords: offEqual = sWord.find('='); if offEqual > 0: sKey = sWord[:offEqual]; try: idValue = int(sWord[offEqual+1:].rstrip('.,')); except: pass; else: if sKey == 'idTestSet': oRet.append(self._createTestSetResultsDetailsLink(idValue, oEntry.tsEffective)); continue; if sKey == 'idTestBox': oRet.append(self._createTestBoxDetailsLink(idValue, oEntry.tsEffective)); continue; if sKey == 'idSchedGroup': oRet.append(self._createSchedGroupDetailsLink(idValue, oEntry.tsEffective)); continue; oRet.append(WuiElementText(sWord)); return oRet; def _formatListEntryHtml(self, iEntry): # pylint: disable=too-many-statements """ Overridden parent method. """ oEntry = self._aoEntries[iEntry]; sRowClass = 'tmodd' if (iEntry + 1) & 1 else 'tmeven'; sHtml = u''; # # Format the timestamp. # sDate = self.formatTsShort(oEntry.tsEffective); if sDate[:10] != self._sPrevDate: self._sPrevDate = sDate[:10]; sHtml += ' <tr class="%s tmdaterow" align="left"><td colspan="7">%s</td></tr>\n' % (sRowClass, sDate[:10],); sDate = sDate[11:] # # System log events. # pylint: disable=redefined-variable-type # aoChanges = None; if oEntry.sEvent == SystemLogData.ksEvent_CmdNacked: sEvent = 'Command not acknowleged'; oDetails = oEntry.sDesc; elif oEntry.sEvent == SystemLogData.ksEvent_TestBoxUnknown: sEvent = 'Unknown testbox'; oDetails = oEntry.sDesc; elif oEntry.sEvent == SystemLogData.ksEvent_TestSetAbandoned: sEvent = 'Abandoned ' if oEntry.sDesc.startswith('idTestSet') else 'Abandoned test set'; oDetails = self._formatDescGeneric(oEntry.sDesc, oEntry); elif oEntry.sEvent == SystemLogData.ksEvent_UserAccountUnknown: sEvent = 'Unknown user account'; oDetails = oEntry.sDesc; elif oEntry.sEvent == SystemLogData.ksEvent_XmlResultMalformed: sEvent = 'Malformed XML result'; oDetails = oEntry.sDesc; elif oEntry.sEvent == SystemLogData.ksEvent_SchedQueueRecreate: sEvent = 'Recreating scheduling queue'; asWords = oEntry.sDesc.split(); if len(asWords) > 3 and asWords[0] == 'User' and asWords[1][0] == '#': try: idAuthor = int(asWords[1][1:]); except: pass; else: oEntry.oAuthor = self._oUserAccountLogic.cachedLookup(idAuthor); if oEntry.oAuthor is not None: i = 2; if asWords[i] == 'recreated': i += 1; oEntry.sDesc = ' '.join(asWords[i:]); oDetails = self._formatDescGeneric(oEntry.sDesc.replace('sched queue #', 'for scheduling group idSchedGroup='), oEntry); # # System changelog events. # elif oEntry.sEvent == SystemChangelogLogic.ksWhat_Blacklisting: sEvent = 'Modified blacklisting'; oDetails = self._createBlacklistingDetailsLink(oEntry.idWhat, oEntry.tsEffective); elif oEntry.sEvent == SystemChangelogLogic.ksWhat_Build: sEvent = 'Modified build'; oDetails = self._createBuildDetailsLink(oEntry.idWhat, oEntry.tsEffective); elif oEntry.sEvent == SystemChangelogLogic.ksWhat_BuildSource: sEvent = 'Modified build source'; oDetails = self._createBuildSourceDetailsLink(oEntry.idWhat, oEntry.tsEffective); elif oEntry.sEvent == SystemChangelogLogic.ksWhat_GlobalRsrc: sEvent = 'Modified global resource'; oDetails = self._createGlobalResourceDetailsLink(oEntry.idWhat, oEntry.tsEffective); elif oEntry.sEvent == SystemChangelogLogic.ksWhat_FailureCategory: sEvent = 'Modified failure category'; oDetails = self._createFailureCategoryDetailsLink(oEntry.idWhat, oEntry.tsEffective); (aoChanges, _) = self._oFailureCategoryLogic.fetchForChangeLog(oEntry.idWhat, 0, 1, oEntry.tsEffective); elif oEntry.sEvent == SystemChangelogLogic.ksWhat_FailureReason: sEvent = 'Modified failure reason'; oDetails = self._createFailureReasonDetailsLink(oEntry.idWhat, oEntry.tsEffective); (aoChanges, _) = self._oFailureReasonLogic.fetchForChangeLog(oEntry.idWhat, 0, 1, oEntry.tsEffective); elif oEntry.sEvent == SystemChangelogLogic.ksWhat_SchedGroup: sEvent = 'Modified scheduling group'; oDetails = self._createSchedGroupDetailsLink(oEntry.idWhat, oEntry.tsEffective); elif oEntry.sEvent == SystemChangelogLogic.ksWhat_TestBox: sEvent = 'Modified testbox'; oDetails = self._createTestBoxDetailsLink(oEntry.idWhat, oEntry.tsEffective); (aoChanges, _) = self._oTestBoxLogic.fetchForChangeLog(oEntry.idWhat, 0, 1, oEntry.tsEffective); elif oEntry.sEvent == SystemChangelogLogic.ksWhat_TestCase: sEvent = 'Modified test case'; oDetails = self._createTestCaseDetailsLink(oEntry.idWhat, oEntry.tsEffective); (aoChanges, _) = self._oTestCaseLogic.fetchForChangeLog(oEntry.idWhat, 0, 1, oEntry.tsEffective); elif oEntry.sEvent == SystemChangelogLogic.ksWhat_TestGroup: sEvent = 'Modified test group'; oDetails = self._createTestGroupDetailsLink(oEntry.idWhat, oEntry.tsEffective); elif oEntry.sEvent == SystemChangelogLogic.ksWhat_TestResult: sEvent = 'Modified test failure reason'; oDetails = self._createTestSetDetailsLinkByResult(oEntry.idWhat, oEntry.tsEffective); elif oEntry.sEvent == SystemChangelogLogic.ksWhat_User: sEvent = 'Modified user account'; oDetails = self._createUserAccountDetailsLink(oEntry.idWhat, oEntry.tsEffective); else: sEvent = '%s(%s)' % (oEntry.sEvent, oEntry.idWhat,); oDetails = '!Unknown event!' + (oEntry.sDesc if oEntry.sDesc else ''); # # Do the formatting. # if aoChanges: oChangeEntry = aoChanges[0]; cAttribsChanged = len(oChangeEntry.aoChanges) + 1; if oChangeEntry.oOldRaw is None and sEvent.startswith('Modified '): sEvent = 'Created ' + sEvent[9:]; else: oChangeEntry = None; cAttribsChanged = -1; sHtml += u' <tr class="%s">\n' \ u' <td rowspan="%d" align="center" >%s</td>\n' \ u' <td rowspan="%d" align="center" >%s</td>\n' \ u' <td colspan="5" class="%s%s">%s %s</td>\n' \ u' </tr>\n' \ % ( sRowClass, 1 + cAttribsChanged + 1, sDate, 1 + cAttribsChanged + 1, webutils.escapeElem(oEntry.oAuthor.sUsername if oEntry.oAuthor is not None else ''), sRowClass, ' tmsyschlogevent' if oChangeEntry is not None else '', webutils.escapeElem(sEvent), oDetails.toHtml() if isinstance(oDetails, WuiHtmlBase) else oDetails, ); if oChangeEntry is not None: sHtml += u' <tr class="%s tmsyschlogspacerrowabove">\n' \ u' <td xrowspan="%d" style="border-right: 0px; border-bottom: 0px;"></td>\n' \ u' <td colspan="3" style="border-right: 0px;"></td>\n' \ u' <td rowspan="%d" class="%s tmsyschlogspacer"></td>\n' \ u' </tr>\n' \ % (sRowClass, cAttribsChanged + 1, cAttribsChanged + 1, sRowClass); for j, oChange in enumerate(oChangeEntry.aoChanges): fLastRow = j + 1 == len(oChangeEntry.aoChanges); sHtml += u' <tr class="%s%s tmsyschlogattr%s">\n' \ % ( sRowClass, 'odd' if j & 1 else 'even', ' tmsyschlogattrfinal' if fLastRow else '',); if j == 0: sHtml += u' <td class="%s tmsyschlogspacer" rowspan="%d"></td>\n' % (sRowClass, cAttribsChanged - 1,); if isinstance(oChange, AttributeChangeEntryPre): sHtml += u' <td class="%s%s">%s</td>\n' \ u' <td><div class="tdpre"><pre>%s</pre></div></td>\n' \ u' <td class="%s%s"><div class="tdpre"><pre>%s</pre></div></td>\n' \ % ( ' tmtopleft' if j == 0 else '', ' tmbottomleft' if fLastRow else '', webutils.escapeElem(oChange.sAttr), webutils.escapeElem(oChange.sOldText), ' tmtopright' if j == 0 else '', ' tmbottomright' if fLastRow else '', webutils.escapeElem(oChange.sNewText), ); else: sHtml += u' <td class="%s%s">%s</td>\n' \ u' <td>%s</td>\n' \ u' <td class="%s%s">%s</td>\n' \ % ( ' tmtopleft' if j == 0 else '', ' tmbottomleft' if fLastRow else '', webutils.escapeElem(oChange.sAttr), webutils.escapeElem(oChange.sOldText), ' tmtopright' if j == 0 else '', ' tmbottomright' if fLastRow else '', webutils.escapeElem(oChange.sNewText), ); sHtml += u' </tr>\n'; if oChangeEntry is not None: sHtml += u' <tr class="%s tmsyschlogspacerrowbelow "><td colspan="5"></td></tr>\n\n' % (sRowClass,); return sHtml; def _generateTableHeaders(self): """ Overridden parent method. """ sHtml = u'<thead class="tmheader">\n' \ u' <tr>\n' \ u' <th rowspan="2">When</th>\n' \ u' <th rowspan="2">Who</th>\n' \ u' <th colspan="5">Event</th>\n' \ u' </tr>\n' \ u' <tr>\n' \ u' <th style="border-right: 0px;"></th>\n' \ u' <th>Attribute</th>\n' \ u' <th>Old</th>\n' \ u' <th style="border-right: 0px;">New</th>\n' \ u' <th></th>\n' \ u' </tr>\n' \ u'</thead>\n'; return sHtml;
def _actionSignOn(self): # pylint: disable=R0914 """ Implement sign-on """ # # Validate parameters (raises exception on failure). # sOs = self._getStringParam(constants.tbreq.SIGNON_PARAM_OS, coreconsts.g_kasOses); sOsVersion = self._getStringParam(constants.tbreq.SIGNON_PARAM_OS_VERSION); sCpuVendor = self._getStringParam(constants.tbreq.SIGNON_PARAM_CPU_VENDOR); sCpuArch = self._getStringParam(constants.tbreq.SIGNON_PARAM_CPU_ARCH, coreconsts.g_kasCpuArches); sCpuName = self._getStringParam(constants.tbreq.SIGNON_PARAM_CPU_NAME, fStrip = True, sDefValue = ''); # new lCpuRevision = self._getLongParam( constants.tbreq.SIGNON_PARAM_CPU_REVISION, lMin = 0, lDefValue = 0); # new cCpus = self._getIntParam( constants.tbreq.SIGNON_PARAM_CPU_COUNT, 1, 16384); fCpuHwVirt = self._getBoolParam( constants.tbreq.SIGNON_PARAM_HAS_HW_VIRT); fCpuNestedPaging = self._getBoolParam( constants.tbreq.SIGNON_PARAM_HAS_NESTED_PAGING); fCpu64BitGuest = self._getBoolParam( constants.tbreq.SIGNON_PARAM_HAS_64_BIT_GUEST, fDefValue = True); fChipsetIoMmu = self._getBoolParam( constants.tbreq.SIGNON_PARAM_HAS_IOMMU); cMbMemory = self._getLongParam( constants.tbreq.SIGNON_PARAM_MEM_SIZE, 8, 1073741823); # 8MB..1PB cMbScratch = self._getLongParam( constants.tbreq.SIGNON_PARAM_SCRATCH_SIZE, 0, 1073741823); # 0..1PB sReport = self._getStringParam(constants.tbreq.SIGNON_PARAM_REPORT, fStrip = True, sDefValue = ''); # new iTestBoxScriptRev = self._getIntParam( constants.tbreq.SIGNON_PARAM_SCRIPT_REV, 1, 100000000); iPythonHexVersion = self._getIntParam( constants.tbreq.SIGNON_PARAM_PYTHON_VERSION, 0x020300f0, 0x030f00f0); self._checkForUnknownParameters(); # Null conversions for new parameters. if len(sReport) == 0: sReport = None; if len(sCpuName) == 0: sCpuName = None; if lCpuRevision <= 0: lCpuRevision = None; # # Connect to the database and validate the testbox. # oDb = TMDatabaseConnection(self._oSrvGlue.dprint); oTestBoxLogic = TestBoxLogic(oDb); oTestBox = oTestBoxLogic.tryFetchTestBoxByUuid(self._sTestBoxUuid); if oTestBox is None: oSystemLogLogic = SystemLogLogic(oDb); oSystemLogLogic.addEntry(SystemLogData.ksEvent_TestBoxUnknown, 'addr=%s uuid=%s os=%s %d cpus' \ % (self._sTestBoxAddr, self._sTestBoxUuid, sOs, cCpus), 24, fCommit = True); return self._resultResponse(constants.tbresp.STATUS_NACK); # # Update the row in TestBoxes if something changed. # if self._sTestBoxAddr != oTestBox.ip \ or sOs != oTestBox.sOs \ or sOsVersion != oTestBox.sOsVersion \ or sCpuVendor != oTestBox.sCpuVendor \ or sCpuArch != oTestBox.sCpuArch \ or sCpuName != oTestBox.sCpuName \ or lCpuRevision != oTestBox.lCpuRevision \ or cCpus != oTestBox.cCpus \ or fCpuHwVirt != oTestBox.fCpuHwVirt \ or fCpuNestedPaging != oTestBox.fCpuNestedPaging \ or fCpu64BitGuest != oTestBox.fCpu64BitGuest \ or fChipsetIoMmu != oTestBox.fChipsetIoMmu \ or cMbMemory != oTestBox.cMbMemory \ or cMbScratch != oTestBox.cMbScratch \ or sReport != oTestBox.sReport \ or iTestBoxScriptRev != oTestBox.iTestBoxScriptRev \ or iPythonHexVersion != oTestBox.iPythonHexVersion: oTestBoxLogic.updateOnSignOn(oTestBox.idTestBox, oTestBox.idGenTestBox, sTestBoxAddr = self._sTestBoxAddr, sOs = sOs, sOsVersion = sOsVersion, sCpuVendor = sCpuVendor, sCpuArch = sCpuArch, sCpuName = sCpuName, lCpuRevision = lCpuRevision, cCpus = cCpus, fCpuHwVirt = fCpuHwVirt, fCpuNestedPaging = fCpuNestedPaging, fCpu64BitGuest = fCpu64BitGuest, fChipsetIoMmu = fChipsetIoMmu, cMbMemory = cMbMemory, cMbScratch = cMbScratch, sReport = sReport, iTestBoxScriptRev = iTestBoxScriptRev, iPythonHexVersion = iPythonHexVersion); # # Update the testbox status, making sure there is a status. # oStatusLogic = TestBoxStatusLogic(oDb); oStatusData = oStatusLogic.tryFetchStatus(oTestBox.idTestBox); if oStatusData is not None: self._cleanupOldTest(oDb, oStatusData); else: oStatusLogic.insertIdleStatus(oTestBox.idTestBox, oTestBox.idGenTestBox, fCommit = True); # # ACK the request. # dResponse = \ { constants.tbresp.ALL_PARAM_RESULT: constants.tbresp.STATUS_ACK, constants.tbresp.SIGNON_PARAM_ID: oTestBox.idTestBox, constants.tbresp.SIGNON_PARAM_NAME: oTestBox.sName, } return self._writeResponse(dResponse);