Example #1
0
def _checkDbInfo(testSuiteObj, testName, dbConObj, diskId):
    """
    Dump the information in ngas_disks, ngas_files and ngas_files_retired in
    connection with the disk and compare the results to reference dumps.

    testSuiteObj:   Test suite object (ngamsTestSuite)

    testName:       Name of the test case (string).

    dbConObj:       DB connection object (ngamsDb).

    diskId:         ID of disk to retire (string).

    Returns:        Void.
    """
    # ngas_disks:
    tmpDiskInfo = ngamsDiskInfo.ngamsDiskInfo().read(dbConObj, diskId)
    diskInfoBuf = filterOutLines(
        tmpDiskInfo.dumpBuf(),
        ["InstallationDate:", "AvailableMb:", "TotalDiskWriteTime:"])
    refStatFile = "ref/ngasRetireDisk_%s_1" % testName
    tmpStatFile = saveInFile(None, diskInfoBuf)
    testSuiteObj.checkFilesEq(refStatFile, tmpStatFile,
                              "Incorrect/missing info in ngas_disks")

    # ngas_files:
    query = "SELECT %s FROM ngas_files nf WHERE disk_id='%s'" %\
            (ngamsDb._ngasFilesCols, diskId)
    curObj = dbConObj.dbCursor(query)
    fileInfoBuf = ""
    while (1):
        res = curObj.fetch(1)
        if (res == []): break
        tmpFileInfo = ngamsFileInfo.ngamsFileInfo().unpackSqlResult(res[0])
        fileInfoBuf += filterOutLines(
            tmpFileInfo.dumpBuf(), ["IngestionDate:", "CreationDate:"]) + "\n"
    refStatFile = "ref/ngasRetireDisk_%s_2" % testName
    tmpStatFile = saveInFile(None, fileInfoBuf)
    testSuiteObj.checkFilesEq(refStatFile, tmpStatFile,
                              "Incorrect/missing info in ngas_files")

    # ngas_files_retired:
    query = "SELECT %s FROM ngas_files_retired nf WHERE disk_id='%s'" %\
            (ngamsDb._ngasFilesCols, diskId)
    curObj = dbConObj.dbCursor(query)
    fileInfoBuf = ""
    while (1):
        res = curObj.fetch(1)
        if (res == []): break
        tmpFileInfo = ngamsFileInfo.ngamsFileInfo().unpackSqlResult(res[0])
        fileInfoBuf += filterOutLines(
            tmpFileInfo.dumpBuf(), ["IngestionDate:", "CreationDate:"]) + "\n"
    refStatFile = "ref/ngasRetireDisk_%s_3" % testName
    tmpStatFile = saveInFile(None, fileInfoBuf)
    testSuiteObj.checkFilesEq(refStatFile, tmpStatFile,
                              "Incorrect/missing info in ngas_files")
Example #2
0
    def getFileInfoFromDiskIdFilename(self, diskId, filename):
        """
        The method queries the file information for a file referred to by the
        Disk ID for the disk hosting it and the filename as stored in the
        NGAS DB.

        diskId:      ID for disk hosting the file (string).

        filename:    NGAS (relative) filename (string).

        Returns:     Return ngamsFileInfo object with the information for the
                     file if found or None if the file was not found
                     (ngamsFileInfo|None).
        """
        T = TRACE()

        # Query for the file.
        sql = "SELECT %s FROM ngas_files nf WHERE nf.disk_id={0} AND nf.file_name={1}"
        sql = sql % (ngamsDbCore.getNgasFilesCols(
            self._file_ignore_columnname), )

        # Execute the query directly and return the result.
        res = self.query2(sql, args=(diskId, filename))
        if res:
            return ngamsFileInfo.ngamsFileInfo().unpackSqlResult(res[0])
        else:
            return None
