Beispiel #1
0
    def xmlFlush(self, fRetry=False, fForce=False):
        """
        Flushes the XML back log. Called with the lock held, may leave it
        while communicating with the server.
        """
        if not self._fXmlFlushing:
            asXml = self._asXml
            self._asXml = []
            if len(asXml) > 0 or fForce is True:
                self._fXmlFlushing = True

                g_oLock.release()
                (asXml, fIncErrors) = self._xmlDoFlush(asXml, fRetry=fRetry)
                g_oLock.acquire()

                if fIncErrors:
                    self.testIncErrors()

                self._fXmlFlushing = False
                if asXml is None:
                    self._secTsXmlFlush = utils.timestampSecond()
                else:
                    self._asXml = asXml + self._asXml
                return True

            self._secTsXmlFlush = utils.timestampSecond()
        return False
Beispiel #2
0
    def _waitForTestManagerConnectivity(self, cSecTimeout):
        """
        Check and wait for network connectivity to the test manager.

        This is used with the windows installation and uninstallation since
        these usually disrupts network connectivity when installing the filter
        driver.  If we proceed to quickly, we might finish the test at a time
        when we cannot report to the test manager and thus end up with an
        abandonded test error.
        """
        cSecElapsed = 0
        secStart = utils.timestampSecond()
        while reporter.checkTestManagerConnection() is False:
            cSecElapsed = utils.timestampSecond() - secStart
            if cSecElapsed >= cSecTimeout:
                reporter.log(
                    '_waitForTestManagerConnectivity: Giving up after %u secs.'
                    % (cSecTimeout, ))
                return False
            time.sleep(2)

        if cSecElapsed > 0:
            reporter.log('_waitForTestManagerConnectivity: Waited %s secs.' %
                         (cSecTimeout, ))
        return True
Beispiel #3
0
    def xmlFlush(self, fRetry = False, fForce = False):
        """
        Flushes the XML back log. Called with the lock held, may leave it
        while communicating with the server.
        """
        if not self._fXmlFlushing:
            asXml = self._asXml;
            self._asXml = [];
            if len(asXml) > 0  or  fForce is True:
                self._fXmlFlushing = True;

                g_oLock.release();
                (asXml, fIncErrors) = self._xmlDoFlush(asXml, fRetry = fRetry);
                g_oLock.acquire();

                if fIncErrors:
                    self.testIncErrors();

                self._fXmlFlushing = False;
                if asXml is None:
                    self._secTsXmlFlush = utils.timestampSecond();
                else:
                    self._asXml = asXml + self._asXml;
                return True;

            self._secTsXmlFlush = utils.timestampSecond();
        return False;
Beispiel #4
0
    def _doUploadFile(self, oSrcFile, sSrcFilename, sDescription, sKind,
                      sMime):
        """ Uploads the given file to the test manager. """

        # Prepare header and url.
        dHeader = dict(self._dHttpHeader)
        dHeader['Content-Type'] = 'application/octet-stream'
        self._writeOutput('%s: _doUploadFile: sHeader=%s' % (
            utils.getTimePrefix(),
            dHeader,
        ))
        oSrcFile.seek(0, 2)
        self._writeOutput('%s: _doUploadFile: size=%d' % (
            utils.getTimePrefix(),
            oSrcFile.tell(),
        ))
        oSrcFile.seek(0)

        from common import constants
        sUrl = self._sTmServerPath + '&' \
             + self._fnUrlEncode({ constants.tbreq.UPLOAD_PARAM_NAME: os.path.basename(sSrcFilename),
                                   constants.tbreq.UPLOAD_PARAM_DESC: sDescription,
                                   constants.tbreq.UPLOAD_PARAM_KIND: sKind,
                                   constants.tbreq.UPLOAD_PARAM_MIME: sMime,
                                   constants.tbreq.ALL_PARAM_ACTION:  constants.tbreq.UPLOAD,
                                })

        # Retry loop.
        secStart = utils.timestampSecond()
        while True:
            try:
                oConn = self._fnTmConnect()
                oConn.request('POST', sUrl, oSrcFile.read(), dHeader)
                fRc = self._processTmStatusResponse(oConn,
                                                    '_doUploadFile',
                                                    fClose=True)
                oConn.close()
                if fRc is not None:
                    return fRc
            except:
                logXcpt('warning: exception during UPLOAD request')

            if utils.timestampSecond(
            ) - secStart >= self.kcSecTestManagerRetryTimeout:
                self._writeOutput('%s: _doUploadFile: Timed out.' %
                                  (utils.getTimePrefix(), ))
                break
            try:
                oSrcFile.seek(0)
            except:
                logXcpt()
                break
            self._writeOutput('%s: _doUploadFile: Retrying...' %
                              (utils.getTimePrefix(), ))
            time.sleep(2)

        return False
Beispiel #5
0
    def _reportDone(self, sResult):
        """
        Report EXEC job done to the test manager.

        sResult is a value from constants.result.
        """
        ## @todo optimize this to use one server connection.

        #
        # Log it.
        #
        assert sResult in constants.result.g_kasValidResults
        self._log('Done %s' % (sResult, ))

        #
        # Report it.
        #
        fRc = True
        secStart = utils.timestampSecond()
        while True:
            self._logFlush()
            ## @todo Combine this with EXEC_COMPLETED.
            oConnection = None
            try:
                oConnection = self._oTestBoxScript.openTestManagerConnection()
                oConnection.postRequest(
                    constants.tbreq.EXEC_COMPLETED,
                    {constants.tbreq.EXEC_COMPLETED_PARAM_RESULT: sResult})
                oConnection.close()
            except Exception as oXcpt:
                if utils.timestampSecond(
                ) - secStart < self.ksecTestManagerTimeout:
                    self._log('_reportDone exception (%s) - retrying...' %
                              (oXcpt, ))
                    time.sleep(2)
                    continue
                self._log('_reportDone error: %s' % (oXcpt, ))
                if oConnection is not None:  # Be kind to apache.
                    try:
                        oConnection.close()
                    except:
                        pass
                fRc = False
            break

        #
        # Mark the task as completed.
        #
        self._complete()
        return fRc
