def _cleanupOldTest(self, oDb, oStatusData):
        """
        Cleans up any old test set that may be left behind and changes the
        state to 'idle'.  See scenario #9:
        file://../../docs/AutomaticTestingRevamp.html#cleaning-up-abandoned-testcase

        Note. oStatusData.enmState is set to idle, but tsUpdated is not changed.
        """

        # Cleanup any abandoned test.
        if oStatusData.idTestSet is not None:
            SystemLogLogic(oDb).addEntry(
                SystemLogData.ksEvent_TestSetAbandoned,
                "idTestSet=%u idTestBox=%u enmState=%s %s" %
                (oStatusData.idTestSet, oStatusData.idTestBox,
                 oStatusData.enmState, self._sAction),
                fCommit=False)
            TestSetLogic(oDb).completeAsAbandoned(oStatusData.idTestSet,
                                                  fCommit=False)
            GlobalResourceLogic(oDb).freeGlobalResourcesByTestBox(
                self._idTestBox, fCommit=False)

        # Change to idle status
        if oStatusData.enmState != TestBoxStatusData.ksTestBoxState_Idle:
            TestBoxStatusLogic(oDb).updateState(
                self._idTestBox,
                TestBoxStatusData.ksTestBoxState_Idle,
                fCommit=False)
            oStatusData.tsUpdated = oDb.getCurrentTimestamp()
            oStatusData.enmState = TestBoxStatusData.ksTestBoxState_Idle

        # Commit.
        oDb.commit()

        return True
Пример #2
0
    def main(self):
        """ Main method. """
        oDb = TMDatabaseConnection()

        # Get a list of orphans.
        oLogic = TestSetLogic(oDb)
        aoOrphans = oLogic.fetchOrphaned()
        if len(aoOrphans) > 0:
            # Complete them.
            if self.oConfig.fJustDoIt:
                print 'Completing %u test sets as abandoned:' % (
                    len(aoOrphans), )
                for oTestSet in aoOrphans:
                    print '#%-7u: idTestBox=%-3u tsCreated=%s tsDone=%s' \
                        % (oTestSet.idTestSet, oTestSet.idTestBox, oTestSet.tsCreated, oTestSet.tsDone)
                    oLogic.completeAsAbandoned(oTestSet.idTestSet)
                print 'Committing...'
                oDb.commit()
            else:
                for oTestSet in aoOrphans:
                    print '#%-7u: idTestBox=%-3u tsCreated=%s tsDone=%s' \
                        % (oTestSet.idTestSet, oTestSet.idTestBox, oTestSet.tsCreated, oTestSet.tsDone)
                print 'Not completing any testsets without seeing the --just-do-it option.'
        else:
            print 'No orphaned test sets.\n'
        return 0
    def _actionExecCompleted(self):
        """
        Implement EXEC completion.

        Because the action is request by the worker thread of the testbox
        script we cannot pass pending commands back to it like originally
        planned.  So, we just complete the test set and update the status.
        """
        #
        # Parameter validation.
        #
        sStatus = self._getStringParam(
            constants.tbreq.EXEC_COMPLETED_PARAM_RESULT,
            TestBoxController.kasValidResults)
        self._checkForUnknownParameters()

        (oDb, oStatusData, _) = self._connectToDbAndValidateTb([
            TestBoxStatusData.ksTestBoxState_Testing,
            TestBoxStatusData.ksTestBoxState_GangTesting
        ])
        if oStatusData is None:
            return False

        #
        # Complete the status.
        #
        oDb.rollback()
        oDb.begin()
        oTestSetLogic = TestSetLogic(oDb)
        idTestSetGangLeader = oTestSetLogic.complete(
            oStatusData.idTestSet,
            self.kadTbResultToStatus[sStatus],
            fCommit=False)

        oStatusLogic = TestBoxStatusLogic(oDb)
        if oStatusData.enmState == TestBoxStatusData.ksTestBoxState_Testing:
            assert idTestSetGangLeader is None
            GlobalResourceLogic(oDb).freeGlobalResourcesByTestBox(
                self._idTestBox)
            oStatusLogic.updateState(self._idTestBox,
                                     TestBoxStatusData.ksTestBoxState_Idle,
                                     fCommit=False)
        else:
            assert idTestSetGangLeader is not None
            oStatusLogic.updateState(
                self._idTestBox,
                TestBoxStatusData.ksTestBoxState_GangCleanup,
                oStatusData.idTestSet,
                fCommit=False)
            if oStatusLogic.isWholeGangDoneTesting(idTestSetGangLeader):
                GlobalResourceLogic(oDb).freeGlobalResourcesByTestBox(
                    self._idTestBox)
                oStatusLogic.updateState(self._idTestBox,
                                         TestBoxStatusData.ksTestBoxState_Idle,
                                         fCommit=False)

        oDb.commit()
        return self._resultResponse(constants.tbresp.STATUS_ACK)