Example #3
0
    def readHierarchy(self, containerId, includeFiles=False):
        """
        Reads an ngamsContainer object from the database
        and recursively populates it with its children containers.

        :param containerId: string
        :return ngamsContainer.ngamsContainer
        """

        container = self.read(containerId)
        if includeFiles:

            # Always get the latest version of the files
            # We do this on the software side to avoid any complex SQL query
            # that might not work in some engines
            sql = "SELECT %s FROM ngas_files nf WHERE container_id = {0} ORDER BY nf.file_id, nf.file_version DESC"
            sql = sql % (ngamsDbCore.getNgasFilesCols(self._file_ignore_columnname),)
            res = self.query2(sql, args=(containerId,))
            prevFileId = None
            for r in res:
                fileId = r[ngamsDbCore.NGAS_FILES_FILE_ID]
                if fileId == prevFileId:
                    continue
                prevFileId = fileId
                fileInfo = ngamsFileInfo.ngamsFileInfo().unpackSqlResult(r)
                container.addFileInfo(fileInfo)

        # Check if it contains children
        res = self.query2("SELECT container_id FROM ngas_containers WHERE parent_container_id = {0}", args=(containerId,))
        for r in res:
            container.addContainer(self.readHierarchy(r[0], includeFiles))
        return container
Example #4
0
    def unpackFromDomNode(self,
                          fileListNode):
        """
        Unpack a File List from a DOM File List Node object.

        fileListNode:   DOM File List Node object (Node).

        Returns:        Reference to object itself.
        """
        self.setId(getAttribValue(fileListNode, "Id"))
        self.setComment(getAttribValue(fileListNode, "Comment", 1))
        self.setStatus(getAttribValue(fileListNode, "Status", 1))

        # Unpack the File Status Elements.
        fileStatusNodes = ngamsGetChildNodes(fileListNode, "FileStatus")
        for fileStatusNode in fileStatusNodes:
            fileStatusObj = ngamsFileInfo.ngamsFileInfo()
            self.addFileInfoObj(fileStatusObj)
            fileStatusObj.unpackFromDomNode(fileStatusNode)

        # Unpack File List Elements.
        fileListNodes = ngamsGetChildNodes(fileListNode, "FileList")
        for fileListNode in fileListNodes:
            fileListObj = ngamsFileList()
            self.addFileListObj(fileListObj)
            fileListObj.unpackFromDomNode(fileListNode)

        return self
Example #5
0
    def unpackFromDomNode(self, contEl):
        """
        Unpacks the contents of the given DOM Element
        and populates this ngamsContainer object with
        them. This method also recursively traverses
        any children elements containing information
        about child containers and files.

        :param contEl: xml.dom.minidom.Element
        """

        self.setContainerId(contEl.getAttribute('id'))
        self.setContainerName(contEl.getAttribute('name'))
        self.setContainerSize(int(contEl.getAttribute('size')))

        ingDate = contEl.getAttribute('ingestionDate')
        self.setIngestionDate(fromiso8601(ingDate) if ingDate else None)

        subContEls = [n for n in contEl.childNodes \
                      if n.nodeType == minidom.Node.ELEMENT_NODE
                      and n.tagName == 'Container']
        fileEls    = [n for n in contEl.childNodes \
                      if n.nodeType == minidom.Node.ELEMENT_NODE
                      and n.tagName == 'FileStatus']

        for subContEl in subContEls:
            childContainer = ngamsContainer()
            childContainer.unpackFromDomNode(subContEl)
            self.addContainer(childContainer)
        for fileEl in fileEls:
            fileInfo = ngamsFileInfo.ngamsFileInfo()
            fileInfo.unpackFromDomNode(fileEl)
            self.addFileInfo(fileInfo)