Beispiel #6
0
    def _logInternal(self, sMessage, fPrefix = True, fFlushCheck = False):
        """
        Internal logging.
        Won't flush the backlog, returns a flush indicator so the caller can
        do it instead.
        """
        if fPrefix:
            try:
                oNow = datetime.utcnow();
                sTs = '%02u:%02u:%02u.%06u ' % (oNow.hour, oNow.minute, oNow.second, oNow.microsecond);
            except Exception as oXcpt:
                sTs = 'oXcpt=%s ' % (oXcpt);
            sFullMsg = sTs + sMessage;
        else:
            sFullMsg = sMessage;

        self._oBackLogLock.acquire();
        self._asBackLog.append(sFullMsg);
        cchBackLog = self._cchBackLog + len(sFullMsg) + 1;
        self._cchBackLog = cchBackLog;
        secTsBackLogFlush = self._secTsBackLogFlush;
        self._oBackLogLock.release();

        testboxcommons.log(sFullMsg);
        return fFlushCheck \
            and (   cchBackLog >= self.kcchMaxBackLog \
                 or utils.timestampSecond() - secTsBackLogFlush >= self.kcSecBackLogFlush);
Beispiel #7
0
    def __init__(self):
        ReporterBase.__init__(self)
        self.sTestManagerUrl = os.environ.get('TESTBOX_MANAGER_URL')
        self.sTestBoxUuid = os.environ.get('TESTBOX_UUID')
        self.idTestBox = int(os.environ.get('TESTBOX_ID'))
        self.idTestSet = int(os.environ.get('TESTBOX_TEST_SET_ID'))
        self._asXml = []
        self._secTsXmlFlush = utils.timestampSecond()
        self._secTsXmlLast = self._secTsXmlFlush
        self._fXmlFlushing = False
        self.oOutput = sys.stdout
        # Hack for __del__ output.
        self.fFlushEachLine = True
        self.fDebugXml = 'TESTDRIVER_REPORTER_DEBUG_XML' in os.environ

        # Prepare the TM connecting.
        import urlparse
        import httplib
        import urllib
        from common import constants

        self._fnUrlEncode = urllib.urlencode
        self._fnUrlParseQs = urlparse.parse_qs
        self._oParsedTmUrl = urlparse.urlparse(self.sTestManagerUrl)

        if     sys.version_info[0] >= 3 \
           or (sys.version_info[0] == 2 and sys.version_info[1] >= 6):
            if self._oParsedTmUrl.scheme == 'https':  # pylint: disable=E1101
                self._fnTmConnect = lambda: httplib.HTTPSConnection(
                    self._oParsedTmUrl.hostname,
                    timeout=self.kcSecTestManagerRequestTimeout)
            else:
                self._fnTmConnect = lambda: httplib.HTTPConnection(
                    self._oParsedTmUrl.hostname,
                    timeout=self.kcSecTestManagerRequestTimeout)
        else:
            if self._oParsedTmUrl.scheme == 'https':  # pylint: disable=E1101
                self._fnTmConnect = lambda: httplib.HTTPSConnection(
                    self._oParsedTmUrl.hostname)
            else:
                self._fnTmConnect = lambda: httplib.HTTPConnection(
                    self._oParsedTmUrl.hostname)
        self._dHttpHeader = \
        {
            'Content-Type':     'application/x-www-form-urlencoded; charset=utf-8',
            'User-Agent':       'TestDriverReporter/%s.0 (%s, %s)' % (__version__, utils.getHostOs(), utils.getHostArch(),),
            'Accept':           'text/plain,application/x-www-form-urlencoded',
            'Accept-Encoding':  'identity',
            'Cache-Control':    'max-age=0',
            #'Connection':       'keep-alive',
        }

        dParams = {
            constants.tbreq.ALL_PARAM_TESTBOX_UUID: self.sTestBoxUuid,
            constants.tbreq.ALL_PARAM_TESTBOX_ID: self.idTestBox,
            constants.tbreq.RESULT_PARAM_TEST_SET_ID: self.idTestSet,
        }
        self._sTmServerPath = '/%s/testboxdisp.py?%s' \
                            % ( self._oParsedTmUrl.path.strip('/'), # pylint: disable=E1101
                                urllib.urlencode(dParams), )
Beispiel #8
0
    def _xmlDoFlush(self, asXml, fRetry=False, fDtor=False):
        """
        The code that does the actual talking to the server.
        Used by both xmlFlush and __del__.
        """
        secStart = utils.timestampSecond()
        while True:
            fRc = None
            try:
                # Post.
                from common import constants
                sPostBody = self._fnUrlEncode({
                    constants.tbreq.XML_RESULT_PARAM_BODY:
                    '\n'.join(asXml),
                })
                oConn = self._fnTmConnect()
                oConn.request(
                    'POST', self._sTmServerPath +
                    ('&%s=%s' % (constants.tbreq.ALL_PARAM_ACTION,
                                 constants.tbreq.XML_RESULTS)), sPostBody,
                    self._dHttpHeader)

                fRc = self._processTmStatusResponse(oConn,
                                                    '_xmlDoFlush',
                                                    fClose=True)
                if fRc is True:
                    if self.fDebugXml:
                        self._writeOutput('_xmlDoFlush:\n%s' %
                                          ('\n'.join(asXml), ))
                    return (None, False)
                if fRc is False:
                    self._writeOutput(
                        '_xmlDoFlush: Failed - we should abort the test, really.'
                    )
                    return (None, True)
            except Exception, oXcpt:
                if not fDtor:
                    logXcpt('warning: exception during XML_RESULTS request')
                else:
                    self._writeOutput(
                        'warning: exception during XML_RESULTS request: %s' %
                        (oXcpt, ))

            if   fRetry is not True \
              or utils.timestampSecond() - secStart >= self.kcSecTestManagerRetryTimeout:
                break
            time.sleep(2)
