Example #1
0
 def hexFormatBytes(abBuf):
     """ Formats a buffer/string/whatever as a string of hex bytes """
     if sys.version_info[0] >= 3:
         if utils.isString(abBuf):
             try:
                 abBuf = bytes(abBuf, 'utf-8')
             except:
                 pass
     else:
         if utils.isString(abBuf):
             try:
                 abBuf = bytearray(abBuf, 'utf-8')
                 # pylint: disable=redefined-variable-type
             except:
                 pass
     sRet = ''
     off = 0
     for off, bByte in enumerate(abBuf):
         if off > 0:
             sRet += ' ' if off & 7 else '-'
         if isinstance(bByte, int):
             sRet += '%02x' % (bByte, )
         else:
             sRet += '%02x' % (ord(bByte), )
     return sRet
Example #2
0
    def dispatchRequest(self):
        """
        Dispatches the incoming request where the path is given as an argument.

        Will raise RestDispException on failure.
        """

        #
        # Get the parameters.
        #
        try:
            dParams = self._oSrvGlue.getParameters()
        except Exception as oXcpt:
            raise RestDispException(
                'Error retriving parameters: %s' % (oXcpt, ), 500)
        self._dParams = dParams

        #
        # Get the path parameter.
        #
        if self.ksParam_sPath not in dParams:
            raise RestDispException(
                'No "%s" parameter in request (params: %s)' % (
                    self.ksParam_sPath,
                    dParams,
                ), 500)
        self._sPath = self._getStringParam(self.ksParam_sPath)
        assert utils.isString(self._sPath)

        return self._dispatchRequestCommon()
Example #3
0
def escapeAttrToStr(oObject):
    """
    Stringifies the object and hands it to escapeAttr.  May return unicode string.
    """
    if utils.isString(oObject):
        return escapeAttr(oObject);
    return escapeAttr(str(oObject));
    def __init__(self, oExec, sTargetOs, oDiskCfg):
        self.oExec    = oExec;
        self.lstDisks = [ ]; # List of disks present in the system.
        self.dPools   = { }; # Dictionary of storage pools.
        self.dVols    = { }; # Dictionary of volumes.
        self.iPoolId  = 0;
        self.iVolId   = 0;

        fRc = True;
        oStorOs = None;
        if sTargetOs == 'solaris':
            oStorOs = StorageConfigOsSolaris();
        elif sTargetOs == 'linux':
            oStorOs = StorageConfigOsLinux(); # pylint: disable=R0204
        else:
            fRc = False;

        if fRc:
            self.oStorOs = oStorOs;
            if utils.isString(oDiskCfg):
                self.lstDisks = oStorOs.getDisksMatchingRegExp(oDiskCfg);
            else:
                # Assume a list of of disks and add.
                for sDisk in oDiskCfg:
                    self.lstDisks.append(StorageDisk(sDisk));
Example #5
0
def escapeAttrToStr(oObject):
    """
    Stringifies the object and hands it to escapeAttr.  May return unicode string.
    """
    if utils.isString(oObject):
        return escapeAttr(oObject)
    return escapeAttr(str(oObject))
Example #6
0
    def validateListOfStr(
        asValues, cchMin=None, cchMax=None, asValidValues=None, aoNilValues=tuple([[], None]), fAllowNull=True
    ):
        """ Validates a list of text items."""
        (asValues, sError) = ModelDataBase.validateListOfSomething(asValues, aoNilValues, fAllowNull)

        if sError is None and asValues not in aoNilValues and len(asValues) > 0:
            if not utils.isString(asValues[0]):
                return (asValues, "Invalid item data type.")

            if not fAllowNull and cchMin is None:
                cchMin = 1

            for sValue in asValues:
                if asValidValues is not None and sValue not in asValidValues:
                    sThisErr = 'Invalid value "%s".' % (sValue,)
                elif cchMin is not None and len(sValue) < cchMin:
                    sThisErr = 'Value "%s" is too short, min length is %u chars.' % (sValue, cchMin)
                elif cchMax is not None and len(sValue) > cchMax:
                    sThisErr = 'Value "%s" is too long, max length is %u chars.' % (sValue, cchMax)
                else:
                    continue

                if sError is None:
                    sError = sThisErr
                else:
                    sError += " " + sThisErr

        return (asValues, sError)
