Ejemplo n.º 1
0
    def test_ArchiveCmd_Err_1(self):
        """
        Synopsis:
        Issue ARCHIVE Command/request times out.

        Description:
        The purpose of the test is to check that a request that times out
        is handled properly by the C-Client/API and a proper error message
        is produced.

        Expected Result:
        After the given timeout, the C-Client/API should generate a timeout
        error message.

        Test Steps:
        - Start speciel instance of server where Archive Requests blocks.
        - Issue Archive Request (small file) specifying a timeout of 10s.
        - Capture the output from the ngamsCClient, filter this, and
          check that the proper error message has been generated.

        Remarks:
        ...
        """
        rmFile("tmp/reqCallBack_tmp")
        saveInFile("tmp/reqCallBack_tmp", "reqCallBack_BlockCmds1")
        self.prepExtSrv(srvModule="ngamsSrvTestDynReqCallBack")
        out = _execCClient(unpackXmlStat=0,
                           pars=[["-port", "8888"], ["-cmd", "ARCHIVE"],
                                 ["-fileUri", "src/SmallFile.fits"],
                                 ["-timeOut", "5"]])
        tmpStatFile = saveInFile(None, filterOutLines(out, ["Host"]))
        refStatFile = "ref/ngamsCClientTest_test_ArchiveCmd_Err_1_ref"
        self.checkFilesEq(refStatFile, tmpStatFile, "Incorrect handling " +\
                          "of timeout of Archive Request in C-Client/API")
Ejemplo n.º 2
0
    def test_ArchiveCmd_Err_4_1(self):
        """
        Synopsis:
        Correct HTTP response, but illegal NG/AMS XML status document.

        Description:
        The purpose of the test is to verify that the C-Client/API handles
        correctly the situation where an incorrectly formatted XML status
        response is contained in the response from the server and the
        proper error code generated by the C-API.

        Expected Result:
        The C-API detects the wrongly formatted NG/AMS XML status document,
        and produces the appropriate error code.

        Test Steps:
        - Start special instance of the server which generates an HTTP
          response with a corrupt XML NG/AMS status document.
        - Issue an Archive Request via the ngamsCClient.
        - Compare the output from ngamsCClient to check that the invalid
          response was correctly handled.

        Remarks:
        ...
        """

        # TODO: From V4.0, this test case produces the error:
        #
        #  Error Code:     -103
        #  Message:        Invalid reply from data server
        #
        # - and not:
        #
        # Error Code:     -4
        # Message:        Problem communicating with server
        # Status:         FAILURE
        #
        # - as for previous version.
        #
        # This should be investigated and resolved.

        rmFile("tmp/reqCallBack_tmp")
        saveInFile("tmp/reqCallBack_tmp", "reqCallBack_IllegalResp")
        self.prepExtSrv(srvModule="ngamsSrvTestDynReqCallBack")
        httpResp = "HTTP/1.0 200 OK\015\012" +\
                   "Server: NGAMS/v2.3/2004-07-12T11:39:39\015\012" +\
                   "Date: Thu, 7 Oct 2004 16:20:28 GMT\015\012" +\
                   "Expires: Thu, 7 Oct 2004 16:20:28 GMT\015\012" +\
                   "Content-Type: text/xml\015\012" +\
                   "Content-Length: 36\015\012" +\
                   "\015\012" +\
                   "COMPLETELY CORRUPT NG/AMS XML STATUS"
        saveInFile("tmp/ngamsServerTestIllegalResp_tmp", httpResp)
        out = _execCClient(unpackXmlStat=0,
                           pars=[["-port", "8888"], ["-cmd", "ARCHIVE"],
                                 ["-fileUri", "src/SmallFile.fits"]])
        tmpStatFile = saveInFile(None, filterOutLines(out, ["Host"]))
        refStatFile = "ref/ngamsCClientTest_test_ArchiveCmd_Err_4_1_ref"
        self.checkFilesEq(refStatFile, tmpStatFile, "Incorrect handling " +\
                          "of corrupt server HTTP response in C-Client/API")
Ejemplo n.º 3
0
def remDisk(srvObj, reqPropsObj, diskId, execute):
    """
    Select a disk for removal and remove the information if so specified
    from the NGAS DB and delete all information on the disk.

    srvObj:         Reference to NG/AMS server class object (ngamsServer).

    reqPropsObj:    Request Property object to keep track of actions done
                    during the request handling (ngamsReqProps).

    diskId:         ID of disk. Complete ID must be specified. I.e., no
                    wildcards are handled (string).

    execute:        If set to 1 the information about the disk will be deleted.
                    Otherwise only the information about the disk selected for
                    deletion will be queried (integer/0|1).

    Returns:        Status object contained information about disk
                    selected for deletion/deleted (ngamsStatus).
    """
    tmpFilePat = ngamsHighLevelLib.genTmpFilename(srvObj.getCfg(),
                                                  "REMDISK_CMD")
    try:
        status = _remDisk(srvObj, reqPropsObj, diskId, execute, tmpFilePat)
        return status
    finally:
        rmFile(tmpFilePat + "*")
Ejemplo n.º 4
0
def checkTarball(filename):
    """
    Check that the tarball is correct

    filename:  Name of tarball file (string).

    Returns:   Void.
    """
    err = 0
    tmpFilename = filename.replace(":", "_") + "_tmp"
    try:
        execCmd("ln -s " + filename + " " + tmpFilename)
        stat, out, _ = execCmd("tar -tf " + tmpFilename)
        rmFile(tmpFilename)
        if (stat != 0):
            errMsg = str(out).replace("\n", " --- ")
            err = 1
    except Exception as e:
        rmFile(tmpFilename)
        errMsg = str(e)
        err = 1
    if (err):
        errMsg = "Error checking tarball: " + errMsg
        errMsg = genLog("NGAMS_ER_DAPI_BAD_FILE",
                        [filename, "ngasTarBallPlugIn", errMsg])
        raise Exception(errMsg)
Ejemplo n.º 5
0
def retrieveFiles(diskIdList):
    """
    Retrieve all files associated to a list of Disk IDs.

    diskIdList:   List of Disk IDs (list).

    Returns:      Void.
    """
    dbCon = ngamsDb.ngamsDb("ESOECF", "ngas", "ngas", "bmdhc19wdw==")
    client = ngamsPClient.ngamsPClient("jewel1", 7777)
    for diskId in diskIdList:
        dbCur = dbCon.getFileInfoList("IBM-DTLA-307075-YSDYSG3X871")
        while (1):
            fileList = dbCur.fetch(100)
            if (not fileList): break
            for fileInfo in fileList:
                fileId = fileInfo[ngamsDb.NGAS_FILES_FILE_ID]
                fileVersion = fileInfo[ngamsDb.NGAS_FILES_FILE_VER]
                print "Retrieving file with File ID/Version: %s/%d" %\
                      (fileId, fileVersion)
                startTime = time.time()
                res = client.retrieve(fileId, fileVersion,"/tmp/TestFile")
                deltaTime = (time.time() - startTime)
                if (res.getStatus() == NGAMS_SUCCESS):
                    format = "  - Successfully retrieved file with " +\
                             "File ID/Version: %s/%d/Time: %.3fs"
                    print format % (fileId, fileVersion, deltaTime)
                else:
                    format = "  - ERROR retrieving file with " +\
                             "File ID/Version: %s/%d: %s/Time: %.3fs"
                    print format % (fileId, fileVersion,
                                    str(res.getMessage()).replace("\n", " - "),
                                    deltaTime)
                rmFile("/tmp/TestFile")