Beispiel #9
0
    def _assembleArguments(self, sAction, fWithInterpreter=True):
        """
        Creates an argument array for subprocess.Popen, splitting the
        sScriptCmdLine like bourne shell would.
        fWithInterpreter is used (False) when checking that the script exists.

        Returns None on bad input.
        """

        #
        # This is a good place to export the test set id to the environment.
        #
        os.environ['TESTBOX_TEST_SET_ID'] = str(self._idResult)
        cTimeoutLeft = utils.timestampSecond() - self._tsSecStarted
        cTimeoutLeft = 0 if cTimeoutLeft >= self._cSecTimeout else self._cSecTimeout - cTimeoutLeft
        os.environ['TESTBOX_TIMEOUT'] = str(cTimeoutLeft)
        os.environ['TESTBOX_TIMEOUT_ABS'] = str(self._tsSecStarted +
                                                self._cSecTimeout)

        #
        # Do replacements and split the command line into arguments.
        #
        if self._sScriptCmdLine.find('@ACTION@') >= 0:
            sCmdLine = self._sScriptCmdLine.replace('@ACTION@', sAction)
        else:
            sCmdLine = self._sScriptCmdLine + ' ' + sAction
        for sVar in [
                'TESTBOX_PATH_BUILDS', 'TESTBOX_PATH_RESOURCES',
                'TESTBOX_PATH_SCRATCH', 'TESTBOX_PATH_SCRIPTS',
                'TESTBOX_PATH_UPLOAD', 'TESTBOX_UUID', 'TESTBOX_REPORTER',
                'TESTBOX_ID', 'TESTBOX_TEST_SET_ID', 'TESTBOX_TIMEOUT',
                'TESTBOX_TIMEOUT_ABS'
        ]:
            if sCmdLine.find('${' + sVar + '}') >= 0:
                sCmdLine = sCmdLine.replace('${' + sVar + '}',
                                            os.environ[sVar])

        asArgs = utils.argsSplit(sCmdLine)

        #
        # Massage argv[0]:
        #   - Convert portable slashes ('/') to the flavor preferred by the
        #     OS we're currently running on.
        #   - Run python script thru the current python interpreter (important
        #     on systems that doesn't sport native hash-bang script execution).
        #
        asArgs[0] = asArgs[0].replace('/', os.path.sep)
        if not os.path.isabs(asArgs[0]):
            asArgs[0] = os.path.join(self._oTestBoxScript.getPathScripts(),
                                     asArgs[0])

        if asArgs[0].endswith('.py') and fWithInterpreter:
            if sys.executable is not None and len(sys.executable) > 0:
                asArgs.insert(0, sys.executable)
            else:
                asArgs.insert(0, 'python')

        return asArgs
Beispiel #10
0
    def _doUploadFile(self, oSrcFile, sSrcFilename, sDescription, sKind, sMime):
        """ Uploads the given file to the test manager. """

        # Prepare header and url.
        dHeader = dict(self._dHttpHeader);
        dHeader['Content-Type'] = 'application/octet-stream';
        self._writeOutput('%s: _doUploadFile: sHeader=%s' % (utils.getTimePrefix(), dHeader,));
        oSrcFile.seek(0, 2);
        self._writeOutput('%s: _doUploadFile: size=%d' % (utils.getTimePrefix(), oSrcFile.tell(),));
        oSrcFile.seek(0);

        from common import constants;
        sUrl = self._sTmServerPath + '&' \
             + self._fnUrlEncode({ constants.tbreq.UPLOAD_PARAM_NAME: os.path.basename(sSrcFilename),
                                   constants.tbreq.UPLOAD_PARAM_DESC: sDescription,
                                   constants.tbreq.UPLOAD_PARAM_KIND: sKind,
                                   constants.tbreq.UPLOAD_PARAM_MIME: sMime,
                                   constants.tbreq.ALL_PARAM_ACTION:  constants.tbreq.UPLOAD,
                                });

        # Retry loop.
        secStart = utils.timestampSecond();
        while True:
            try:
                oConn = self._fnTmConnect();
                oConn.request('POST', sUrl, oSrcFile.read(), dHeader);
                fRc = self._processTmStatusResponse(oConn, '_doUploadFile', fClose = True);
                oConn.close();
                if fRc is not None:
                    return fRc;
            except:
                logXcpt('warning: exception during UPLOAD request');

            if utils.timestampSecond() - secStart >= self.kcSecTestManagerRetryTimeout:
                self._writeOutput('%s: _doUploadFile: Timed out.' % (utils.getTimePrefix(),));
                break;
            try: oSrcFile.seek(0);
            except:
                logXcpt();
                break;
            self._writeOutput('%s: _doUploadFile: Retrying...' % (utils.getTimePrefix(), ));
            time.sleep(2);

        return False;
    def _reportDone(self, sResult):
        """
        Report EXEC job done to the test manager.

        sResult is a value from constants.result.
        """
        ## @todo optimize this to use one server connection.

        #
        # Log it.
        #
        assert sResult in constants.result.g_kasValidResults;
        self._log('Done %s' % (sResult,));

        #
        # Report it.
        #
        fRc = True;
        secStart = utils.timestampSecond();
        while True:
            self._logFlush(); ## @todo Combine this with EXEC_COMPLETED.
            oConnection = None;
            try:
                oConnection = self._oTestBoxScript.openTestManagerConnection();
                oConnection.postRequest(constants.tbreq.EXEC_COMPLETED, {constants.tbreq.EXEC_COMPLETED_PARAM_RESULT: sResult});
                oConnection.close();
            except Exception as oXcpt:
                if utils.timestampSecond() - secStart < self.ksecTestManagerTimeout:
                    self._log('_reportDone exception (%s) - retrying...' % (oXcpt,));
                    time.sleep(2);
                    continue;
                self._log('_reportDone error: %s' % (oXcpt,));
                if oConnection is not None: # Be kind to apache.
                    try:    oConnection.close();
                    except: pass;
                fRc = False;
            break;

        #
        # Mark the task as completed.
        #
        self._complete();
        return fRc;