Example #6
0
    def unpackFromDomNode(self, diskNode, ignoreVarDiskPars=0):
        """
        Unpack the disk information contained in a DOM DiskStatus
        Node and set the members of the object accordingly.

        diskNode:           DOM Disk Node (Node).

        ignoreVarDiskPars:  Ignore the variable part of the disk status:
                            Host ID, Slot ID, Mounted, Mount
                            Point (integer/0|1).

        Returns:            Reference to object itself.
        """
        T = TRACE()

        self.setDiskId(getAttribValue(diskNode, "DiskId"))
        self.setArchive(getAttribValue(diskNode, "Archive"))

        instDate = getAttribValue(diskNode, "InstallationDate")
        if instDate:
            self.setInstallationDate(fromiso8601(instDate))

        self.setType(getAttribValue(diskNode, "Type"))
        self.setManufacturer(getAttribValue(diskNode, "Manufacturer", 1))
        self.setLogicalName(getAttribValue(diskNode, "LogicalName"))

        # These attributes are not contained in certain Status XML
        # Documents, e.g. in the NgasDiskInfo files.
        if (not ignoreVarDiskPars):
            self.setHostId(getAttribValue(diskNode, "HostId"))
            self.setSlotId(getAttribValue(diskNode, "SlotId"))
            self.setMounted(getAttribValue(diskNode, "Mounted"))
            self.setMountPoint(getAttribValue(diskNode, "MountPoint"))

        self.setNumberOfFiles(getAttribValue(diskNode, "NumberOfFiles"))
        self.setAvailableMb(getAttribValue(diskNode, "AvailableMb"))
        self.setBytesStored(getAttribValue(diskNode, "BytesStored"))
        self.setCompleted(getAttribValue(diskNode, "Completed"))

        compDate = getAttribValue(diskNode, "CompletionDate", 1)
        if compDate:
            self.setCompletionDate(fromiso8601(compDate))

        self.setChecksum(getAttribValue(diskNode, "Checksum"))
        write_time = getAttribValue(diskNode, "TotalDiskWriteTime")
        if write_time:
            self.setTotalDiskWriteTime(float(write_time))

        # Handle files.
        fileNodes = diskNode.getElementsByTagName("FileStatus")
        for fileNode in fileNodes:
            fileInfo = ngamsFileInfo.ngamsFileInfo().\
                       unpackFromDomNode(fileNode, self.getDiskId())
            self.addFileObj(fileInfo)

        return self
Example #7
0
def cloneCheckFile(diskId, fileId, fileVersion, dbConObj, pClientObj,
                   checkRep):
    """
    Clone a file a check afterwards if it was successfully cloned.

    diskId:       ID of disk cloned (string).

    fileId:       ID of file cloned (string).

    fileVersion:  Version of file to check (integer).

    dbConObj:     DB Connection Object (ngamsDb).

    pClientObj:   Initiated instance of NG/AMS P-Client Object (ngamsPClient).

    checkRep:     Check report (string).

    Returns:      Updated Check Report (string).
    """
    msg = "\n-> Attempting to clone file: %s/%s/%s" %\
          (diskId, fileId, fileVersion)
    print msg
    msg += " - status: "
    res = pClientObj.clone(fileId, diskId, fileVersion, wait=1)
    if (res.getStatus() == "FAILURE"):
        status = "FAILURE: " + str(res.getMessage()) + "\n"
    else:
        # Check if file was really cloned.
        res = dbConObj.getFileInfoFromFileIdHostId(_getTargHost(), fileId,
                                                   fileVersion)
        if (res == []):
            status = "FAILURE: File not cloned!\n"
        else:
            fileInfo = ngamsFileInfo.ngamsFileInfo().\
                       unpackSqlResult(res)
            tmpPars = [["disk_id", fileInfo.getDiskId()], ["file_id", fileId],
                       ["file_version", fileVersion]]
            res = pClientObj.sendCmdGen(getHostName(),
                                        pClientObj.getPort(),
                                        NGAMS_CHECKFILE_CMD,
                                        wait=1,
                                        pars=tmpPars)
            status = res.getMessage() + "\n"
    return msg + status
Example #8
0
    def setFileChecksum(self, hostId, fileId, fileVersion, diskId, checksum,
                        checksumPlugIn):
        """
        Set the checksum value in the ngas_files table.

        hostId:          ID of this NGAS host

        fileId:          ID of file (string).

        fileVersion:     Version of file (integer).

        diskId:          ID of disk where file is stored (string).

        checksum:        Checksum of file (string).

        checksumPlugIn:  Name of plug-in used to generate the
                         checksum (string).

        Returns:         Reference to object itself.
        """
        T = TRACE()

        sql = ("UPDATE ngas_files SET checksum={}, checksum_plugin={}"
               " WHERE file_id={} AND file_version={} AND disk_id={}")
        vals = (checksum, checksumPlugIn, fileId, fileVersion, diskId)
        self.query2(sql, args=vals)

        # Create a File Removal Status Document.
        if (self.getCreateDbSnapshot()):
            dbFileInfo = self.getFileInfoFromFileIdHostId(
                hostId, fileId, fileVersion, diskId)
            tmpFileObj = ngamsFileInfo.ngamsFileInfo().\
                         unpackSqlResult(dbFileInfo)
            self.createDbFileChangeStatusDoc(hostId, NGAMS_DB_CH_FILE_UPDATE,
                                             [tmpFileObj])

        self.triggerEvents()
        return self