Ejemplo n.º 6
0
def _delFile(srvObj, path, hostId, execute):
    """
    Delete (remove from disk) the file specified by the path on the given host.

    srvObj:        Reference to NG/AMS server class object (ngamsServer).

    path:          Path of file (string).

    hostId:        ID of host where file is stored (string).

    Returns:       Message with info about the execution (string).
    """
    if (hostId and (hostId != srvObj.getHostId())):
        raise Exception, "DISCARD Command can only be executed locally!"

    # Handle the discard request locally.
    ngasHostId = "%s:%d" % (getHostName(), srvObj.getCfg().getPortNo())
    if (os.path.exists(path)):
        if (not ngamsLib.fileRemovable(path)):
            return genLog("NGAMS_ER_DISCARD_NOT_REM", [path, ngasHostId])
        if (not execute):
            msg = genLog("NGAMS_INFO_DISCARD_GRANTED", [path, ngasHostId])
        else:
            rmFile(path)
            if (os.path.exists(path)):
                return genLog("NGAMS_ER_DISCARD_FAILED",
                              [path, ngasHostId, "Not removable"])
            else:
                msg = genLog("NGAMS_INFO_DISCARD_OK", [path, ngasHostId])
    else:
        return genLog("NGAMS_ER_DISCARD_NOT_FOUND", [path, ngasHostId])

    return msg
Ejemplo n.º 7
0
def _handleFileList(srvObj, reqPropsObj, httpRef):
    """
    Handle STATUS?file_list... Command.

    srvObj:         Reference to NG/AMS server class object (ngamsServer).

    reqPropsObj:    Request Property object to keep track of actions done
                    during the request handling (ngamsReqProps).

    httpRef:        Reference to the HTTP request handler
                    object (ngamsHttpRequestHandler).

    Returns:        The File List ID allocated for this request (string).
    """
    T = TRACE()

    # Should a lower limit for the ingestion date be taken into account.
    fromIngDate = None
    if (reqPropsObj.hasHttpPar("from_ingestion_date")):
        tmpTromIngDate = reqPropsObj.getHttpPar("from_ingestion_date")
        fromIngDate = fromiso8601(tmpTromIngDate)

    # Handle the unique flag. If this is specified, only information for unique
    # File ID/Version pairs are returned.
    unique = False
    if (reqPropsObj.hasHttpPar("unique")):
        unique = int(reqPropsObj.getHttpPar("unique"))

    # Dump the file information needed.
    fileListId = genUniqueId()
    dbmBaseName = STATUS_FILE_LIST_DBM_TAG % fileListId
    fileInfoDbmName = ngamsHighLevelLib.genTmpFilename(srvObj.getCfg(),
                                                       dbmBaseName)

    # Dump the file info from the DB. Deal with uniqueness quickly
    # (instead of using a new file like before)
    try:
        fileInfoDbm = ngamsDbm.ngamsDbm(fileInfoDbmName, 0, 1)
        fileCount = 1
        unique_files = set()
        for f in srvObj.db.files_in_host(srvObj.getHostId(),
                                         from_date=fromIngDate):
            if unique:
                key = str('%s_%d' % (f[2], f[3]))
                if key in unique_files:
                    continue
            else:
                key = str(fileCount)
            fileInfoDbm.add(key, f)
            fileCount += 1

    except Exception as e:
        rmFile(fileInfoDbmName)
        msg = "Problem generating file list for STATUS Command. " +\
              "Parameters: from_ingestion_date=%s. Error: %s" %\
              (str(fromIngDate), str(e))
        raise Exception(msg)

    return fileListId
Ejemplo n.º 8
0
 def retrieve_container(port):
     tgt_dir = tmp_path('tgt')
     self.cretrieve(port,
                    container_name,
                    targetDir=tgt_dir,
                    as_tar=as_tar)
     self._assertEqualsDir(src_root, os.path.join(tgt_dir, 'toplevel'))
     rmFile(tgt_dir)
Ejemplo n.º 9
0
    def test_ArchiveCmd_Err_3_1(self):
        """
        Synopsis:
        Handling of corrupted HTTP response.

        Description:
        The purpose of the test is test that a corrupted HTTP response is
        properly handled by the C-Client/API.

        The response is corrupted such that it only contains a '\015\012'
        ({Slash r}{Slash n}).

        Expected Result:
        The corrupt HTTP response cannot be unpacked/interpreted as an
        XML document. This should be detected by the C-API and a proper
        error message returned.

        Test Steps:
        - Start special instance of the server class, which produces
          an illegal response.
        - Issue an ARCHIVE Command via the ngamsCClient.
        - Check that the output produced on stdout refers to the appropriate
          error message.

        Remarks:
        ...
        """

        # TODO: From V4.0, this test case produces the error:
        #
        # Error Code:     -4
        # Message:        Problem communicating with server
        #
        # - and not:
        #
        # Error Code:     -103
        # Message:        Invalid reply from data server
        #
        # - as for previous version.
        #
        # This should be investigated and resolved.

        rmFile("tmp/reqCallBack_tmp")
        saveInFile("tmp/reqCallBack_tmp", "reqCallBack_IllegalResp")
        rmFile("tmp/ngamsServerTestIllegalResp_tmp")
        saveInFile("tmp/ngamsServerTestIllegalResp_tmp", "\015\012")
        self.prepExtSrv(srvModule="ngamsSrvTestDynReqCallBack")
        out = _execCClient(unpackXmlStat=0,
                           pars=[["-port", "8888"], ["-cmd", "ARCHIVE"],
                                 ["-fileUri", "src/SmallFile.fits"]])
        tmpStatFile = saveInFile(None, filterOutLines(out, ["Host"]))
        refStatFile = "ref/ngamsCClientTest_test_ArchiveCmd_Err_3_1_ref"
        self.checkFilesEq(refStatFile, tmpStatFile, "Incorrect handling " +\
                          "of corrupt server HTTP response in C-Client/API")
Ejemplo n.º 10
0
def checkCleanDirs(startDir,
                   dirExp,
                   fileExp,
                   useLastAccess):
    """
    Check a tree of directories. Delete all empty directories older than
    the given Directory Expiration. Also files are deleted if the file is
    older than File Expiration given.

    startDir:       Starting directory. The function will move downwards from
                    this starting point (string).

    dirExp:         Expiration time in seconds for directories. Empty
                    directories older than this time are deleted (integer).

    fileExp:        Expiration time in seconds for file. Empty file older than
                    this time are deleted (integer).

    useLastAccess:  Rather than using the creation time as reference, the
                    last modification and access date should be used
                    (integer/0|1).

    Returns:        Void.
    """
    timeNow = time.time()
    # TODO: Potential memory bottleneck. Use 'find > file' as for REGISTER
    #       Command.
    entryList = glob.glob(startDir + "/*")
    # Work down through the directories in a recursive manner. If some
    # directories are not deleted during this run because they have contents,
    # they might be deleted during one of the following runs.
    for entry in entryList:
        stat = os.stat(entry)
        if (not useLastAccess):
            refTime = stat.st_ctime # creation time
        else:
            refTime1 = stat.st_mtime # modification time
            refTime2 = stat.st_atime # access time
            if (refTime1 > refTime2):
                refTime = refTime1
            else:
                refTime = refTime2
        if (os.path.isdir(entry)):
            checkCleanDirs(entry, dirExp, fileExp, useLastAccess)
            tmpGlobRes = glob.glob(entry + "/*")
            if (tmpGlobRes == []):
                if ((timeNow - refTime) > dirExp):
                    logger.debug("Deleting temporary directory: %s", entry)
                    rmFile(entry)
        else:
            if (fileExp):
                if ((timeNow - refTime) > fileExp):
                    logger.debug("Deleting temporary file: %s", entry)
                    rmFile(entry)