Beispiel #12
0
    def __init__(self):
        ReporterBase.__init__(self);
        self.sTestManagerUrl    = os.environ.get('TESTBOX_MANAGER_URL');
        self.sTestBoxUuid       = os.environ.get('TESTBOX_UUID');
        self.idTestBox          = int(os.environ.get('TESTBOX_ID'));
        self.idTestSet          = int(os.environ.get('TESTBOX_TEST_SET_ID'));
        self._asXml             = [];
        self._secTsXmlFlush     = utils.timestampSecond();
        self._secTsXmlLast      = self._secTsXmlFlush;
        self._fXmlFlushing      = False;
        self.oOutput            = sys.stdout; # Hack for __del__ output.
        self.fFlushEachLine     = True;
        self.fDebugXml          = 'TESTDRIVER_REPORTER_DEBUG_XML' in os.environ;

        # Prepare the TM connecting.
        import urlparse;
        import httplib;
        import urllib;
        from common import constants;

        self._fnUrlEncode       = urllib.urlencode;
        self._fnUrlParseQs      = urlparse.parse_qs;
        self._oParsedTmUrl      = urlparse.urlparse(self.sTestManagerUrl);

        if     sys.version_info[0] >= 3 \
           or (sys.version_info[0] == 2 and sys.version_info[1] >= 6):
            if self._oParsedTmUrl.scheme == 'https': # pylint: disable=E1101
                self._fnTmConnect = lambda: httplib.HTTPSConnection(self._oParsedTmUrl.hostname,
                                                                    timeout = self.kcSecTestManagerRequestTimeout);
            else:
                self._fnTmConnect = lambda: httplib.HTTPConnection( self._oParsedTmUrl.hostname,
                                                                    timeout = self.kcSecTestManagerRequestTimeout);
        else:
            if self._oParsedTmUrl.scheme == 'https': # pylint: disable=E1101
                self._fnTmConnect = lambda: httplib.HTTPSConnection(self._oParsedTmUrl.hostname);
            else:
                self._fnTmConnect = lambda: httplib.HTTPConnection( self._oParsedTmUrl.hostname);
        self._dHttpHeader = \
        {
            'Content-Type':     'application/x-www-form-urlencoded; charset=utf-8',
            'User-Agent':       'TestDriverReporter/%s.0 (%s, %s)' % (__version__, utils.getHostOs(), utils.getHostArch(),),
            'Accept':           'text/plain,application/x-www-form-urlencoded',
            'Accept-Encoding':  'identity',
            'Cache-Control':    'max-age=0',
            #'Connection':       'keep-alive',
        };

        dParams = {
            constants.tbreq.ALL_PARAM_TESTBOX_UUID:     self.sTestBoxUuid,
            constants.tbreq.ALL_PARAM_TESTBOX_ID:       self.idTestBox,
            constants.tbreq.RESULT_PARAM_TEST_SET_ID:   self.idTestSet,
        };
        self._sTmServerPath = '/%s/testboxdisp.py?%s' \
                            % ( self._oParsedTmUrl.path.strip('/'), # pylint: disable=E1101
                                urllib.urlencode(dParams), );
Beispiel #13
0
    def _logFlush(self, oGivenConnection=None):
        """
        Flushes the log to the test manager.

        No exceptions.
        """
        fRc = True
        self._oBackLogFlushLock.acquire()

        # Grab the current back log.
        self._oBackLogLock.acquire()
        asBackLog = self._asBackLog
        self._asBackLog = []
        self._cchBackLog = 0
        self._secTsBackLogFlush = utils.timestampSecond()
        self._oBackLogLock.release()

        # If there is anything to flush, flush it.
        if asBackLog:
            sBody = ''
            for sLine in asBackLog:
                sBody += sLine + '\n'

            oConnection = None
            try:
                if oGivenConnection is None:
                    oConnection = self._oTestBoxScript.openTestManagerConnection(
                    )
                    oConnection.postRequest(
                        constants.tbreq.LOG_MAIN,
                        {constants.tbreq.LOG_PARAM_BODY: sBody})
                    oConnection.close()
                else:
                    oGivenConnection.postRequest(
                        constants.tbreq.LOG_MAIN,
                        {constants.tbreq.LOG_PARAM_BODY: sBody})
            except Exception as oXcpt:
                testboxcommons.log('_logFlush error: %s' % (oXcpt, ))
                if len(sBody) < self.kcchMaxBackLog * 4:
                    self._oBackLogLock.acquire()
                    asBackLog.extend(self._asBackLog)
                    self._asBackLog = asBackLog
                    # Don't restore _cchBackLog as there is no point in retrying immediately.
                    self._oBackLogLock.release()
                if oConnection is not None:  # Be kind to apache.
                    try:
                        oConnection.close()
                    except:
                        pass
                fRc = False

        self._oBackLogFlushLock.release()
        return fRc
    def _waitForTestManagerConnectivity(self, cSecTimeout):
        """
        Check and wait for network connectivity to the test manager.

        This is used with the windows installation and uninstallation since
        these usually disrupts network connectivity when installing the filter
        driver.  If we proceed to quickly, we might finish the test at a time
        when we cannot report to the test manager and thus end up with an
        abandonded test error.
        """
        cSecElapsed = 0;
        secStart    = utils.timestampSecond();
        while reporter.checkTestManagerConnection() is False:
            cSecElapsed = utils.timestampSecond() - secStart;
            if cSecElapsed >= cSecTimeout:
                reporter.log('_waitForTestManagerConnectivity: Giving up after %u secs.' % (cSecTimeout,));
                return False;
            time.sleep(2);

        if cSecElapsed > 0:
            reporter.log('_waitForTestManagerConnectivity: Waited %s secs.' % (cSecTimeout,));
        return True;
    def __init__(self, oTestBoxScript, cSecTimeout, fnThreadProc):
        self._oTestBoxScript    = oTestBoxScript;
        self._cSecTimeout       = cSecTimeout;
        self._tsSecStarted      = utils.timestampSecond();
        self.__oRLock           = threading.RLock();
        self._oCv               = threading.Condition(self.__oRLock);
        self._fRunning          = True;     # Protected by lock.
        self._fShouldTerminate  = False;    # Protected by lock.

        # Spawn the worker thread.
        self._oThread           = threading.Thread(target=fnThreadProc);
        self._oThread.daemon    = True;
        self._oThread.start();