Example #7
0
def escapeElemToStr(oObject):
    """
    Stringifies the object and hands it to escapeElem.
    """
    if utils.isString(oObject):
        return escapeElem(oObject)
    return escapeElem(str(oObject))
Example #8
0
def escapeElemToStr(oObject):
    """
    Stringifies the object and hands it to escapeElem.
    """
    if utils.isString(oObject):
        return escapeElem(oObject);
    return escapeElem(str(oObject));
Example #9
0
def dbTimestampToDatetime(oValue):
    """
    Converts a database timestamp to a datetime instance.
    """
    if isinstance(oValue, datetime.datetime):
        return oValue;
    if utils.isString(oValue):
        raise Exception('TODO');
    return oValue.pydatetime();
Example #10
0
 def _toHtml(self, oObject):
     """Translate some object to HTML."""
     if isinstance(oObject, WuiHtmlBase):
         return oObject.toHtml()
     if db.isDbTimestamp(oObject):
         return webutils.escapeElem(self.formatTsShort(oObject))
     if utils.isString(oObject):
         return webutils.escapeElem(oObject)
     return webutils.escapeElem(str(oObject))
Example #11
0
def stringRes(rc, sExpect):
    """Checks a string result."""
    global g_cTests, g_cFailures
    g_cTests = g_cTests + 1
    if utils.isString(rc):
        if rc == sExpect:
            return 'PASSED'
    g_cFailures = g_cFailures + 1
    return 'FAILED'
Example #12
0
def dbTimestampToDatetime(oValue):
    """
    Converts a database timestamp to a datetime instance.
    """
    if isinstance(oValue, datetime.datetime):
        return oValue
    if utils.isString(oValue):
        return utils.parseIsoTimestamp(oValue)
    return oValue.pydatetime()
def stringRes(rc, sExpect):
    """Checks a string result."""
    global g_cTests, g_cFailures;
    g_cTests = g_cTests + 1;
    if utils.isString(rc):
        if rc == sExpect:
            return 'PASSED';
    g_cFailures = g_cFailures + 1;
    return 'FAILED';
Example #14
0
def dbTimestampToDatetime(oValue):
    """
    Converts a database timestamp to a datetime instance.
    """
    if isinstance(oValue, datetime.datetime):
        return oValue
    if utils.isString(oValue):
        raise Exception('TODO')
    return oValue.pydatetime()
Example #15
0
 def _toHtml(self, oObject):
     """Translate some object to HTML."""
     if isinstance(oObject, WuiHtmlBase):
         return oObject.toHtml();
     if db.isDbTimestamp(oObject):
         return webutils.escapeElem(self.formatTsShort(oObject));
     if utils.isString(oObject):
         return webutils.escapeElem(oObject);
     return webutils.escapeElem(str(oObject));
Example #16
0
def isDbTimestamp(oValue):
    """
    Checks if oValue is a DB timestamp object.
    """
    if isinstance(oValue, datetime.datetime):
        return True
    if utils.isString(oValue):
        ## @todo detect strings as well.
        return False
    return getattr(oValue, 'pydatetime', None) != None
Example #17
0
def isDbTimestamp(oValue):
    """
    Checks if oValue is a DB timestamp object.
    """
    if isinstance(oValue, datetime.datetime):
        return True;
    if utils.isString(oValue):
        ## @todo detect strings as well.
        return False;
    return getattr(oValue, 'pydatetime', None) != None;