Ejemplo n.º 11
0
    def test_VolumeDir_01(self):
        """
        Synopsis:
        Grouping of data volumes under the Volume Dir in the NGAS Root Dir.

        Description:
        See ngamsArchiveCmdTest.test_VolumeDir_01().

        This tests verifies that the files archived into this structure can
        be received.

        Expected Result:
        When the server goes Online, it should accept the given directory
        structure and it should be possible to archive files into this
        structureand subsequently to receive them.

        Test Steps:
        - Create the volume dirs from an existing structure.
        - Start server with configuration specifying the Volumes Dir in which
          all volumes will be hosted.
        - Archive a FITS file.
        - Retrieve the files and check that they are OK.

        Remarks:
        ...
        """
        # Create basic structure.
        ngasRootDir = tmp_path("NGAS")
        rmFile(ngasRootDir)
        checkCreatePath(ngasRootDir)
        subprocess.check_call(
            ['tar', 'zxf',
             self.resource('src/volumes_dir.tar.gz')])
        mvFile('volumes', ngasRootDir)

        # Create configuration, start server.
        self.prepExtSrv(delDirs=0, cfgFile='src/ngamsCfg_VolumeDirectory.xml')

        # Archive a file.
        stat = self.archive("src/SmallFile.fits")
        self.assert_status_ref_file(
            "ref/ngamsRetrieveCmdTest_test_VolumeDir_01_01_ref", stat)

        # Check that the target files have been archived in their
        # appropriate locations.
        trgFile = tmp_path("test_VolumeDir_01_tmp")
        refFile = "src/SmallFile.fits"
        outFilePath = tmp_path("SmallFile.fits")
        stat = self.retrieve("TEST.2001-05-08T15:25:00.123",
                             targetFile=trgFile)

        # unzip the the file and diff against original
        unzip(trgFile, outFilePath)
        self.checkFilesEq(refFile, outFilePath, "Retrieved file incorrect")
Ejemplo n.º 12
0
def main():
    """
    Main function to execute the tool
    """
    # Parse input parameters
    access_code = ""
    file_list_file = ""
    dcc_message_file = ""
    execute = 0
    notification_email = None
    index = 1
    while index < len(sys.argv):
        par = sys.argv[index].upper()
        try:
            if par == "-ACCESSCODE":
                index += 1
                access_code = sys.argv[index]
            elif par == "-FILELIST":
                index += 1
                file_list_file = sys.argv[index]
            elif par == "-DCCMSG":
                index += 1
                dcc_message_file = sys.argv[index]
            elif par == "-EXECUTE":
                execute = 1
            elif par == "-NOTIFEMAIL":
                index += 1
                notification_email = sys.argv[index]
            else:
                sys.exit(1)
            index += 1
        except Exception as e:
            print("\nProblem executing the File Discard Tool: {:s}\n".format(str(e)))
            print(correct_usage())
            sys.exit(1)

    if notification_email is None:
        notification_email = ngasUtilsLib.get_parameter_ngas_resource_file(ngasUtilsLib.NGAS_RC_PAR_NOTIF_EMAIL)
    if dcc_message_file and not file_list_file:
        file_list_file = os.path.join(tempfile.gettempdir(), "ngasDiscardFiles.tmp")
        rmFile(file_list_file)
        ngasUtilsLib.dcc_message_to_file_list(dcc_message_file, file_list_file)
    try:
        if not file_list_file:
            print(correct_usage())
            raise Exception("Incorrect command line parameter(s) given!")
        if not access_code:
            access_code = ngasUtilsLib.console_input("Enter Access Code:")
        ngasUtilsLib.check_access_code(access_code)
        discard_files(file_list_file, execute, notification_email)
    except Exception as e:
        print("\nProblem encountered:\n\n" + str(e) + " -- bailing out\n")
Ejemplo n.º 13
0
def compress(reqPropsObj, parDic):
    """
    Compress the file if required.

    reqPropsObj:  NG/AMS request properties object (ngamsReqProps).

    parDic:       Dictionary with parameters for the DAPI. This is generated
                  with ngamsPlugInApi.parseDapiPlugInPars() (Dictionary).

    Returns:      Tupe containing uncompressed filesize, archived filesize
                  and the format (mime-type) of the resulting data file
                  (tuple).
    """
    stFn = reqPropsObj.getStagingFilename()
    uncomprSize = ngamsPlugInApi.getFileSize(stFn)
    mime = reqPropsObj.getMimeType()
    compression = parDic.get("compression")

    if _compress_data(parDic):
        logger.debug("Compressing file: %s using: %s", stFn, compression)

        # Compress *and* calculate checksum on compressed stream
        # The value crc_name depends on the server configuration and whether the
        # user requested a different variant (see ngamsArchiveUtils)
        gzip_name = '%s.gz' % stFn
        crc_info = None
        if 'crc_name' in reqPropsObj:
            crc_info = ngamsFileUtils.get_checksum_info(
                reqPropsObj['crc_name'])

        compress_start = time.time()
        with open(stFn, 'rb') as f:
            crc = ngamsLib.gzip_compress(f,
                                         gzip_name,
                                         65536,
                                         crc_info=crc_info)
        compress_time = time.time() - compress_start

        reqPropsObj.setStagingFilename(gzip_name)
        rmFile(stFn)
        mime = 'application/x-gfits'
        compression = 'gzip --no-name'

        logger.debug("File compressed: %s Time: %.3fs", gzip_name,
                     compress_time)
    else:
        compression = ''
        crc = None

    archFileSize = ngamsPlugInApi.getFileSize(reqPropsObj.getStagingFilename())

    return uncomprSize, archFileSize, mime, compression, crc
Ejemplo n.º 14
0
def monitorMemUsage(parDic):
    """
    """
    rmFile(parDic["OUTFILE"])
    fo = open(parDic["OUTFILE"], "w")
    memUsageCmd = "/usr/bin/pmap %d" % parDic["PID"]
    while (1):
        stat, out = commands.getstatusoutput(memUsageCmd)
        memUsage = out.split("\n")[-1].split(" ")[-1][0:-1]
        logLine = "%s %s\n" % (PccUtTime.TimeStamp().getTimeStamp(), memUsage)
        fo.write(logLine)
        print logLine[:-1]
        fo.flush()
        time.sleep(parDic["INTERVAL"])
    fo.close()
Ejemplo n.º 15
0
def _openDbSnapshot(ngamsCfgObj,
                    mtPt):
    """
    Open a bsddb file DB. If the file exists and this is not
    a read-only NGAS system the file is opened for reading and writing.
    If this is a read-only NGAS system it is only opened for reading.

    If the file DB does not exist, a new DB is created.

    If the file DB does not exist and this is a read-only NGAS system,
    None is returned.

    The name of the DB file is:

      <Disk Mount Point>/NGAMS_DB_DIR/NGAMS_DB_NGAS_FILES

    ngamsCfgObj:    NG/AMS Configuration Object (ngamsConfig).

    mtPt:           Mount point (string).

    Returns:        File DB object (bsddb|None).
    """
    snapShotFile = os.path.normpath(mtPt + "/" + NGAMS_DB_DIR + "/" +\
                                    NGAMS_DB_NGAS_FILES)
    checkCreatePath(os.path.normpath(mtPt + "/" + NGAMS_DB_CH_CACHE))
    if (os.path.exists(snapShotFile)):
        if (_updateSnapshot(ngamsCfgObj)):
            # Open the existing DB Snapshot for reading and writing.
            snapshotDbm = bsddb.hashopen(snapShotFile, "w")
        else:
            # Open only for reading.
            snapshotDbm = bsddb.hashopen(snapShotFile, "r")
    else:
        if (_updateSnapshot(ngamsCfgObj)):
            # Create a new DB Snapshot.
            snapshotDbm = bsddb.hashopen(snapShotFile, "c")
        else:
            # There is no DB Snapshot and it is not possible to
            # create one - the check cannot be carried out.
            snapshotDbm = None

    # Remove possible, old /<mt pt>/.db/NgasFiles.xml snapshots.
    # TODO: Remove when it can be assumed that all old XML snapshots have
    #       been removed.
    rmFile(os.path.normpath(mtPt + "/" + NGAMS_DB_DIR + "/NgasFiles.xml"))

    return snapshotDbm