Example #9
0
def _scanDir(srcDir, recursive, fileExtList):
    """
    Scan the given directory file for files. If diretories are found in the
    directory, these are returned in a list.

    srcDir:         Directory to scan for matching files (string).

    recursive:      Traverse the directory tree recursively (integer/0|1).

    fileExtList:    List with extensions to take into account (list).

    Returns:        List with ngamsFileInfo objects for matching files (list).
    """
    info(4, "Entering _scanDir() ...")
    srcDir = os.path.expanduser(srcDir)
    info(2, "Scanning directory: %s ..." % srcDir)
    fileInfoList = []
    fileList = glob.glob(os.path.normpath("%s/*" % srcDir))
    for file in fileList:
        file = file.strip()
        if (os.path.isdir(file) and recursive):
            fileInfoList += _scanDir(file, recursive, fileExtList)
        else:
            # Extension matching?
            for ext in fileExtList:
                if ((file.find("." + ext) + len("." + ext)) == len(file)):
                    # The extension matches. Get the info for the file.
                    statInfo = os.stat(file)
                    tmpFileObj = ngamsFileInfo.ngamsFileInfo().\
                                 setFilename(file).\
                                 setAccDateFromSecs(statInfo[7]).\
                                 setModDateFromSecs(statInfo[8]).\
                                 setCreationDate(statInfo[9]).\
                                 setFileSize(statInfo[6])
                    fileInfoList.append(tmpFileObj)
                    break
    info(4, "Leaving _scanDir()")
    return fileInfoList
Example #10
0
    def deleteFileInfo(self,
                       hostId,
                       diskId,
                       fileId,
                       fileVersion,
                       genSnapshot=1):
        """
        Delete one record for a certain file in the NGAS DB.

        CAUTION:  IF THE DB USER WITH WHICH THERE IS LOGGED IN HAS PERMISSION
                  TO EXECUTE DELETE STATEMENTS, THE INFORMATION ABOUT THE
                  FILE(S) IN THE NGAS DB WILL BE DELETED! THIS INFORMATION
                  CANNOT BE RECOVERED!!

        diskId:         ID of disk hosting the file (string).

        fileId:         ID of file to be deleted. No wildcards accepted
                        (string).

        fileVersion:    Version of file to delete (integer)

        genSnapshot:    Generate Db Snapshot (integer/0|1).

        Returns:        Reference to object itself.
        """
        T = TRACE()

        # We have to update some fields of the disk hosting the file
        # when we delete a file (number_of_files, available_mb,
        # bytes_stored, also maybe later: checksum.
        dbDiskInfo = self.getDiskInfoFromDiskId(diskId)

        # getFileInfoList returns a generator, so we iterate once to get the first element
        try:
            dbFileInfo = next(self.getFileInfoList(diskId, fileId,
                                                   fileVersion))
        except StopIteration:
            msg = "Cannot remove file. File ID: %s, " +\
                  "File Version: %d, Disk ID: %s"
            errMsg = msg % (fileId, fileVersion, diskId)
            raise Exception, errMsg

        sql = "DELETE FROM ngas_files WHERE disk_id={0} AND file_id={1} AND file_version={2}"
        self.query2(sql, args=(diskId, fileId, fileVersion))

        # Create a File Removal Status Document.
        if (self.getCreateDbSnapshot() and genSnapshot):
            tmpFileObj = ngamsFileInfo.ngamsFileInfo().\
                         unpackSqlResult(dbFileInfo)
            self.createDbFileChangeStatusDoc(hostId, NGAMS_DB_CH_FILE_DELETE,
                                             [tmpFileObj])

        # Now update the ngas_disks entry for the disk hosting the file.
        if (dbDiskInfo):
            newNumberOfFiles = (dbDiskInfo[ngamsDbCore.\
                                           NGAS_DISKS_NO_OF_FILES] - 1)
            if (newNumberOfFiles < 0): newNumberOfFiles = 0
            newAvailMb = (dbDiskInfo[ngamsDbCore.NGAS_DISKS_AVAIL_MB] +
                          int(float(dbFileInfo[ngamsDbCore.\
                                               NGAS_FILES_FILE_SIZE])/1e6))
            newBytesStored = (dbDiskInfo[ngamsDbCore.\
                                         NGAS_DISKS_BYTES_STORED] -
                              dbFileInfo[ngamsDbCore.NGAS_FILES_FILE_SIZE])
            if (newBytesStored < 0): newBytesStored = 0
            sql = "UPDATE ngas_disks SET number_of_files={0}, " +\
                  "available_mb={1}, bytes_stored={2} WHERE disk_id={3}"
            self.query2(sql,
                        args=(newNumberOfFiles, newAvailMb, newBytesStored,
                              diskId))

        self.triggerEvents()
        return self