Example #18
0
    def validateTs(sValue, aoNilValues = tuple([None, '']), fAllowNull = True):
        """ Validates a timestamp field. """
        if sValue in aoNilValues:
            return (sValue, None if fAllowNull else 'Mandatory.');
        if not utils.isString(sValue):
            return (sValue, None);

        sError = None;
        if len(sValue) == len('2012-10-08 01:54:06.364207+02:00'):
            oRes = re.match(r'(\d{4})-([01]\d)-([0123])\d ([012]\d):[0-5]\d:([0-6]\d).\d{6}[+-](\d\d):(\d\d)', sValue);
            if    oRes is not None \
              and (   int(oRes.group(6)) >  12 \
                   or int(oRes.group(7)) >= 60):
                sError = 'Invalid timezone offset.';
        elif len(sValue) == len('2012-10-08 01:54:06.00'):
            oRes = re.match(r'(\d{4})-([01]\d)-([0123])\d ([012]\d):[0-5]\d:([0-6]\d).\d{2}', sValue);
        elif len(sValue) == len('9999-12-31 23:59:59.999999'):
            oRes = re.match(r'(\d{4})-([01]\d)-([0123])\d ([012]\d):[0-5]\d:([0-6]\d).\d{6}', sValue);
        elif len(sValue) == len('999999-12-31 00:00:00.00'):
            oRes = re.match(r'(\d{6})-([01]\d)-([0123])\d ([012]\d):[0-5]\d:([0-6]\d).\d{2}', sValue);
        elif len(sValue) == len('9999-12-31T23:59:59.999999Z'):
            oRes = re.match(r'(\d{4})-([01]\d)-([0123])\d[Tt]([012]\d):[0-5]\d:([0-6]\d).\d{6}[Zz]', sValue);
        elif len(sValue) == len('9999-12-31T23:59:59.999999999Z'):
            oRes = re.match(r'(\d{4})-([01]\d)-([0123])\d[Tt]([012]\d):[0-5]\d:([0-6]\d).\d{9}[Zz]', sValue);
        else:
            return (sValue, 'Invalid timestamp length.');

        if oRes is None:
            sError = 'Invalid timestamp (format: 2012-10-08 01:54:06.364207+02:00).';
        else:
            iYear  = int(oRes.group(1));
            if iYear % 4 == 0 and (iYear % 100 != 0  or iYear % 400 == 0):
                acDaysOfMonth = [31, 29, 31,  30, 31, 30,  31, 31, 30,  31, 30, 31];
            else:
                acDaysOfMonth = [31, 28, 31,  30, 31, 30,  31, 31, 30,  31, 30, 31];
            iMonth = int(oRes.group(2));
            iDay   = int(oRes.group(3));
            iHour  = int(oRes.group(4));
            iSec   = int(oRes.group(5));
            if iMonth > 12:
                sError = 'Invalid timestamp month.';
            elif iDay > acDaysOfMonth[iMonth - 1]:
                sError = 'Invalid timestamp day-of-month (%02d has %d days).' % (iMonth, acDaysOfMonth[iMonth - 1]);
            elif iHour > 23:
                sError = 'Invalid timestamp hour.'
            elif iSec >= 61:
                sError = 'Invalid timestamp second.'
            elif iSec >= 60:
                sError = 'Invalid timestamp: no leap seconds, please.'
        return (sValue, sError);