Ejemplo n.º 16
0
def _cloneThread(srvObj,
                 cloneListDbmName,
                 tmpFilePat,
                 targetDiskId="",
                 reqPropsObj=None,
                 dummyPar=None):
    """
    Function that carried out the actual cloning process of the files
    referenced to in the 'cloneList'

    srvObj:           Reference to instance of Server Object (ngamsServer).

    cloneListDbmName: Name of DBM containing the information about
                      the files to be cloned. This DB has an index number
                      as key pointing to pickled information about each file.
                      This pickled information is

                        [<File Info Object>, <Host ID>, <Mount Point>]

                      (string)

    tmpFilePat:       File pattern to be used for generating temporary
                      files (string).

    targetDiskId:     ID of disk to where the files cloned should be written
                      (string).

    reqPropsObj:      If an NG/AMS Request Properties Object is given, the
                      Request Status will be updated as the request is carried
                      out (ngamsReqProps).

    Returns:          Void.
    """
    logger.info("Cloning Thread carrying out Clone Request ...")
    try:
        _cloneExec(srvObj, cloneListDbmName, tmpFilePat, targetDiskId,
                   reqPropsObj)
        rmFile(tmpFilePat + "*")
        logger.info("Processing of Clone Request completed")
        thread.exit()
    except Exception:
        rmFile(tmpFilePat + "*")
        raise
Ejemplo n.º 17
0
def run(srvObj, stopEvt):

    cfg = srvObj.getCfg()
    logdir = os.path.dirname(cfg.getLocalLogFile())

    # The LOG-ROTATE-<timestamp>.nglog.unsaved pattern is produced by the
    # ngamsServer.NgasRotatingFileHandler class, which is the file handler
    # attached to the root logger in the server process
    logger.debug("Checking if there are unsaved rotated logfiles")
    for unsaved in sorted(
            glob.glob(os.path.join(logdir, 'LOG-ROTATE-*.nglog.unsaved'))):

        # Remove the .unsaved bit, leave the rest
        fname = '.'.join(unsaved.split('.')[:-1])
        try:
            mvFile(unsaved, fname)
            try_archiving(cfg, srvObj, fname)
        except Exception as e:
            mvFile(fname, unsaved)
            if isinstance(e, socket.error) and e.errno == errno.ECONNREFUSED:
                # this is expected when the server is just starting up,
                # let's ignore for now
                logger.warning(
                    "Server not up yet, postponing processing of %s", unsaved)
                continue
            raise

        # Do additional things with our logfiles
        for plugin in get_logfile_handler_plugins(cfg):
            try:
                plugin(srvObj, fname)
            except:
                logger.exception("Error while handling logfile %s", fname)

    logger.debug("Check if there are old rotated logfiles to remove ...")
    max_rotations = max(min(cfg.getLogRotateCache(), 100), 0)
    logfiles = glob.glob(os.path.join(logdir, 'LOG-ROTATE-*.nglog'))
    logfiles.sort()
    for f in logfiles[max_rotations:]:
        logger.info("Removing rotated logfile %s", f)
        rmFile(f)
Ejemplo n.º 18
0
def checkTarball(filename):
    """
    Check that the tarball is correct

    filename:  Name of tarball file (string).

    Returns:   Void.
    """
    err = 0
    tmpFilename = filename.replace(":", "_") + "_tmp"
    try:
        commands.getstatusoutput("ln -s " + filename + " " + tmpFilename)
        stat, out = commands.getstatusoutput("tar -tf " + tmpFilename)
        rmFile(tmpFilename)
        if (stat != 0):
            errMsg = str(out).replace("\n", " --- ")
            err = 1
    except Exception, e:
        rmFile(tmpFilename)
        errMsg = str(e)
        err = 1
Ejemplo n.º 19
0
def _registerThread(srvObj,
                    fileListDbmName,
                    tmpFilePat,
                    diskInfoDic,
                    reqPropsObj=None,
                    dummyPar=None):
    """
    See documentation for _registerExec().

    The purpose of this function is merely to excapsulate the actual
    cloning to make it possible to clean up in case an exception is thrown.
    """
    try:
        _registerExec(srvObj, fileListDbmName, tmpFilePat, diskInfoDic,
                      reqPropsObj)
        rmFile(tmpFilePat + "*")
        return
    except Exception:
        logger.exception("Exception raised in Register Sub-Thread")
        rmFile(tmpFilePat + "*")
        raise
Ejemplo n.º 20
0
def ngamsTileCompress(filename):
    """
    Tile compress the referenced file.

    filename:   Filename (string).

    Returns:    Void.
    """
    tmpFilename = filename + ".tmp"
    try:
        comprCmd = "imcopy %s '%s[compress]'" % (filename, tmpFilename)
        logger.debug("Command to tile compress file: %s", comprCmd)
        stat, out = commands.getstatusoutput(comprCmd)
        if (stat != 0):
            msg = "Error compressing file: %s. Error: %s" %\
                  (filename, stat.replace("\n", "   "))
            raise Exception, msg
        mvFile(tmpFilename, filename)
        logger.debug("Successfully tile compressed file: %s", filename)
    except Exception, e:
        rmFile(tmpFilename)
        raise Exception, e
Ejemplo n.º 21
0
    def test_RetrieveCmd_Err_1_2(self):
        """
        Synopsis:
        Issue RETRIEVE Command/server dies during initial handling.

        Description:
        Check that the situation where the server dies during the initial
        handling of a Retrieve Request is correctly handled by the C-API.

        Expected Result:
        The C-API should detect that the server died (=broken socket
        connection) and should produce the appropriate error code, which is
        printed on stdout by the ngamsCClient.

        Test Steps:
        - Start a special instance of the server, which kills itself
          when receiving a RETRIEVE Command.
        - Archive a file.
        - Issue a RETRIEVE Command to retrieve the archived file.
        - Verify that the proper output is produced by ngamsCClient indicating
          the problem.

        Remarks:
        ...
        """
        rmFile("tmp/reqCallBack_tmp")
        saveInFile("tmp/reqCallBack_tmp", "reqCallBack_SrvCrash2")
        self.prepExtSrv(srvModule="ngamsSrvTestDynReqCallBack")
        out =\
            _execCClient(unpackXmlStat = 0,
                         pars = [["-port", "8888"],
                                 ["-cmd", "RETRIEVE"],
                                 ["-fileId", "TEST.2001-05-08T15:25:00.123"],
                                 ["-timeOut", "10"]])
        tmpStatFile = saveInFile(None, filterOutLines(out, ["Host"]))
        refStatFile = "ref/ngamsCClientTest_test_RetrieveCmd_Err_1_2_ref"
        self.checkFilesEq(refStatFile, tmpStatFile, "Incorrect handling " +\
                          "of timeout of Retrieve Request in C-Client/API")