Example #11
0
    def deleteDiskInfo(self, diskId, delFileInfo=1):
        """
        Delete a record for a certain disk in the NGAS DB.

        CAUTION:  IF THE DB USER WITH WHICH THERE IS LOGGED IN HAS PERMISSION
                  TO EXECUTE DELETE STATEMENTS, THE INFORMATION ABOUT THE
                  DISK IN THE NGAS DB WILL BE DELETED! THIS INFORMATION
                  CANNOT BE RECOVERED!!

        diskId:        ID of disk for which to delete the entry (string).

        delFileInfo:   If set to 1, the file information for the files
                       stored on the disk is deleted as well (integer/0|1).

        Returns:       Reference to object itself.
        """
        T = TRACE()

        fileInfoDbmName = None
        fileInfoDbm = None
        try:

            # Get the information about the files on the disk (before this
            # information is deleted).
            if delFileInfo and self.getCreateDbSnapshot():
                diskInfo = ngamsDiskInfo.ngamsDiskInfo().read(self, diskId)
                fileInfoDbmName = self.genTmpFile('DISK_INFO')
                fileInfoDbm = ngamsDbm.ngamsDbm(fileInfoDbmName,
                                                cleanUpOnDestr=0,
                                                writePerm=1)
                fileCount = 0
                for fileInfo in self.getFileInfoList(diskId, fetch_size=1000):
                    fileInfoDbm.add(str(fileCount), fileInfo)
                    fileCount += 1
                fileInfoDbm.sync()

            # Delete the disk info.
            sql = "DELETE FROM ngas_disks WHERE disk_id={}"
            self.query2(sql, args=(diskId, ))

            # Delete file info if requested.
            if delFileInfo:
                sql = "DELETE FROM ngas_files WHERE disk_id={}"
                self.query2(sql, args=(diskId, ))

                # Create a File Removal Status Document.
                if (self.getCreateDbSnapshot()):
                    op = NGAMS_DB_CH_FILE_DELETE
                    fileInfoDbm.initKeyPtr()
                    key, fileSqlInfo = fileInfoDbm.getNext()
                    while (key):
                        tmpFileObj = ngamsFileInfo.ngamsFileInfo().\
                                     unpackSqlResult(fileSqlInfo)
                        self.createDbRemFileChangeStatusDoc(
                            diskInfo, tmpFileObj)

                        key, fileSqlInfo = fileInfoDbm.getNext()

                    self.triggerEvents(
                        [diskInfo.getDiskId(),
                         diskInfo.getMountPoint()])

            return self
        except Exception:
            logger.exception("Error deleting disk info from DB")
            raise
        finally:
            if fileInfoDbm:
                del fileInfoDbm
            if fileInfoDbmName:
                rmFile(fileInfoDbmName)