Пример #4
0
 def __init__(self, oOptions):
     """
     Parse command line
     """
     self.fVerbose = oOptions.fVerbose
     self.sSrcDir = config.g_ksFileAreaRootDir
     self.sDstDir = config.g_ksZipFileAreaRootDir
     #self.oTestSetLogic = TestSetLogic(TMDatabaseConnection(self.dprint if self.fVerbose else None));
     self.oTestSetLogic = TestSetLogic(TMDatabaseConnection(None))
     self.fDryRun = oOptions.fDryRun
Пример #5
0
    def _doGangGatheringTimedOut(self, oDb, oStatusData):
        """
        _doRequestCommand worker for handling a box in gang-gathering-timed-out state.
        This will do clean-ups similar to _cleanupOldTest and update the state likewise.
        """
        oDb.begin();

        TestSetLogic(oDb).completeAsGangGatheringTimeout(oStatusData.idTestSet, fCommit = False);
        GlobalResourceLogic(oDb).freeGlobalResourcesByTestBox(self._idTestBox, fCommit = False);
        TestBoxStatusLogic(oDb).updateState(self._idTestBox, TestBoxStatusData.ksTestBoxState_Idle, fCommit = False);

        oStatusData.tsUpdated = oDb.getCurrentTimestamp();
        oStatusData.enmState  = TestBoxStatusData.ksTestBoxState_Idle;

        oDb.commit();
        return None;
    def _actionUpload(self):
        """ Implement uploading of files. """
        #
        # Parameter validation.
        #
        sName = self._getStringParam(constants.tbreq.UPLOAD_PARAM_NAME)
        sMime = self._getStringParam(constants.tbreq.UPLOAD_PARAM_MIME)
        sKind = self._getStringParam(constants.tbreq.UPLOAD_PARAM_KIND)
        sDesc = self._getStringParam(constants.tbreq.UPLOAD_PARAM_DESC)
        self._checkForUnknownParameters()

        (oDb, oStatusData, _) = self._connectToDbAndValidateTb([
            TestBoxStatusData.ksTestBoxState_Testing,
            TestBoxStatusData.ksTestBoxState_GangTesting
        ])
        if oStatusData is None:
            return False

        if len(sName) > 128 or len(sName) < 3:
            raise TestBoxControllerException('Invalid file name "%s"' %
                                             (sName, ))
        if re.match(r'^[a-zA-Z0-9_\-(){}#@+,.=]*$', sName) is None:
            raise TestBoxControllerException('Invalid file name "%s"' %
                                             (sName, ))

        if sMime not in [
                'text/plain',  #'text/html', 'text/xml',
                'application/octet-stream',
                'image/png',  #'image/gif', 'image/jpeg',
                #'video/webm', 'video/mpeg', 'video/mpeg4-generic',
        ]:
            raise TestBoxControllerException('Invalid MIME type "%s"' %
                                             (sMime, ))

        if sKind not in TestResultFileData.kasKinds:
            raise TestBoxControllerException('Invalid kind "%s"' % (sKind, ))

        if len(sDesc) > 256:
            raise TestBoxControllerException('Invalid description "%s"' %
                                             (sDesc, ))
        if not set(sDesc).issubset(set(string.printable)):
            raise TestBoxControllerException('Invalid description "%s"' %
                                             (sDesc, ))

        if ('application/octet-stream', {}) != self._oSrvGlue.getContentType():
            raise TestBoxControllerException(
                'Unexpected content type: %s; %s' %
                self._oSrvGlue.getContentType())

        cbFile = self._oSrvGlue.getContentLength()
        if cbFile <= 0:
            raise TestBoxControllerException(
                'File "%s" is empty or negative in size (%s)' %
                (sName, cbFile))
        if (cbFile + 1048575) / 1048576 > config.g_kcMbMaxUploadSingle:
            raise TestBoxControllerException(
                'File "%s" is too big %u bytes (max %u MiB)' % (
                    sName,
                    cbFile,
                    config.g_kcMbMaxUploadSingle,
                ))

        #
        # Write the text to the log file.
        #
        oTestSet = TestSetData().initFromDbWithId(oDb, oStatusData.idTestSet)
        oDstFile = TestSetLogic(oDb).createFile(oTestSet,
                                                sName=sName,
                                                sMime=sMime,
                                                sKind=sKind,
                                                sDesc=sDesc,
                                                cbFile=cbFile,
                                                fCommit=True)

        offFile = 0
        oSrcFile = self._oSrvGlue.getBodyIoStream()
        while offFile < cbFile:
            cbToRead = cbFile - offFile
            if cbToRead > 256 * 1024:
                cbToRead = 256 * 1024
            offFile += cbToRead

            abBuf = oSrcFile.read(cbToRead)
            oDstFile.write(abBuf)
            # pylint: disable=E1103
            del abBuf

        oDstFile.close()
        # pylint: disable=E1103

        # Done.
        return self._resultResponse(constants.tbresp.STATUS_ACK)
    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()