Example #19
0
    def validateTs(sValue, aoNilValues=tuple([None, ""]), fAllowNull=True):
        """ Validates a timestamp field. """
        if sValue in aoNilValues:
            return (sValue, None if fAllowNull else "Mandatory.")
        if not utils.isString(sValue):
            return (sValue, None)

        sError = None
        if len(sValue) == len("2012-10-08 01:54:06.364207+02:00"):
            oRes = re.match(r"(\d{4})-([01]\d)-([0123])\d ([012]\d):[0-5]\d:([0-6]\d).\d{6}[+-](\d\d):(\d\d)", sValue)
            if oRes is not None and (int(oRes.group(6)) > 12 or int(oRes.group(7)) >= 60):
                sError = "Invalid timezone offset."
        elif len(sValue) == len("2012-10-08 01:54:06.00"):
            oRes = re.match(r"(\d{4})-([01]\d)-([0123])\d ([012]\d):[0-5]\d:([0-6]\d).\d{2}", sValue)
        elif len(sValue) == len("9999-12-31 23:59:59.999999"):
            oRes = re.match(r"(\d{4})-([01]\d)-([0123])\d ([012]\d):[0-5]\d:([0-6]\d).\d{6}", sValue)
        elif len(sValue) == len("999999-12-31 00:00:00.00"):
            oRes = re.match(r"(\d{6})-([01]\d)-([0123])\d ([012]\d):[0-5]\d:([0-6]\d).\d{2}", sValue)
        elif len(sValue) == len("9999-12-31T23:59:59.999999Z"):
            oRes = re.match(r"(\d{4})-([01]\d)-([0123])\d[Tt]([012]\d):[0-5]\d:([0-6]\d).\d{6}[Zz]", sValue)
        elif len(sValue) == len("9999-12-31T23:59:59.999999999Z"):
            oRes = re.match(r"(\d{4})-([01]\d)-([0123])\d[Tt]([012]\d):[0-5]\d:([0-6]\d).\d{9}[Zz]", sValue)
        else:
            return (sValue, "Invalid timestamp length.")

        if oRes is None:
            sError = "Invalid timestamp (format: 2012-10-08 01:54:06.364207+02:00)."
        else:
            iYear = int(oRes.group(1))
            if iYear % 4 == 0 and (iYear % 100 != 0 or iYear % 400 == 0):
                acDaysOfMonth = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
            else:
                acDaysOfMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
            iMonth = int(oRes.group(2))
            iDay = int(oRes.group(3))
            iHour = int(oRes.group(4))
            iSec = int(oRes.group(5))
            if iMonth > 12:
                sError = "Invalid timestamp month."
            elif iDay > acDaysOfMonth[iMonth - 1]:
                sError = "Invalid timestamp day-of-month (%02d has %d days)." % (iMonth, acDaysOfMonth[iMonth - 1])
            elif iHour > 23:
                sError = "Invalid timestamp hour."
            elif iSec >= 61:
                sError = "Invalid timestamp second."
            elif iSec >= 60:
                sError = "Invalid timestamp: no leap seconds, please."
        return (sValue, sError)
Example #20
0
 def _addLabel(self, sName, sLabel, sDivSubClass = 'normal'):
     """Internal worker for adding a label."""
     if sName in self._dErrors:
         sError = self._dErrors[sName];
         if utils.isString(sError):          # List error trick (it's an associative array).
             return self._add('      <li>\n'
                              '        <div class="tmform-field"><div class="tmform-field-%s">\n'
                              '          <label for="%s" class="tmform-error-label">%s\n'
                              '              <span class="tmform-error-desc">%s</span>\n'
                              '          </label>\n'
                              % (escapeAttr(sDivSubClass), escapeAttr(sName), escapeElem(sLabel),
                                 self._escapeErrorText(sError), ) );
     return self._add('      <li>\n'
                      '        <div class="tmform-field"><div class="tmform-field-%s">\n'
                      '          <label  for="%s">%s</label>\n'
                      % (escapeAttr(sDivSubClass), escapeAttr(sName), escapeElem(sLabel)) );
Example #21
0
 def _addLabel(self, sName, sLabel, sDivSubClass = 'normal'):
     """Internal worker for adding a label."""
     if sName in self._dErrors:
         sError = self._dErrors[sName];
         if utils.isString(sError):          # List error trick (it's an associative array).
             return self._add('      <li>\n'
                              '        <div class="tmform-field"><div class="tmform-field-%s">\n'
                              '          <label for="%s" class="tmform-error-label">%s\n'
                              '              <span class="tmform-error-desc">%s</span>\n'
                              '          </label>\n'
                              % (escapeAttr(sDivSubClass), escapeAttr(sName), escapeElem(sLabel),
                                 self._escapeErrorText(sError), ) );
     return self._add('      <li>\n'
                      '        <div class="tmform-field"><div class="tmform-field-%s">\n'
                      '          <label  for="%s">%s</label>\n'
                      % (escapeAttr(sDivSubClass), escapeAttr(sName), escapeElem(sLabel)) );