Beispiel #16
0
    def __init__(self, oTestBoxScript, cSecTimeout, fnThreadProc):
        self._oTestBoxScript    = oTestBoxScript;
        self._cSecTimeout       = cSecTimeout;
        self._tsSecStarted      = utils.timestampSecond();
        self.__oRLock           = threading.RLock();
        self._oCv               = threading.Condition(self.__oRLock);
        self._fRunning          = True;     # Protected by lock.
        self._fShouldTerminate  = False;    # Protected by lock.

        # Spawn the worker thread.
        self._oThread           = threading.Thread(target=fnThreadProc);
        self._oThread.daemon    = True;
        self._oThread.start();
    def _assembleArguments(self, sAction, fWithInterpreter = True):
        """
        Creates an argument array for subprocess.Popen, splitting the
        sScriptCmdLine like bourne shell would.
        fWithInterpreter is used (False) when checking that the script exists.

        Returns None on bad input.
        """

        #
        # This is a good place to export the test set id to the environment.
        #
        os.environ['TESTBOX_TEST_SET_ID'] = str(self._idResult);
        cTimeoutLeft = utils.timestampSecond() - self._tsSecStarted;
        cTimeoutLeft = 0 if cTimeoutLeft >= self._cSecTimeout else self._cSecTimeout - cTimeoutLeft;
        os.environ['TESTBOX_TIMEOUT']     = str(cTimeoutLeft);
        os.environ['TESTBOX_TIMEOUT_ABS'] = str(self._tsSecStarted + self._cSecTimeout);

        #
        # Do replacements and split the command line into arguments.
        #
        if self._sScriptCmdLine.find('@ACTION@') >= 0:
            sCmdLine = self._sScriptCmdLine.replace('@ACTION@', sAction);
        else:
            sCmdLine = self._sScriptCmdLine + ' ' + sAction;
        for sVar in [ 'TESTBOX_PATH_BUILDS', 'TESTBOX_PATH_RESOURCES', 'TESTBOX_PATH_SCRATCH', 'TESTBOX_PATH_SCRIPTS',
                      'TESTBOX_PATH_UPLOAD', 'TESTBOX_UUID', 'TESTBOX_REPORTER', 'TESTBOX_ID', 'TESTBOX_TEST_SET_ID',
                      'TESTBOX_TIMEOUT', 'TESTBOX_TIMEOUT_ABS' ]:
            if sCmdLine.find('${' + sVar + '}') >= 0:
                sCmdLine = sCmdLine.replace('${' + sVar + '}', os.environ[sVar]);

        asArgs = utils.argsSplit(sCmdLine);

        #
        # Massage argv[0]:
        #   - Convert portable slashes ('/') to the flavor preferred by the
        #     OS we're currently running on.
        #   - Run python script thru the current python interpreter (important
        #     on systems that doesn't sport native hash-bang script execution).
        #
        asArgs[0] = asArgs[0].replace('/', os.path.sep);
        if not os.path.isabs(asArgs[0]):
            asArgs[0] = os.path.join(self._oTestBoxScript.getPathScripts(), asArgs[0]);

        if asArgs[0].endswith('.py') and fWithInterpreter:
            if sys.executable:
                asArgs.insert(0, sys.executable);
            else:
                asArgs.insert(0, 'python');

        return asArgs;
Beispiel #18
0
    def _xmlDoFlush(self, asXml, fRetry = False, fDtor = False):
        """
        The code that does the actual talking to the server.
        Used by both xmlFlush and __del__.
        """
        secStart = utils.timestampSecond();
        while True:
            fRc = None;
            try:
                # Post.
                from common import constants;
                sPostBody = self._fnUrlEncode({constants.tbreq.XML_RESULT_PARAM_BODY: '\n'.join(asXml),});
                oConn = self._fnTmConnect();
                oConn.request('POST',
                              self._sTmServerPath + ('&%s=%s' % (constants.tbreq.ALL_PARAM_ACTION, constants.tbreq.XML_RESULTS)),
                              sPostBody,
                              self._dHttpHeader);

                fRc = self._processTmStatusResponse(oConn, '_xmlDoFlush', fClose = True);
                if fRc is True:
                    if self.fDebugXml:
                        self._writeOutput('_xmlDoFlush:\n%s' % ('\n'.join(asXml),));
                    return (None, False);
                if fRc is False:
                    self._writeOutput('_xmlDoFlush: Failed - we should abort the test, really.');
                    return (None, True);
            except Exception, oXcpt:
                if not fDtor:
                    logXcpt('warning: exception during XML_RESULTS request');
                else:
                    self._writeOutput('warning: exception during XML_RESULTS request: %s' % (oXcpt,));

            if   fRetry is not True \
              or utils.timestampSecond() - secStart >= self.kcSecTestManagerRetryTimeout:
                break;
            time.sleep(2);