Ejemplo n.º 22
0
    def test_RetrieveCmd_Err_1_1(self):
        """
        Synopsis:
        Issue RETRIEVE Command/request times out.

        Description:
        The purpose of the test is to verify that the situation where a
        Retrieve Request times out is correctly handled by the C-API.

        Expected Result:
        After the specified timeout is reached, the appropriate error code
        is returned to the client.

        Test Steps:
        - Start special instance of the server, which blocks on a Retrieve
          Request (no response send).
        - Issue a Retrieve Request via the ngamsCClient with timeout 10s.
        - Verify that after 10s the correct error code is returned by the
          C-API (printed by ngamsCClient on stdout).

        Remarks:
        ...
        """
        rmFile("tmp/reqCallBack_tmp")
        saveInFile("tmp/reqCallBack_tmp", "reqCallBack_AccArchiveBlock2")
        self.prepExtSrv(srvModule="ngamsSrvTestDynReqCallBack")
        sendPclCmd(port=8888).archive("src/SmallFile.fits")
        out =\
            _execCClient(unpackXmlStat = 0,
                         pars = [["-port", "8888"],
                                 ["-cmd", "RETRIEVE"],
                                 ["-fileId", "TEST.2001-05-08T15:25:00.123"],
                                 ["-timeOut", "10"]])
        tmpStatFile = saveInFile(None, filterOutLines(out, ["Host"]))
        refStatFile = "ref/ngamsCClientTest_test_RetrieveCmd_Err_1_1_ref"
        self.checkFilesEq(refStatFile, tmpStatFile, "Incorrect handling " +\
                          "of timeout of Retrieve Request in C-Client/API")
Ejemplo n.º 23
0
def run(srvObj, stopEvt):

    cfg = srvObj.getCfg()
    logdir = os.path.dirname(cfg.getLocalLogFile())

    # The LOG-ROTATE-<timestamp>.nglog.unsaved pattern is produced by the
    # ngamsServer.NgasRotatingFileHandler class, which is the file handler
    # attached to the root logger in the server process
    logger.debug("Checking if there are unsaved rotated logfiles")
    for unsaved in glob.glob(os.path.join(logdir,
                                          'LOG-ROTATE-*.nglog.unsaved')):

        # Remove the .unsaved bit, leave the rest
        fname = '.'.join(unsaved.split('.')[:-1])
        mvFile(unsaved, fname)

        # Connect to the server and send a pull ARCHIVE request
        if cfg.getArchiveRotatedLogfiles():
            file_uri = "file://" + fname
            host, port = srvObj.get_self_endpoint()
            ngamsPClient.ngamsPClient(host,
                                      port).archive(file_uri, 'ngas/nglog')

        # Do additional things with our logfiles
        for plugin in get_logfile_handler_plugins(cfg):
            try:
                plugin(srvObj, fname)
            except:
                logger.exception("Error while handling logfile %s", fname)

    logger.debug("Check if there are old rotated logfiles to remove ...")
    max_rotations = max(min(cfg.getLogRotateCache(), 100), 0)
    logfiles = glob.glob(os.path.join(logdir, 'LOG-ROTATE-*.nglog'))
    logfiles.sort()
    for f in logfiles[max_rotations:]:
        logger.info("Removing rotated logfile %s", f)
        rmFile(f)
Ejemplo n.º 24
0
    def test_ArchiveCmd_Err_2(self):
        """
        Synopsis:
        Issue ARCHIVE Command/server crashes (broken socket connection).

        Description:
        The purpose of the test is to verify the correct handling/behavior
        of the C-Client/API in the case the socket connection to the server
        breaks.

        Expected Result:
        During the request handling the socket connection is provoked to break
        and the C-Client/API should detect this and shoudl produce the proper
        error message.

        Test Steps:
        - Start special instance of the server which makes itself crash when
          a request is received (to simulate a broken socket connection).
        - Submit an ARCHIVE Command via the C-Client/API (small file).
        - Check the result produced by the ngamsCClient on stdout that this
          is as expected.

        Remarks:
        ...

        """
        rmFile("tmp/reqCallBack_tmp")
        saveInFile("tmp/reqCallBack_tmp", "reqCallBack_SrvCrash1")
        self.prepExtSrv(srvModule="ngamsSrvTestDynReqCallBack")
        out = _execCClient(unpackXmlStat=0,
                           pars=[["-port", "8888"], ["-cmd", "ARCHIVE"],
                                 ["-fileUri", "src/SmallFile.fits"]])
        tmpStatFile = saveInFile(None, filterOutLines(out, ["Host"]))
        refStatFile = "ref/ngamsCClientTest_test_ArchiveCmd_Err_2_ref"
        self.checkFilesEq(refStatFile, tmpStatFile, "Incorrect handling " +\
                          "of crash of server in C-Client/API")
Ejemplo n.º 25
0
    def test_ArchiveCmd_Err_3_3(self):
        """
        Synopsis:
        Issue ARCHIVE Command/server sends back a nonsense HTTP response.

        Description:
        The purpose of the test is test that a corrupted HTTP response is
        properly handled by the C-Client/API.

        The response is corrupted such that it contains 'noise'.

        Expected Result:
        The C-API should detect the illegally formatted response and return
        the correct error code.

        Test Steps:
        - Start special instance of the server that generates a non-sense
          HTTP response.
        - Issue an Archive Request via the ngamsCClient.
        - Check that the proper error message is produced by the ngamsCClient

        Remarks:
        ...
        """
        rmFile("tmp/reqCallBack_tmp")
        saveInFile("tmp/reqCallBack_tmp", "reqCallBack_IllegalResp")
        rmFile("tmp/ngamsServerTestIllegalResp_tmp")
        saveInFile("tmp/ngamsServerTestIllegalResp_tmp", "f-423hcqfe-0")
        self.prepExtSrv(srvModule="ngamsSrvTestDynReqCallBack")
        out = _execCClient(unpackXmlStat=0,
                           pars=[["-port", "8888"], ["-cmd", "ARCHIVE"],
                                 ["-fileUri", "src/SmallFile.fits"]])
        tmpStatFile = saveInFile(None, filterOutLines(out, ["Host"]))
        refStatFile = "ref/ngamsCClientTest_test_ArchiveCmd_Err_3_3_ref"
        self.checkFilesEq(refStatFile, tmpStatFile, "Incorrect handling " +\
                          "of corrupt server HTTP response in C-Client/API")
Ejemplo n.º 26
0
    def test_ArchiveCmd_Err_5_1(self):
        """
        Synopsis:
        Issue ARCHIVE Command/socket breaks while writing data on it.

        Description:
        The purpose of the test is to verify that the C-API handles
        properly the situation where the socket connection breaks while
        data is being written on it (during an Archive Push Request).

        Expected Result:
        The C-API should detect that the write socket connection breaks, and
        should produce the appropriate error message.

        Test Steps:
        - Start special instance of server which terminates itself while
          the client writes the data to the server.
        - Issue Archive Push Request with a big file to the server.
        - Verify that the proper error response is produced by the C-API.

        Remarks:
        ...
        """
        rmFile("tmp/reqCallBack_tmp")
        saveInFile("tmp/reqCallBack_tmp", "reqCallBack_SrvCrash1")
        self.prepExtSrv(srvModule="ngamsSrvTestDynReqCallBack")
        cpFile("src/WFI-TEST.fits.Z", "tmp/WFI-TEST_tmp.fits.Z")
        rmFile("tmp/WFI-TEST_tmp.fits")
        subprocess.check_call(['uncompress', 'tmp/WFI-TEST_tmp.fits.Z'])
        out = _execCClient(unpackXmlStat=0,
                           pars=[["-port", "8888"], ["-cmd", "ARCHIVE"],
                                 ["-fileUri", "tmp/WFI-TEST_tmp.fits"]])
        tmpStatFile = saveInFile(None, filterOutLines(out, ["Host"]))
        refStatFile = "ref/ngamsCClientTest_test_ArchiveCmd_Err_5_1_ref"
        self.checkFilesEq(refStatFile, tmpStatFile, "Incorrect handling " +\
                          "of broken write socket in C-Client/API")