Example #12
0
    def writeFileEntry(self,
                       hostId,
                       diskId,
                       filename,
                       fileId,
                       fileVersion,
                       format,
                       fileSize,
                       uncompressedFileSize,
                       compression,
                       ingestionDate,
                       ignore,
                       checksum,
                       checksumPlugIn,
                       fileStatus,
                       creationDate,
                       iotime,
                       ingestionRate,
                       genSnapshot=1,
                       updateDiskInfo=0):
        """
        The method writes the information in connection with a file in the
        NGAS DB. If an entry already exists for that file, it is updated
        with the information contained in the File Info Object. Otherwise,
        a new entry is created.

        diskId           Values for the columns in the ngas_disks
        ...              table (use values returned from ngamsFileInfo).

        genSnapshot:     Generate a snapshot file (integer/0|1).

        updateDiskInfo:  Update automatically the disk info for the
                         disk hosting this file (integer/0|1).

        Returns:         Void.
        """
        T = TRACE(5)

        # Check if the entry already exists. If yes update it, otherwise
        # insert a new element.
        if ignore == -1:
            ignore = 0

        checksum = str(checksum) if checksum else None
        ingDate = self.convertTimeStamp(ingestionDate)
        creDate = self.convertTimeStamp(creationDate)

        sql = []
        vals = []
        sql_str = None

        if (self.fileInDb(diskId, fileId, fileVersion)):
            # We only allow to modify a limited set of columns.
            sql.append(("UPDATE ngas_files SET "
                        "file_name={}, format={}, file_size={}, "
                        "uncompressed_file_size={}, compression={}, "
                        "%s={}, checksum={}, checksum_plugin={}, "
                        "file_status={}, creation_date={}, io_time={}, "
                        "ingestion_rate={} WHERE file_id={} AND disk_id={}" %
                        (self._file_ignore_columnname, )))
            vals = [filename, format, fileSize, uncompressedFileSize, compression,\
                    ignore, checksum, checksumPlugIn, fileStatus, creDate,\
                    int(iotime*1000), ingestionRate, fileId, diskId]

            if int(fileVersion) != -1:
                sql.append(" AND file_version={}")
                vals.append(fileVersion)

            dbOperation = NGAMS_DB_CH_FILE_UPDATE
            sql_str = ''.join(sql)
        else:
            sql_str = (
                "INSERT INTO ngas_files (disk_id, file_name, file_id,"
                "file_version, format, file_size, uncompressed_file_size,"
                " compression, ingestion_date, %s, checksum, "
                "checksum_plugin, file_status, creation_date, io_time, "
                "ingestion_rate) VALUES ({}, {}, {}, {}, {}, {}, {}, {},"
                " {}, {}, {},{}, {}, {}, {}, {})" %
                (self._file_ignore_columnname, ))
            vals = (diskId, filename, fileId, fileVersion, format, fileSize,\
                    uncompressedFileSize, compression, ingDate, ignore,\
                    checksum, checksumPlugIn, fileStatus, creDate,\
                    int(iotime*1000), ingestionRate)
            dbOperation = NGAMS_DB_CH_FILE_INSERT

        self.query2(sql_str, args=vals)

        # Update the Disk Info of the disk concerned if requested and
        # if a new entry was added.
        #
        # Note: In case of an update the columns ngas_disks.avail_mb
        #       and ngas_disks.bytes_stored should in principle be
        #       updated according to the actual size of the new
        #       version of the file.
        #print "writeFileEntry".upper(), updateDiskInfo, dbOperation
        if (updateDiskInfo and (dbOperation == NGAMS_DB_CH_FILE_INSERT)):
            self.updateDiskFileStatus(diskId, fileSize)

        # Create a Temporary DB Change Snapshot Document if requested.
        if (self.getCreateDbSnapshot() and genSnapshot):
            tmpFileObj = ngamsFileInfo.ngamsFileInfo().\
                            setDiskId(diskId).setFilename(filename).setFileId(fileId).\
                            setFileVersion(fileVersion).setFormat(format).setFileSize(fileSize).\
                            setUncompressedFileSize(uncompressedFileSize).setCompression(compression).\
                            setIngestionDate(ingestionDate).setIgnore(ignore).setChecksum(checksum).\
                            setChecksumPlugIn(checksumPlugIn).setFileStatus(fileStatus).setCreationDate(creationDate).\
                            setIoTime(iotime).setIngestionRate(ingestionRate)
            self.createDbFileChangeStatusDoc(hostId, dbOperation, [tmpFileObj])
            del tmpFileObj

        self.triggerEvents([diskId, None])
Example #13
0
 def startFile(self, filename):
     MIMEMultipartHandler.startFile(self, filename)
     logger.debug('Found file: %s', filename)
     fileInfo = ngamsFileInfo.ngamsFileInfo()
     fileInfo.setFileId(filename)
     self._container.addFileInfo(fileInfo)