Beispiel #19
0
    def __init__(self, oTestBoxScript, fnThreadProc, cSecTimeout, idResult, sScriptCmdLine):
        """
        Class instance init
        """
        # Init our instance data.
        self._idResult          = idResult;
        self._sScriptCmdLine    = sScriptCmdLine;
        self._oChild            = None;
        self._oBackLogLock      = threading.RLock();
        self._oBackLogFlushLock = threading.RLock();
        self._asBackLog         = [];
        self._cchBackLog        = 0;
        self._secTsBackLogFlush = utils.timestampSecond();

        # Init super.
        TestBoxBaseTask.__init__(self, oTestBoxScript, cSecTimeout, fnThreadProc);
    def __init__(self, oTestBoxScript, fnThreadProc, cSecTimeout, idResult, sScriptCmdLine):
        """
        Class instance init
        """
        # Init our instance data.
        self._idResult          = idResult;
        self._sScriptCmdLine    = sScriptCmdLine;
        self._oChild            = None;
        self._oBackLogLock      = threading.RLock();
        self._oBackLogFlushLock = threading.RLock();
        self._asBackLog         = [];
        self._cchBackLog        = 0;
        self._secTsBackLogFlush = utils.timestampSecond();

        # Init super.
        TestBoxBaseTask.__init__(self, oTestBoxScript, cSecTimeout, fnThreadProc);
    def _logFlush(self, oGivenConnection = None):
        """
        Flushes the log to the test manager.

        No exceptions.
        """
        fRc = True;
        self._oBackLogFlushLock.acquire();

        # Grab the current back log.
        self._oBackLogLock.acquire();
        asBackLog = self._asBackLog;
        self._asBackLog  = [];
        self._cchBackLog = 0;
        self._secTsBackLogFlush = utils.timestampSecond();
        self._oBackLogLock.release();

        # If there is anything to flush, flush it.
        if asBackLog:
            sBody = '';
            for sLine in asBackLog:
                sBody += sLine + '\n';

            oConnection = None;
            try:
                if oGivenConnection is None:
                    oConnection = self._oTestBoxScript.openTestManagerConnection();
                    oConnection.postRequest(constants.tbreq.LOG_MAIN, {constants.tbreq.LOG_PARAM_BODY: sBody});
                    oConnection.close();
                else:
                    oGivenConnection.postRequest(constants.tbreq.LOG_MAIN, {constants.tbreq.LOG_PARAM_BODY: sBody});
            except Exception as oXcpt:
                testboxcommons.log('_logFlush error: %s' % (oXcpt,));
                if len(sBody) < self.kcchMaxBackLog * 4:
                    self._oBackLogLock.acquire();
                    asBackLog.extend(self._asBackLog);
                    self._asBackLog = asBackLog;
                    # Don't restore _cchBackLog as there is no point in retrying immediately.
                    self._oBackLogLock.release();
                if oConnection is not None: # Be kind to apache.
                    try:    oConnection.close();
                    except: pass;
                fRc = False;

        self._oBackLogFlushLock.release();
        return fRc;
Beispiel #22
0
    def _xmlFlushIfNecessary(self):
        """Flushes the XML back log if necessary."""
        tsNow = utils.timestampSecond();
        cSecs     = tsNow - self._secTsXmlFlush;
        cSecsLast = tsNow - self._secTsXmlLast;
        self._secTsXmlLast = tsNow;

        # Absolute flush thresholds.
        if cSecs >= self.kcSecXmlFlushMax:
            return self.xmlFlush();
        if len(self._asXml) >= self.kcLinesXmlFlush:
            return self.xmlFlush();

        # Flush if idle long enough.
        if    cSecs     >= self.kcSecXmlFlushMin \
          and cSecsLast >= self.kcSecXmlFlushIdle:
            return self.xmlFlush();

        return False;
Beispiel #23
0
    def _xmlFlushIfNecessary(self):
        """Flushes the XML back log if necessary."""
        tsNow = utils.timestampSecond()
        cSecs = tsNow - self._secTsXmlFlush
        cSecsLast = tsNow - self._secTsXmlLast
        self._secTsXmlLast = tsNow

        # Absolute flush thresholds.
        if cSecs >= self.kcSecXmlFlushMax:
            return self.xmlFlush()
        if len(self._asXml) >= self.kcLinesXmlFlush:
            return self.xmlFlush()

        # Flush if idle long enough.
        if    cSecs     >= self.kcSecXmlFlushMin \
          and cSecsLast >= self.kcSecXmlFlushIdle:
            return self.xmlFlush()

        return False
Beispiel #24
0
    def _monitorChild(self, cSecTimeout, fTryKillCommand = True, oChild = None):
        """
        Monitors the child process.  If the child executes longer that
        cSecTimeout allows, we'll terminate it.
        Returns Success indicator and constants.result value.
        """

        if oChild is None:
            oChild = self._oChild;

        iProcGroup = oChild.pid;
        if utils.getHostOs() in ['win', 'os2'] or iProcGroup <= 0:
            iProcGroup = -2;

        #
        # Do timeout processing and check the health of the child.
        #
        sResult   = constants.result.PASSED;
        seStarted = utils.timestampSecond();
        while True:
            # Check status.
            iRc = oChild.poll();
            if iRc is not None:
                self._log('Child doing "%s" completed with exit code %d' % (oChild.sTestBoxScriptAction, iRc));
                oChild.oOutputThread.join(self.kcSecFinalOutputTimeout);

                if oChild is self._oChild:
                    self._oChild = None;

                if iRc == constants.rtexitcode.SKIPPED:
                    return (True, constants.result.SKIPPED);
                if iRc != constants.rtexitcode.SUCCESS:
                    return (False, constants.result.FAILED);
                return (True, constants.result.PASSED);

            # Check for abort first, since that has less of a stigma.
            if self._shouldTerminate() is True:
                sResult = constants.result.ABORTED;
                break;

            # Check timeout.
            cSecElapsed = utils.timestampSecond() - seStarted;
            if cSecElapsed > cSecTimeout:
                self._log('Timeout: %u secs (limit %u secs)' % (cSecElapsed, cSecTimeout));
                sResult = constants.result.TIMED_OUT;
                break;

            # Wait.
            cSecLeft = cSecTimeout - cSecElapsed;
            oChild.oOutputThread.join(15 if cSecLeft > 15 else (cSecLeft + 1));

        #
        # If the child is still alive, try use the abort command to stop it
        # very gently.  This let's the testdriver clean up daemon processes
        # and such that our code below won't catch.
        #
        if fTryKillCommand and oChild.poll() is None:
            self._log('Attempting to abort child...');
            (fRc2, oAbortChild) = self._spawnChild('abort');
            if oAbortChild is not None and fRc2 is True:
                self._monitorChild(self.kcSecAbortTimeout, False, oAbortChild);
                oAbortChild = None;

        #
        # If the child is still alive, try the polite way.
        #
        if oChild.poll() is None:
            self._log('Attempting to terminate child doing "%s"...' % (oChild.sTestBoxScriptAction,));

            if iProcGroup > 0:
                try:
                    os.killpg(iProcGroup, signal.SIGTERM); # pylint: disable=E1101
                except Exception, oXcpt:
                    self._log('killpg() failed: %s' % (oXcpt,));

            try:
                self._oChild.terminate();
                oChild.oOutputThread.join(self.kcSecTerminateOutputTimeout);
            except Exception, oXcpt:
                self._log('terminate() failed: %s' % (oXcpt,));