Ejemplo n.º 27
0
def handleCmd(srvObj, reqPropsObj, httpRef):
    """
    Handle Command QUERY to query the DB system used.

    srvObj:         Reference to NG/AMS server class object (ngamsServer).

    reqPropsObj:    Request Property object to keep track of actions done
                    during the request handling (ngamsReqProps).

    httpRef:        Reference to the HTTP request handler
                    object (ngamsHttpRequestHandler).

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

    # Get command parameters.
    if not 'query' in reqPropsObj:
        raise Exception("No query specified. Valid queries are: %s" %
                        (queries.keys(), ))
    query = reqPropsObj.getHttpPar("query").lower()
    if query not in queries.keys():
        raise Exception("Invalid query specified. Valid queries are: %s" %
                        (queries.keys(), ))

    out_format = None
    if 'format' in reqPropsObj:
        out_format = reqPropsObj["format"]

    cursorId = None
    if (reqPropsObj.hasHttpPar("cursor_id")):
        cursorId = reqPropsObj.getHttpPar("cursor_id")

    fetch = None
    if (reqPropsObj.hasHttpPar("fetch")):
        fetch = int(reqPropsObj.getHttpPar("fetch"))

    # Select the SQL statement + pars to execute
    colnames, sql = queries[query]
    args = ()
    if query in ('subscribers_like', 'files_like', 'files_location',
                 'lastver_location'):
        param = '%'
        if (reqPropsObj.hasHttpPar("like")):
            param = reqPropsObj.getHttpPar("like")
        args = (param, )
    elif query == 'files_between':
        param1 = param2 = ''
        if 'start' in reqPropsObj:
            param1 = reqPropsObj["start"]
        if 'end' in reqPropsObj:
            param2 = reqPropsObj["end"]
        if param1 and param2:
            args = (param1, param2)
        elif param1:
            sql = 'select * from ngas_files where ingestion_date >= {0}'
            args = (param1, )
        else:
            sql = queries['files_list']

    # Execute the query.
    if not cursorId:

        # TODO: Make possible to return an XML document
        # TODO: Potential problem with very large result sets.
        #       Implement streaming result directly3
        # rtobar, 2018 Feb: for the streaming result functionality to work
        #                   correctly we need to support sending content with
        #                   chunked transfer encoding first. This is not
        #                   difficult to add on the server side, but needs
        #                   to be also added on the client side (which I suppose
        #                   means all languages, not only python, if we really
        #                   need to maintain those).
        #                   We already support proper cursors at the database
        #                   access level, so it's not difficult to change
        #                   the query below to use a cursor and work as a
        #                   generator instead of returning the full list of
        #                   results in one go.
        res = srvObj.getDb().query2(sql, args=args)

        if out_format in ("list", 'text'):
            finalRes = formatAsList(res, colnames)
            mimeType = NGAMS_TEXT_MT
        elif out_format == "pickle":
            finalRes = cPickle.dumps([res])
            mimeType = NGAMS_PYTHON_PICKLE_MT
        elif out_format == "json":
            results = [{colname: val
                        for colname, val in zip(colnames, row)} for row in res]
            finalRes = six.b(json.dumps(results, default=encode_decimal))
            mimeType = NGAMS_JSON_MT
        else:
            finalRes = six.b(str(list(res)))
            mimeType = NGAMS_PYTHON_LIST_MT

        # Return the data and good bye.
        httpRef.send_data(finalRes, mimeType)
        return

    # TODO:
    #
    #
    #
    # The rest seems to be very old functionality, which we probably
    # want to drop at some point. I'm still keeping it here for the time being
    # to be a good citizen and not break any (very potential) user.
    #
    #
    #
    elif (fetch):
        cursorDbmFilename = genCursorDbmName(srvObj.getCfg().\
                                             getRootDirectory(), cursorId)
        if (not os.path.exists(cursorDbmFilename)):
            logger.error("Illegal Cursor ID: %s or cursor expired", cursorId)
            return []
        try:
            cursorDbm = ngamsDbm.ngamsDbm(cursorDbmFilename, writePerm=1)
            count = 0
            resSet = []
            cursorIdx = cursorDbm.get(CURSOR_IDX)
            while (count < fetch):
                cursorIdx += 1
                if (cursorDbm.hasKey(str(cursorIdx))):
                    res = cursorDbm.get(str(cursorIdx))
                    resSet.append(res)
                else:
                    # -- no more results to return.
                    break
                count += 1
            cursorDbm.add(CURSOR_IDX, cursorIdx)
            cursorDbm.sync()
            del cursorDbm
            # If all entries have been fetched, we delete the cursor DBM.
            if (count < fetch):
                rmFile(cursorDbmFilename + "*")

            # Return the data.
            # TODO: Make it possible to return ASCII List + XML.
            httpRef.send_data(str(resSet), NGAMS_PYTHON_LIST_MT)

        except Exception as e:
            msg = "Error fetching from cursor with ID: %s. Error: %s"
            raise Exception(msg % (cursorId, str(e)))
    elif (query and cursorId):
        logger.debug("Creating new cursor with ID: %s, query: %s", cursorId,
                     query)
        cursorDbmFilename = genCursorDbmName(srvObj.getCfg().\
                                             getRootDirectory(), cursorId)
        cursorDbm = ngamsDbm.ngamsDbm(cursorDbmFilename, writePerm=1)

        # Make the query in a cursor and dump the results into the DBM.
        curObj = srvObj.getDb().dbCursor(query, args=args)
        with curObj:
            for res in curObj.fetch(1000):
                cursorDbm.addIncKey(res)
        cursorDbm.add(CURSOR_IDX, 0)
        cursorDbm.sync()
        del cursorDbm
        # TODO: In this case no reply is generated??
    else:
        msg = "Error illegal combination of parameters. Correct syntax is: " +\
              "QUERY?query=<Query>[&out_format=<Format (list)>] or " +\
              "QUERY?query=<Query>&cursor_id=<ID> followed by N calls to " +\
              "QUERY?cursor_id=<ID>&fetch=<Number of Elements>"
        raise Exception(msg)
Ejemplo n.º 28
0
def handleCmd(srvObj,
              reqPropsObj,
              httpRef):
    """
    Handle STATUS command.

    srvObj:         Reference to NG/AMS server class object (ngamsServer).

    reqPropsObj:    Request Property object to keep track of actions done
                    during the request handling (ngamsReqProps).

    httpRef:        Reference to the HTTP request handler object
                    (ngamsHttpRequestHandler).

    Returns:        Void.
    """
    status = ngamsStatus.ngamsStatus()
    status.setDate(toiso8601()).\
           setVersion(getNgamsVersion()).setHostId(srvObj.getHostId()).\
           setStatus(NGAMS_SUCCESS).\
           setMessage("Successfully handled command STATUS").\
           setState(srvObj.getState()).setSubState(srvObj.getSubState())

    reqPropsObjRef = reqPropsObj

    # Get the information requested.
    diskId            = ""
    fileId            = ""
    fileVersion       = ""
    configurationFile = ""
    fileAccess        = ""
    hostId            = ""
    requestId         = ""
    dbTime            = ""
    dbTimeReset       = ""
    fileList          = ""
    fileListId        = ""
    maxElements       = 100000
    if (reqPropsObj.hasHttpPar("disk_id")):
        diskId = reqPropsObj.getHttpPar("disk_id")

    if (reqPropsObj.hasHttpPar("file_id")):
        fileId = reqPropsObj.getHttpPar("file_id")
    if (reqPropsObj.hasHttpPar("file_version")):
        fileVersion = int(reqPropsObj.getHttpPar("file_version"))

    if (reqPropsObj.hasHttpPar("configuration_file")): 
        configurationFile = reqPropsObj.getHttpPar("configuration_file")

    if (reqPropsObj.hasHttpPar("file_access")):
        fileAccess = reqPropsObj.getHttpPar("file_access")

    if (reqPropsObj.hasHttpPar("host_id")):
        hostId = reqPropsObj.getHttpPar("host_id")

    if (reqPropsObj.hasHttpPar("max_elements")):
        maxElements = int(reqPropsObj.getHttpPar("max_elements"))

    if (reqPropsObj.hasHttpPar("request_id")):
        requestId = reqPropsObj.getHttpPar("request_id")

    if (reqPropsObj.hasHttpPar("db_time")):
        dbTime = True
    if (reqPropsObj.hasHttpPar("db_time_reset")):
        dbTimeReset = True

    if (reqPropsObj.hasHttpPar("flush_log")):
        # in the past this called flushLog()
        # do we really want to keep that functionality? I doubt it
        pass

    if (reqPropsObj.hasHttpPar("file_list")):
        fileList = int(reqPropsObj.getHttpPar("file_list"))

    if (reqPropsObj.hasHttpPar("file_list_id")):
        fileListId = reqPropsObj.getHttpPar("file_list_id")

    if (reqPropsObj.hasHttpPar("dump_object_info")):
        # Dump status of all objects allocated into file specified.
        targFile = reqPropsObj.getHttpPar("dump_object_info")
        rmFile(targFile)
        fo = open(targFile, "w")
        fo.write(_genObjectStatus())
        fo.close()

    # Handle request for file info.
    genCfgStatus     = 0
    genDiskStatus    = 0
    genFileStatus    = 0
    genStatesStatus  = 1
    genRequestStatus = 0
    msg              = ""
    help             = 0
    if (reqPropsObj.hasHttpPar("help")):
        global _help
        msg = _help
        help = 1

    elif hostId and hostId != srvObj.getHostId():

        host, port = srvObj.get_remote_server_endpoint(hostId)
        cfgObj = srvObj.getCfg()
        if not cfgObj.getProxyMode():
            httpRef.redirect(host, port)
            return
        else:
            try:
                httpRef.proxy_request(hostId, host, port)
            except Exception as e:
                ex = re.sub("<|>", "", str(e))
                errMsg = genLog("NGAMS_ER_COM",
                                [host, port,ex])
                raise Exception(errMsg)
            return
    elif (fileList):
        if (not fileListId):
            # It's a new STATUS?file_list request.
            fileListId = _handleFileList(srvObj, reqPropsObj, httpRef)
        # Send back data from the request.
        _handleFileListReply(srvObj, reqPropsObj, httpRef, fileListId,
                             maxElements)
    elif (diskId):
        diskObj = ngamsDiskInfo.ngamsDiskInfo()
        diskObj.read(srvObj.getDb(), diskId)
        status.addDiskStatus(diskObj)
        genDiskStatus = 1
    elif (fileId):
        if (not fileVersion): fileVersion = -1
        try:
            fileObj = ngamsFileInfo.ngamsFileInfo()
            fileObj.read(srvObj.getHostId(), srvObj.getDb(), fileId, fileVersion)
            diskObj = ngamsDiskInfo.ngamsDiskInfo()
            try:
                diskObj.read(srvObj.getDb(), fileObj.getDiskId())
            except:
                errMsg = "Illegal Disk ID found: {0} for file with ID: {1}".format(fileObj.getDiskId(), fileId)
                raise Exception(errMsg)
            diskObj.addFileObj(fileObj)
            status.addDiskStatus(diskObj)
        except:
            # The file was not found in the database. Check if it is available
            # on a remote partner site.
            host, port, status_info, disk_info, file_info = \
                ngamsFileUtils.lookup_partner_site_file_status(srvObj, fileId,
                                                               fileVersion,
                                                               reqPropsObj)
            # Update status reply using the disk status and file status
            # information retrieved from the partner site
            status.addDiskStatus(disk_info)
        genDiskStatus = 1
        genFileStatus = 1
    elif (requestId):
        logger.debug("Checking status of request with ID: %s", requestId)
        reqPropsObjRef = srvObj.getRequest(requestId)
        if (not reqPropsObjRef):
            errMsg = genLog("NGAMS_ER_ILL_REQ_ID", [requestId])
            raise Exception(errMsg)
        genRequestStatus = 1
    elif (configurationFile):
        msg = "configuration_file=" + srvObj.cfg_fname
        genCfgStatus = 1
        # Hidden feature to return complete Cfg!!
        try:
            genCfgStatus = int(configurationFile)
        except ValueError:
            genCfgStatus = 1
        status.setNgamsCfgObj(srvObj.getCfg())
    elif (fileAccess):
        if (not fileVersion): fileVersion = -1
        fileId = fileAccess
        msg = _checkFileAccess(srvObj, reqPropsObj, httpRef, fileId,
                               fileVersion, diskId)
    elif (dbTime):
        logger.debug("Querying total DB time")
        msg = "Total DB time: %.6fs" % srvObj.getDb().getDbTime()
    elif (dbTimeReset):
        msg = "Resetting DB timer"
        logger.debug(msg)
        srvObj.getDb().resetDbTime()
    else:
        msg = "Successfully handled command STATUS"

    if (reqPropsObjRef == reqPropsObj):
        reqPropsObj.setCompletionTime()
        srvObj.updateRequestDb(reqPropsObj)
    if (genCfgStatus or genDiskStatus or genFileStatus or genRequestStatus):
        status.setReqStatFromReqPropsObj(reqPropsObjRef)

        # Generate XML reply.
        logger.debug("Status requests: " + str([genCfgStatus, genDiskStatus, genFileStatus,
                                                genStatesStatus]))
        xmlStat = status.genXmlDoc(genCfgStatus, genDiskStatus, genFileStatus,
                                   genStatesStatus)
        xmlStat = ngamsHighLevelLib.addStatusDocTypeXmlDoc(srvObj, xmlStat)
        httpRef.send_data(six.b(xmlStat), NGAMS_XML_MT)
    elif not httpRef.reply_sent:
        httpRef.send_status(msg)

    if (msg and (not help)):
        logger.info(msg)
    else:
        logger.info("Successfully handled command STATUS")
Ejemplo n.º 29
0
def _handleFileListReply(srvObj,
                         reqPropsObj,
                         httpRef,
                         fileListId,
                         maxElements = None):
    """
    Extracts file information from a previously dumped file information
    in connection with a STATUS?file_list request.

    srvObj:         Reference to NG/AMS server class object (ngamsServer).

    reqPropsObj:    Request Property object to keep track of actions done
                    during the request handling (ngamsReqProps).

    httpRef:        Reference to the HTTP request handler object
                    (ngamsHttpRequestHandler).

    fileListId:     File List ID allocated to this request (string).

    maxElements:    Maximum number of elements to extract and return to the
                    requestor (integer).

    Returns:        Void.
    """
    # Get the name of the DBM in which the information is stored.
    dbmBaseName = STATUS_FILE_LIST_DBM_TAG % fileListId
    dbmPat = os.path.normpath("%s/*%s*" %\
                              (ngamsHighLevelLib.\
                               getNgasTmpDir(srvObj.getCfg()),
                               dbmBaseName))
    dbmMatches = glob.glob(dbmPat)
    if (len(dbmMatches) < 1):
        msg = "Referenced File List ID: %s in connection with " +\
              "STATUS/file_list request, is not (or no longer) known"
        raise Exception(msg % fileListId)
    elif (len(dbmMatches) > 1):
        msg = "Inconsistencies encountered in locating result set for " +\
              "STATUS/file_list for referenced File List ID: %s"
        raise Exception(msg % fileListId)
    fileInfoDbmName = dbmMatches[0]

    # Generate the NG/AMS Status Document, with a File List in it.
    # Compress it on the fly.
    fileListXmlDoc = ngamsHighLevelLib.\
                     genTmpFilename(srvObj.getCfg(),
                                    "STATUS_FILE_LIST_XML.xml")
    try:
        tmpFileListDbm = ngamsDbm.ngamsDbm(fileInfoDbmName,
                                           cleanUpOnDestr = 0,
                                           writePerm = 1)
        rmFile(fileListXmlDoc)
        fo = open(fileListXmlDoc, "w")
        if (not maxElements):
            remainingObjects = 0
        else:
            remainingObjects = (tmpFileListDbm.getCount() - maxElements)
        if (remainingObjects < 0):
            remainingObjects = 0
        fo.write(_fileListXmlHdr % (fileListId, str(remainingObjects)))

        # Loop over the file info objects and write them into the file.
        # take max the number of elements specified.
        tmpFileListDbm.initKeyPtr()
        elCount = 0
        keyRefList = []
        while (True):
            # Have the requested number of elements been extracted?
            if (maxElements):
                if (elCount >= maxElements):
                    break

            # Get the next key (if there are more elements).
            key, fileInfo = tmpFileListDbm.getNext()
            if (not key):
                break
            try:
                # Write the File Status XML Element in the file.
                tmpFileInfoObj = ngamsFileInfo.ngamsFileInfo().\
                                 unpackSqlResult(fileInfo)
                fileInfoXml = tmpFileInfoObj.genXml(storeDiskId = 1).\
                              toprettyxml("  ", "\n")[:-1]
                fo.write("\n" + fileInfoXml)
            except Exception as e:
                msg = "Error creating STATUS/File List XML Document. " +\
                      "Error: %s" % str(e)
                logger.error(msg)
                raise
            keyRefList.append(key)
            elCount += 1
        # Finish up the XML document, close the file.
        fo.write(_fileListXmlFooter)
        fo.close()
        # Assume this type of file can always be compressed.
        fileListXmlDoc = compressFile(fileListXmlDoc)
    except:
        rmFile("%s*" % fileInfoDbmName)
        rmFile("%s*" % fileListXmlDoc)
        raise

    # Send the XML document back to the requestor.
    try:
        httpRef.send_file(fileListXmlDoc, NGAMS_GZIP_XML_MT)

        # Remove the reported entries.
        for key in keyRefList:
            tmpFileListDbm.rem(key)
        tmpFileListDbm.sync()
        del keyRefList
        keyRefList = []

        # If there are no more entries, delete the DBM.
        dbmCount = tmpFileListDbm.getCount()
        del tmpFileListDbm
        if (dbmCount == 0):
            rmFile("%s*" % fileInfoDbmName)

    except Exception as e:
        msg = "Error returning response to STATUS?file_list request. Error: %s"
        msg = msg % str(e)
        raise Exception(msg)
    finally:
        rmFile(fileListXmlDoc)
Ejemplo n.º 30
0
def _remFile(srvObj, reqPropsObj, diskId, fileId, fileVersion, execute,
             tmpFilePat):
    """
    See documentation for the ngamsRemFileCmd.remFile() function.
    """
    # Check for illegal parameter combinations.
    if ((not diskId) or (diskId and (not fileId))):
        errMsg = "Disk ID: %s, File ID: %s, File Version: %d" %\
                 (diskId, fileId, fileVersion)
        errMsg = genLog("NGAMS_ER_CMD_SYNTAX", [NGAMS_REMFILE_CMD, errMsg])
        raise Exception(errMsg)

    # Temporary DBM to contain SQL info about files concerned by the query.
    fileListDbmName = os.path.normpath(tmpFilePat + "_FILE_LIST")
    fileListDbm = ngamsDbm.ngamsDbm(fileListDbmName, writePerm=1)

    # Get the information from the DB about the files in question.
    hostId = None
    diskIds = []
    fileIds = []
    if (diskId):
        diskIds = [diskId]
    elif ((not diskId) and fileId):
        hostId = srvObj.getHostId()
    if (fileId): fileIds = [fileId]
    if (fileVersion == -1): fileVersion = None

    n_files = 0
    for f in srvObj.db.getFileSummary1(hostId, diskIds, fileIds, ignore=None):
        if fileVersion is not None and fileVersion != f[
                ngamsDbCore.SUM1_VERSION]:
            continue
        msg = "Scheduling file with ID: %s/%d on disk with ID: %s for " +\
              "deletion"
        logger.debug(msg, f[ngamsDbCore.SUM1_FILE_ID],
                     f[ngamsDbCore.SUM1_VERSION], f[ngamsDbCore.SUM1_DISK_ID])
        fileListDbm.add(str(n_files), f)
        n_files += 1
        fileListDbm.sync()

    # Check if the files selected for deletion are available within the NGAS
    # system, in at least 3 copies.
    filesMisCopyDbmName, filesNotRegDbmName, complFileListDbmName =\
                         ngamsRemUtils.checkFileCopiesAndReg(srvObj,
                                                             3, tmpFilePat,
                                                             fileListDbmName)
    status = ngamsRemUtils._remStatErrReport(srvObj, reqPropsObj, tmpFilePat,
                                             filesMisCopyDbmName,
                                             filesNotRegDbmName,
                                             fileListDbmName, diskId, fileId,
                                             fileVersion)
    if (status): return status

    # Check that none of the matching files are stored on other NGAS Nodes.
    # If such are found, do not consider these.
    fileListDbm.initKeyPtr()
    remKeyList = []
    while (1):
        key, fileInfo = fileListDbm.getNext()
        if (not key): break
        if (fileInfo[ngamsDbCore.SUM1_HOST_ID] != srvObj.getHostId()):
            remKeyList.append(key)
    for remKey in remKeyList:
        fileListDbm.rem(remKey)

    #########################################################################
    # Execute the deletion if execute = 1 and files were found to be deleted.
    #########################################################################
    successDelCount = 0
    failedDelCount = 0
    if (execute):
        fileListDbm.initKeyPtr()
        run = 1
        # TODO: This should be changed to a single or a few DB transactions for all files
        # and a bulk rm for the same number of files.
        while (run):
            key, fileInfo = fileListDbm.getNext()
            if (not key):
                run = 0
                continue
            try:
                diskId = fileInfo[ngamsDbCore.SUM1_DISK_ID]
                fileId = fileInfo[ngamsDbCore.SUM1_FILE_ID]
                fileVer = fileInfo[ngamsDbCore.SUM1_VERSION]
                mtPt = fileInfo[ngamsDbCore.SUM1_MT_PT]
                filename = fileInfo[ngamsDbCore.SUM1_FILENAME]
                complFilename = os.path.normpath(mtPt + "/" + filename)
                msg = "Deleting DB info for file: %s/%s/%d"
                logger.debug(msg, diskId, fileId, fileVer)
                # We remove first the DB info and afterwards the file on the
                # disk. The reason for this is that it is considered worse
                # to have an entry for a file in the DB, which is not on disk
                # than vice versa, since NGAS uses the info in the DB to check
                # for the number of available copies.
                try:
                    srvObj.getDb().deleteFileInfo(srvObj.getHostId(), diskId,
                                                  fileId, fileVer)
                    infoMsg = genLog("NGAMS_INFO_DEL_FILE",
                                     [diskId, fileId, fileVer])
                    logger.debug(infoMsg)
                    successDelCount += 1
                except Exception, e:
                    failedDelCount += 1
                    errMsg = genLog("NGAMS_ER_DEL_FILE_DB",
                                    [diskId, fileId, fileVer,
                                     str(e)])
                    logger.warning(errMsg)
                # Removing the DB info was successful, remove the copy on disk.
                msg = "Deleting copy of file: %s/%s/%d: %s"
                logger.debug(msg, diskId, fileId, fileVer, complFilename)
                rmFile(complFilename)
            except Exception, e:
                failedDelCount += 1
                errMsg = genLog(
                    "NGAMS_ER_DEL_FILE_DISK",
                    [diskId, fileId, fileVer, str(e)])
                logger.warning(errMsg)