Example #22
0
    def validateLong(sValue, lMin=0, lMax=None, aoNilValues=tuple([long(-1), None, ""]), fAllowNull=True):
        """ Validates an long integer field. """
        if sValue in aoNilValues:
            if fAllowNull:
                return (None if sValue is None else aoNilValues[0], None)
            return (sValue, "Mandatory.")
        try:
            if utils.isString(sValue):
                lValue = long(sValue, 0)
            else:
                lValue = long(sValue)
        except:
            return (sValue, "Not a long integer")

        if lValue in aoNilValues:
            return (aoNilValues[0], None if fAllowNull else "Mandatory.")

        if lMin is not None and lValue < lMin:
            return (lValue, "Value too small (min %d)" % (lMin,))
        elif lMax is not None and lValue > lMax:
            return (lValue, "Value too high (max %d)" % (lMax,))
        return (lValue, None)
Example #23
0
    def validateInt(sValue, iMin=0, iMax=0x7FFFFFFE, aoNilValues=tuple([-1, None, ""]), fAllowNull=True):
        """ Validates an integer field. """
        if sValue in aoNilValues:
            if fAllowNull:
                return (None if sValue is None else aoNilValues[0], None)
            return (sValue, "Mandatory.")

        try:
            if utils.isString(sValue):
                iValue = int(sValue, 0)
            else:
                iValue = int(sValue)
        except:
            return (sValue, "Not an integer")

        if iValue in aoNilValues:
            return (aoNilValues[0], None if fAllowNull else "Mandatory.")

        if iValue < iMin:
            return (iValue, "Value too small (min %d)" % (iMin,))
        elif iValue > iMax:
            return (iValue, "Value too high (max %d)" % (iMax,))
        return (iValue, None)
Example #24
0
    def validateInt(sValue, iMin = 0, iMax = 0x7ffffffe, aoNilValues = tuple([-1, None, '']), fAllowNull = True):
        """ Validates an integer field. """
        if sValue in aoNilValues:
            if fAllowNull:
                return (None if sValue is None else aoNilValues[0], None);
            return (sValue, 'Mandatory.');

        try:
            if utils.isString(sValue):
                iValue = int(sValue, 0);
            else:
                iValue = int(sValue);
        except:
            return (sValue, 'Not an integer');

        if iValue in aoNilValues:
            return (aoNilValues[0], None if fAllowNull else 'Mandatory.');

        if iValue < iMin:
            return (iValue, 'Value too small (min %d)' % (iMin,));
        elif iValue > iMax:
            return (iValue, 'Value too high (max %d)' % (iMax,));
        return (iValue, None);