Beispiel #25
0
                sTs = 'oXcpt=%s ' % (oXcpt);
            sFullMsg = sTs + sMessage;
        else:
            sFullMsg = sMessage;

        self._oBackLogLock.acquire();
        self._asBackLog.append(sFullMsg);
        cchBackLog = self._cchBackLog + len(sFullMsg) + 1;
        self._cchBackLog = cchBackLog;
        secTsBackLogFlush = self._secTsBackLogFlush;
        self._oBackLogLock.release();

        testboxcommons.log(sFullMsg);
        return fFlushCheck \
            and (   cchBackLog >= self.kcchMaxBackLog \
                 or utils.timestampSecond() - secTsBackLogFlush >= self.kcSecBackLogFlush);

    def _log(self, sMessage):
        """
        General logging function, will flush.
        """
        if self._logInternal(sMessage, fFlushCheck = True):
            self._logFlush();
        return True;

    def _reportDone(self, sResult):
        """
        Report EXEC job done to the test manager.

        sResult is a value from constants.result.
        """
    def _monitorChild(self, cSecTimeout, fTryKillCommand = True, oChild = None):
        """
        Monitors the child process.  If the child executes longer that
        cSecTimeout allows, we'll terminate it.
        Returns Success indicator and constants.result value.
        """

        if oChild is None:
            oChild = self._oChild;

        iProcGroup = oChild.pid;
        if utils.getHostOs() in ['win', 'os2'] or iProcGroup <= 0:
            iProcGroup = -2;

        #
        # Do timeout processing and check the health of the child.
        #
        sResult   = constants.result.PASSED;
        seStarted = utils.timestampSecond();
        while True:
            # Check status.
            iRc = oChild.poll();
            if iRc is not None:
                self._log('Child doing "%s" completed with exit code %d' % (oChild.sTestBoxScriptAction, iRc));
                oChild.oOutputThread.join(self.kcSecFinalOutputTimeout);

                if oChild is self._oChild:
                    self._oChild = None;

                if iRc == constants.rtexitcode.SKIPPED:
                    return (True, constants.result.SKIPPED);
                if iRc != constants.rtexitcode.SUCCESS:
                    return (False, constants.result.FAILED);
                return (True, constants.result.PASSED);

            # Check for abort first, since that has less of a stigma.
            if self._shouldTerminate() is True:
                sResult = constants.result.ABORTED;
                break;

            # Check timeout.
            cSecElapsed = utils.timestampSecond() - seStarted;
            if cSecElapsed > cSecTimeout:
                self._log('Timeout: %u secs (limit %u secs)' % (cSecElapsed, cSecTimeout));
                sResult = constants.result.TIMED_OUT;
                break;

            # Wait.
            cSecLeft = cSecTimeout - cSecElapsed;
            oChild.oOutputThread.join(15 if cSecLeft > 15 else (cSecLeft + 1));

        #
        # If the child is still alive, try use the abort command to stop it
        # very gently.  This let's the testdriver clean up daemon processes
        # and such that our code below won't catch.
        #
        if fTryKillCommand and oChild.poll() is None:
            self._log('Attempting to abort child...');
            (fRc2, oAbortChild) = self._spawnChild('abort');
            if oAbortChild is not None and fRc2 is True:
                self._monitorChild(self.kcSecAbortTimeout, False, oAbortChild);
                oAbortChild = None;

        #
        # If the child is still alive, try the polite way.
        #
        if oChild.poll() is None:
            self._log('Attempting to terminate child doing "%s"...' % (oChild.sTestBoxScriptAction,));

            if iProcGroup > 0:
                try:
                    os.killpg(iProcGroup, signal.SIGTERM); # pylint: disable=E1101
                except Exception as oXcpt:
                    self._log('killpg() failed: %s' % (oXcpt,));

            try:
                self._oChild.terminate();
                oChild.oOutputThread.join(self.kcSecTerminateOutputTimeout);
            except Exception as oXcpt:
                self._log('terminate() failed: %s' % (oXcpt,));

        #
        # If the child doesn't respond to polite, kill it.  Always do a killpg
        # should there be any processes left in the group.
        #
        if iProcGroup > 0:
            try:
                os.killpg(iProcGroup, signal.SIGKILL); # pylint: disable=E1101
            except Exception as oXcpt:
                self._log('killpg() failed: %s' % (oXcpt,));

        if oChild.poll() is None:
            self._log('Attemting to kill child doing "%s"...' % (oChild.sTestBoxScriptAction,));
            try:
                self._oChild.kill();
                oChild.oOutputThread.join(self.kcSecKillOutputTimeout);
            except Exception as oXcpt:
                self._log('kill() failed: %s' % (oXcpt,));

        #
        # Give the whole mess a couple of more seconds to respond in case the
        # output thread exitted prematurely for some weird reason.
        #
        if oChild.poll() is None:
            time.sleep(2);
            time.sleep(2);
            time.sleep(2);

        iRc = oChild.poll();
        if iRc is not None:
            self._log('Child doing "%s" aborted with exit code %d' % (oChild.sTestBoxScriptAction, iRc));
        else:
            self._log('Child doing "%s" is still running, giving up...' % (oChild.sTestBoxScriptAction,));
            ## @todo in this case we should probably try reboot the testbox...
            oChild.oOutputThread.fPleaseQuit = True;

        if oChild is self._oChild:
            self._oChild = None;
        return (False, sResult);