Example #25
0
    def createFile(self,
                   oTestSet,
                   sName,
                   sMime,
                   sKind,
                   sDesc,
                   cbFile,
                   fCommit=False):  # pylint: disable=R0914
        """
        Creates a file and associating with the current test result record in
        the test set.

        Returns file object that the file content can be written to.
        Raises exception on database error, I/O errors, if there are too many
        files in the test set or if they take up too much disk space.

        The caller (testboxdisp.py) is expected to do basic input validation,
        so we skip that and get on with the bits only we can do.
        """

        #
        # Furhter input and limit checks.
        #
        if oTestSet.enmStatus != TestSetData.ksTestStatus_Running:
            raise TMExceptionBase(
                'Cannot create files on a test set with status "%s".' %
                (oTestSet.enmStatus, ))

        self._oDb.execute(
            'SELECT   TestResultStrTab.sValue\n'
            'FROM     TestResultFiles,\n'
            '         TestResults,\n'
            '         TestResultStrTab\n'
            'WHERE    TestResults.idTestSet        = %s\n'
            '     AND TestResultFiles.idTestResult = TestResults.idTestResult\n'
            '     AND TestResultStrTab.idStr       = TestResultFiles.idStrFile\n',
            (oTestSet.idTestSet, ))
        if self._oDb.getRowCount() + 1 > config.g_kcMaxUploads:
            raise TMExceptionBase('Uploaded too many files already (%d).' %
                                  (self._oDb.getRowCount(), ))

        dFiles = {}
        cbTotalFiles = 0
        for aoRow in self._oDb.fetchAll():
            dFiles[aoRow[0].lower()] = 1
            # For determining a unique filename further down.
            sFile = os.path.join(config.g_ksFileAreaRootDir,
                                 oTestSet.sBaseFilename + '-' + aoRow[0])
            try:
                cbTotalFiles += os.path.getsize(sFile)
            except:
                cbTotalFiles += config.g_kcMbMaxUploadSingle * 1048576
        if (cbTotalFiles + cbFile +
                1048575) / 1048576 > config.g_kcMbMaxUploadTotal:
            raise TMExceptionBase('Will exceed total upload limit: %u bytes + %u bytes > %s MiB.' \
                                  % (cbTotalFiles, cbFile, config.g_kcMbMaxUploadTotal))

        #
        # Create a new file.
        #
        self._oDb.execute('SELECT   idTestResult\n'
                          'FROM     TestResults\n'
                          'WHERE    idTestSet = %s\n'
                          '     AND enmStatus = \'running\'::TestStatus_T\n'
                          'ORDER BY idTestResult DESC\n'
                          'LIMIT    1\n' % (oTestSet.idTestSet, ))
        if self._oDb.getRowCount() < 1:
            raise TMExceptionBase(
                'No open test results - someone committed a capital offence or we ran into a race.'
            )
        idTestResult = self._oDb.fetchOne()[0]

        if sName.lower() in dFiles:
            # Note! There is in theory a race here, but that's something the
            #       test driver doing parallel upload with non-unique names
            #       should worry about. The TD should always avoid this path.
            sOrgName = sName
            for i in range(2, config.g_kcMaxUploads + 6):
                sName = '%s-%s' % (
                    i,
                    sName,
                )
                if sName not in dFiles:
                    break
                sName = None
            if sName is None:
                raise TMExceptionBase('Failed to find unique name for %s.' %
                                      (sOrgName, ))

        self._oDb.execute(
            'INSERT INTO TestResultFiles(idTestResult, idTestSet, idStrFile, idStrDescription,\n'
            '                            idStrKind, idStrMime)\n'
            'VALUES (%s, %s, %s, %s, %s, %s)\n', (
                idTestResult,
                oTestSet.idTestSet,
                self.strTabString(sName),
                self.strTabString(sDesc),
                self.strTabString(sKind),
                self.strTabString(sMime),
            ))

        oFile = oTestSet.createFile(sName, 'wb')
        if utils.isString(oFile):
            raise TMExceptionBase('Error creating "%s": %s' % (sName, oFile))
        self._oDb.maybeCommit(fCommit)
        return oFile
Example #26
0
    def createFile(self, oTestSet, sName, sMime, sKind, sDesc, cbFile, fCommit = False): # pylint: disable=R0914
        """
        Creates a file and associating with the current test result record in
        the test set.

        Returns file object that the file content can be written to.
        Raises exception on database error, I/O errors, if there are too many
        files in the test set or if they take up too much disk space.

        The caller (testboxdisp.py) is expected to do basic input validation,
        so we skip that and get on with the bits only we can do.
        """

        #
        # Furhter input and limit checks.
        #
        if oTestSet.enmStatus != TestSetData.ksTestStatus_Running:
            raise TMExceptionBase('Cannot create files on a test set with status "%s".' % (oTestSet.enmStatus,));

        self._oDb.execute('SELECT   TestResultStrTab.sValue\n'
                          'FROM     TestResultFiles,\n'
                          '         TestResults,\n'
                          '         TestResultStrTab\n'
                          'WHERE    TestResults.idTestSet        = %s\n'
                          '     AND TestResultFiles.idTestResult = TestResults.idTestResult\n'
                          '     AND TestResultStrTab.idStr       = TestResultFiles.idStrFile\n'
                          , ( oTestSet.idTestSet,));
        if self._oDb.getRowCount() + 1 > config.g_kcMaxUploads:
            raise TMExceptionBase('Uploaded too many files already (%d).' % (self._oDb.getRowCount(),));

        dFiles = {}
        cbTotalFiles = 0;
        for aoRow in self._oDb.fetchAll():
            dFiles[aoRow[0].lower()] = 1; # For determining a unique filename further down.
            sFile = os.path.join(config.g_ksFileAreaRootDir, oTestSet.sBaseFilename + '-' + aoRow[0]);
            try:
                cbTotalFiles += os.path.getsize(sFile);
            except:
                cbTotalFiles += config.g_kcMbMaxUploadSingle * 1048576;
        if (cbTotalFiles + cbFile + 1048575) / 1048576 > config.g_kcMbMaxUploadTotal:
            raise TMExceptionBase('Will exceed total upload limit: %u bytes + %u bytes > %s MiB.' \
                                  % (cbTotalFiles, cbFile, config.g_kcMbMaxUploadTotal));

        #
        # Create a new file.
        #
        self._oDb.execute('SELECT   idTestResult\n'
                          'FROM     TestResults\n'
                          'WHERE    idTestSet = %s\n'
                          '     AND enmStatus = \'running\'::TestStatus_T\n'
                          'ORDER BY idTestResult DESC\n'
                          'LIMIT    1\n'
                          % ( oTestSet.idTestSet, ));
        if self._oDb.getRowCount() < 1:
            raise TMExceptionBase('No open test results - someone committed a capital offence or we ran into a race.');
        idTestResult = self._oDb.fetchOne()[0];

        if sName.lower() in dFiles:
            # Note! There is in theory a race here, but that's something the
            #       test driver doing parallel upload with non-unique names
            #       should worry about. The TD should always avoid this path.
            sOrgName = sName;
            for i in range(2, config.g_kcMaxUploads + 6):
                sName = '%s-%s' % (i, sName,);
                if sName not in dFiles:
                    break;
                sName = None;
            if sName is None:
                raise TMExceptionBase('Failed to find unique name for %s.' % (sOrgName,));

        self._oDb.execute('INSERT INTO TestResultFiles(idTestResult, idTestSet, idStrFile, idStrDescription,\n'
                          '                            idStrKind, idStrMime)\n'
                          'VALUES (%s, %s, %s, %s, %s, %s)\n'
                          , ( idTestResult,
                              oTestSet.idTestSet,
                              self.strTabString(sName),
                              self.strTabString(sDesc),
                              self.strTabString(sKind),
                              self.strTabString(sMime),
                          ));

        oFile = oTestSet.createFile(sName, 'wb');
        if utils.isString(oFile):
            raise TMExceptionBase('Error creating "%s": %s' % (sName, oFile));
        self._oDb.maybeCommit(fCommit);
        return oFile;