Beispiel #27
0
    def _monitorChild(self, cSecTimeout, fTryKillCommand=True, oChild=None):
        """
        Monitors the child process.  If the child executes longer that
        cSecTimeout allows, we'll terminate it.
        Returns Success indicator and constants.result value.
        """

        if oChild is None:
            oChild = self._oChild

        iProcGroup = oChild.pid
        if utils.getHostOs() in ['win', 'os2'] or iProcGroup <= 0:
            iProcGroup = -2

        #
        # Do timeout processing and check the health of the child.
        #
        sResult = constants.result.PASSED
        seStarted = utils.timestampSecond()
        while True:
            # Check status.
            iRc = oChild.poll()
            if iRc is not None:
                self._log('Child doing "%s" completed with exit code %d' %
                          (oChild.sTestBoxScriptAction, iRc))
                oChild.oOutputThread.join(self.kcSecFinalOutputTimeout)

                if oChild is self._oChild:
                    self._oChild = None

                if iRc == constants.rtexitcode.SKIPPED:
                    return (True, constants.result.SKIPPED)
                if iRc != constants.rtexitcode.SUCCESS:
                    return (False, constants.result.FAILED)
                return (True, constants.result.PASSED)

            # Check for abort first, since that has less of a stigma.
            if self._shouldTerminate() is True:
                sResult = constants.result.ABORTED
                break

            # Check timeout.
            cSecElapsed = utils.timestampSecond() - seStarted
            if cSecElapsed > cSecTimeout:
                self._log('Timeout: %u secs (limit %u secs)' %
                          (cSecElapsed, cSecTimeout))
                sResult = constants.result.TIMED_OUT
                break

            # Wait.
            cSecLeft = cSecTimeout - cSecElapsed
            oChild.oOutputThread.join(15 if cSecLeft > 15 else (cSecLeft + 1))

        #
        # If the child is still alive, try use the abort command to stop it
        # very gently.  This let's the testdriver clean up daemon processes
        # and such that our code below won't catch.
        #
        if fTryKillCommand and oChild.poll() is None:
            self._log('Attempting to abort child...')
            (fRc2, oAbortChild) = self._spawnChild('abort')
            if oAbortChild is not None and fRc2 is True:
                self._monitorChild(self.kcSecAbortTimeout, False, oAbortChild)
                oAbortChild = None

        #
        # If the child is still alive, try the polite way.
        #
        if oChild.poll() is None:
            self._log('Attempting to terminate child doing "%s"...' %
                      (oChild.sTestBoxScriptAction, ))

            if iProcGroup > 0:
                try:
                    os.killpg(iProcGroup, signal.SIGTERM)
                    # pylint: disable=E1101
                except Exception as oXcpt:
                    self._log('killpg() failed: %s' % (oXcpt, ))

            try:
                self._oChild.terminate()
                oChild.oOutputThread.join(self.kcSecTerminateOutputTimeout)
            except Exception as oXcpt:
                self._log('terminate() failed: %s' % (oXcpt, ))

        #
        # If the child doesn't respond to polite, kill it.  Always do a killpg
        # should there be any processes left in the group.
        #
        if iProcGroup > 0:
            try:
                os.killpg(iProcGroup, signal.SIGKILL)
                # pylint: disable=E1101
            except Exception as oXcpt:
                self._log('killpg() failed: %s' % (oXcpt, ))

        if oChild.poll() is None:
            self._log('Attemting to kill child doing "%s"...' %
                      (oChild.sTestBoxScriptAction, ))
            try:
                self._oChild.kill()
                oChild.oOutputThread.join(self.kcSecKillOutputTimeout)
            except Exception as oXcpt:
                self._log('kill() failed: %s' % (oXcpt, ))

        #
        # Give the whole mess a couple of more seconds to respond in case the
        # output thread exitted prematurely for some weird reason.
        #
        if oChild.poll() is None:
            time.sleep(2)
            time.sleep(2)
            time.sleep(2)

        iRc = oChild.poll()
        if iRc is not None:
            self._log('Child doing "%s" aborted with exit code %d' %
                      (oChild.sTestBoxScriptAction, iRc))
        else:
            self._log('Child doing "%s" is still running, giving up...' %
                      (oChild.sTestBoxScriptAction, ))
            ## @todo in this case we should probably try reboot the testbox...
            oChild.oOutputThread.fPleaseQuit = True

        if oChild is self._oChild:
            self._oChild = None
        return (False, sResult)
Beispiel #28
0
                sTs = 'oXcpt=%s ' % (oXcpt);
            sFullMsg = sTs + sMessage;
        else:
            sFullMsg = sMessage;

        self._oBackLogLock.acquire();
        self._asBackLog.append(sFullMsg);
        cchBackLog = self._cchBackLog + len(sFullMsg) + 1;
        self._cchBackLog = cchBackLog;
        secTsBackLogFlush = self._secTsBackLogFlush;
        self._oBackLogLock.release();

        testboxcommons.log(sFullMsg);
        return fFlushCheck \
            and (   cchBackLog >= self.kcchMaxBackLog \
                 or utils.timestampSecond() - secTsBackLogFlush >= self.kcSecBackLogFlush);

    def _log(self, sMessage):
        """
        General logging function, will flush.
        """
        if self._logInternal(sMessage, fFlushCheck = True):
            self._logFlush();
        return True;

    def _reportDone(self, sResult):
        """
        Report EXEC job done to the test manager.

        sResult is a value from constants.result.
        """