Example #27
0
    def renderGraph(self):
        aoTable = self._oData.aoTable # type: WuiHlpGraphDataTable

        # Seems material (google.charts.Bar) cannot change the direction on the Y-axis,
        # so we cannot get bars growing downwards from the top like we want for the
        # reports.  The classic charts OTOH cannot put X-axis labels on the top, but
        # we just drop them all together instead, saving a little space.
        fUseMaterial = False;

        # Unique on load function.
        global g_cGraphs;
        iGraph = g_cGraphs;
        g_cGraphs += 1;

        sHtml  = '<div id="%s">\n' % ( self._sId, );
        sHtml += '<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>\n' \
                 '<script type="text/javascript">\n' \
                 'google.charts.load("current", { packages: ["corechart", "bar"] });\n' \
                 'google.setOnLoadCallback(tmDrawBarGraph%u);\n' \
                 'function tmDrawBarGraph%u()\n' \
                 '{\n' \
                 '    var oGraph;\n' \
                 '    var dGraphOptions = \n' \
                 '    {\n' \
                 '         "title":     "%s",\n' \
                 '         "hAxis": {\n' \
                 '             "title": "%s",\n' \
                 '         },\n' \
                 '         "vAxis": {\n' \
                 '             "direction": %s,\n' \
                 '         },\n' \
                % ( iGraph,
                    iGraph,
                    webutils.escapeAttrJavaScriptStringDQ(self._sTitle) if self._sTitle is not None else '',
                    webutils.escapeAttrJavaScriptStringDQ(aoTable[0].sName) if aoTable and aoTable[0].sName else '',
                    '-1' if self.fYInverted else '1',
                  );
        if fUseMaterial and self.fYInverted:
            sHtml +=  '        "axes": { "x": { 0: { "side": "top" } }, "y": { "0": { "direction": -1, }, }, },\n';
        sHtml += '    };\n';

        # The data.
        if self._oData.fHasStringValues and len(aoTable) > 1:
            sHtml += '    var oData = new google.visualization.DataTable();\n';
            # Column definitions.
            sHtml += '    oData.addColumn("string", "%s");\n' \
                   % (webutils.escapeAttrJavaScriptStringDQ(aoTable[0].sName) if aoTable[0].sName else '',);
            for iValue, oValue in enumerate(aoTable[0].aoValues):
                oSampleValue = aoTable[1].aoValues[iValue];
                if utils.isString(oSampleValue):
                    sHtml += '    oData.addColumn("string", "%s");\n' % (webutils.escapeAttrJavaScriptStringDQ(oValue),);
                else:
                    sHtml += '    oData.addColumn("number", "%s");\n' % (webutils.escapeAttrJavaScriptStringDQ(oValue),);
                sHtml += '    oData.addColumn({type: "string", role: "annotation"});\n';
            # The data rows.
            sHtml += '    oData.addRows([\n';
            for oRow in aoTable[1:]:
                if oRow.sName:
                    sRow = '        [ "%s"' % (webutils.escapeAttrJavaScriptStringDQ(oRow.sName),);
                else:
                    sRow = '        [ null';
                for iValue, oValue in enumerate(oRow.aoValues):
                    if not utils.isString(oValue):
                        sRow += ', %s' % (oValue,);
                    else:
                        sRow += ', "%s"' % (webutils.escapeAttrJavaScriptStringDQ(oValue),);
                    if oRow.asValues[iValue]:
                        sRow += ', "%s"' % (webutils.escapeAttrJavaScriptStringDQ(oRow.asValues[iValue]),);
                    else:
                        sRow += ', null';
                sHtml += sRow + '],\n';
            sHtml += '    ]);\n';
        else:
            sHtml += '    var oData = google.visualization.arrayToDataTable([\n';
            for oRow in aoTable:
                sRow = '        [ "%s"' % (webutils.escapeAttrJavaScriptStringDQ(oRow.sName),);
                for oValue in oRow.aoValues:
                    if utils.isString(oValue):
                        sRow += ', "%s"' % (webutils.escapeAttrJavaScriptStringDQ(oValue),);
                    else:
                        sRow += ', %s' % (oValue,);
                sHtml += sRow + '],\n';
            sHtml += '    ]);\n';

        # Create and draw.
        if not fUseMaterial:
            sHtml += '    oGraph = new google.visualization.ColumnChart(document.getElementById("%s"));\n' \
                     '    oGraph.draw(oData, dGraphOptions);\n' \
                   % ( self._sId, );
        else:
            sHtml += '    oGraph = new google.charts.Bar(document.getElementById("%s"));\n' \
                     '    oGraph.draw(oData, google.charts.Bar.convertOptions(dGraphOptions));\n' \
                   % ( self._sId, );

        # clean and return.
        sHtml += '    oData = null;\n' \
                 '    return true;\n' \
                 '};\n';

        sHtml += '</script>\n' \
                 '</div>\n';
        return sHtml;