Ejemplo n.º 1
0
    def retrieve(self,
                 fileId,
                 fileVersion=-1,
                 pars=[],
                 hdrs={},
                 targetFile=None,
                 processing=None,
                 processingPars=None):
        """
        Request file `fileId` from the NG/AMS Server, store it locally
        in `targetFile`, and return the result of the operation as an
        ngamsStatus object. If `targetFile` is a directory, the name of the
        retrieved file is appended to the directory name.

        If `file_version` is given then that specific of the version will be
        retrieved.
        If `processing` and `processingPars` are given, they are passed down
        as the processing plug-in name and parameters to be applied to the
        retrieved data *on the server side*, respectively.
        """

        pars = list(pars)
        pars.append(("file_id", fileId))
        if fileVersion != -1:
            pars.append(("file_version", str(fileVersion)))
        if processing:
            pars.append(("processing", processing))
            if processingPars:
                pars.append(("processingPars", processingPars))

        targetFile = targetFile or '.'

        resp, host, port = self._get('RETRIEVE', pars, hdrs)
        host_id = "%s:%d" % (host, port)
        with contextlib.closing(resp):

            if resp.status != NGAMS_HTTP_SUCCESS:
                return ngamsStatus.to_status(resp, host_id, 'RETRIEVE')

            # If the target path is a directory, take the filename
            # of the incoming data as the filename
            fname = targetFile
            if os.path.isdir(fname):
                cdisp = resp.getheader('Content-Disposition')
                parts = ngamsLib.parseHttpHdr(cdisp)
                if 'filename' not in parts:
                    msg = "Missing or invalid Content-Disposition header in HTTP response"
                    raise Exception(msg)
                fname = os.path.join(fname,
                                     os.path.basename(parts['filename']))

            # Dump the data into the target file
            readf = functools.partial(resp.read, 65536)
            with open(fname, 'wb') as f:
                for buf in iter(readf, ''):
                    f.write(buf)

            return ngamsStatus.dummy_success_stat(host_id)
Ejemplo n.º 2
0
def _checkFileAccess(srvObj,
                     reqPropsObj,
                     httpRef,
                     fileId,
                     fileVersion=-1,
                     diskId=""):
    """
    Check if a file is accessible either on the local host or on a remotely
    located host.

    srvObj:         Instance of the server 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).

    fileId:         File ID (string).

    fileVersion:    File Version (integer).

    diskId:         Disk ID (string).

    Returns:        Returns message indicating if the file is available
                    (string).
    """
    T = TRACE()

    logger.debug("Checking for access to file with ID: %s", fileId)

    # Check if the file is located on this host, or if the request should be
    # forwarded (if this server should act as proxy).
    location, fileHost, ipAddress, filePortNo, mountPoint, filename, fileId,\
              fileVersion, mimeType =\
              ngamsFileUtils.locateArchiveFile(srvObj, fileId, fileVersion,
                                               diskId)

    if (location != NGAMS_HOST_LOCAL):
        # Go and get it!
        host, port = srvObj.get_remote_server_endpoint(fileHost)
        pars = (('file_access', fileId), ('file_version', fileVersion),
                ('disk_id', diskId))
        resp = ngamsHttpUtils.httpGet(host, port, 'STATUS', pars, timeout=60)
        with contextlib.closing(resp):
            return ngamsStatus.to_status(resp, fileHost, 'STATUS').getMessage()

    else:
        # First check if this system allows for Retrieve Requests.
        if (not srvObj.getCfg().getAllowRetrieveReq()):
            msg = genLog("NGAMS_INFO_SERVICE_UNAVAIL", ["File Retrieval"])
        else:
            fileHost = "%s:%d" % (getHostName(), filePortNo)
            msg = genLog("NGAMS_INFO_FILE_AVAIL",
                         [fileId + "/Version: " + str(fileVersion), fileHost])
        return msg
Ejemplo n.º 3
0
    def get_status(self, cmd, pars=[], hdrs=[]):
        """
        Sends a GET command to the first available NGAS server, receives the
        reply and returns it as a ngamsStatus object.
        """

        resp, host, port = self._get(cmd, pars, hdrs)
        host_id = "%s:%d" % (host, port)

        # If the reply is a ngamsStatus document read it and return it
        return ngamsStatus.to_status(resp, host_id, cmd)
Ejemplo n.º 4
0
    def status(self, pars=[], output=None):
        """
        Request a general status from the NG/AMS Server
        associated to the object.

        Returns:     NG/AMS Status object (ngamsStatus).
        """
        if 'file_list' in [p[0] for p in pars]:
            resp, host, port = self._get(NGAMS_STATUS_CMD, pars=pars)
            if resp.status != NGAMS_HTTP_SUCCESS:
                return ngamsStatus.to_status(resp, '%s:%d' % (host, port),
                                             'STATUS')

            output = output or 'file_list.xml.gz'
            with open(output, 'wb') as fout, contextlib.closing(resp):
                shutil.copyfileobj(resp, fout)
            return ngamsStatus.dummy_success_stat("%s:%d" % (host, port))

        return self.get_status(NGAMS_STATUS_CMD, pars=pars)
Ejemplo n.º 5
0
def _create_remote_subscriptions(srvObj, stop_evt):
    """
    Creates subscriptions in remote servers so they push their data into
    ours.
    """

    subscriptions_in_cfg = srvObj.cfg.getSubscriptionsDic()
    subscriptions = [v for _, v in subscriptions_in_cfg.items()]
    subscriptions_created = 0

    while True:

        # Done with all of them
        if not subscriptions:
            break

        # Iterate over copy, since we modify the original inside the loop
        for subscrObj in list(subscriptions):

            if (not srvObj.getThreadRunPermission()):
                logger.info("Terminating Subscriber thread ...")
                return

            our_host, our_port = srvObj.get_self_endpoint()
            subs_host, subs_port = subscrObj.getHostId(), subscrObj.getPortNo()

            # Not subscribing to ourselves
            if srvObj.is_it_us(subs_host, subs_port):
                logger.warning(
                    "Skipping subscription to %s:%d because that's us",
                    subs_host, subs_port)
                return

            # Create the URL that needs to be set on the remote end so we
            # get subscribed to it.
            # TODO: include reverse proxy information when we add support
            # TODO: hardcoded http will need to be changed when we add support
            #       for https
            url = 'http://%s:%d/%s' % (our_host, our_port, subscrObj.getUrl()
                                       or 'QARCHIVE')
            logger.info("Creating subscription to %s:%d with url=%s",
                        subs_host, subs_port, url)

            pars = [["subscr_id", url], ["priority",
                                         subscrObj.getPriority()],
                    ["url", url], ["start_date",
                                   toiso8601(local=True)]]
            if subscrObj.getFilterPi():
                pars.append(["filter_plug_in", subscrObj.getFilterPi()])
            if subscrObj.getFilterPiPars():
                pars.append(["plug_in_pars", subscrObj.getFilterPiPars()])

            try:
                # Issue SUBSCRIBE command
                resp = ngamsHttpUtils.httpGet(subs_host,
                                              subs_port,
                                              cmd=NGAMS_SUBSCRIBE_CMD,
                                              pars=pars)
                with contextlib.closing(resp):
                    stat = ngamsStatus.to_status(resp, subscrObj.getHostId(),
                                                 NGAMS_SUBSCRIBE_CMD)

                if stat.getStatus() != NGAMS_SUCCESS:
                    msg = "Unsuccessful NGAS XML response. Status: %s, message: %s. Will try again later"
                    logger.warning(msg, stat.getStatus(), stat.getMessage())
                    continue

                subscriptions_created += 1
                logger.info("Successfully subscribed to %s:%d with url=%s",
                            subs_host, subs_port, subscrObj.getUrl())

                # Remember to unsubscribe when going Offline.
                srvObj.getSubscrStatusList().append(subscrObj)
                subscriptions.remove(subscrObj)

            except:
                logger.exception(
                    "Error while adding subscription, will try later")

        if stop_evt.wait(10):
            return

    if subscriptions_created:
        logger.info("Successfully established %d Subscription(s)",
                    subscriptions_created)
    else:
        logger.info("No Subscriptions established")
Ejemplo n.º 6
0
def handleOffline(srvObj, reqPropsObj=None):
    """
    Carry out the actions to put the system in Offline state (Standby).

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

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

    stopJanitorThr:  Setting this to 0, the function will not try to
                     stop the Janitor Thread. The reason for this is that
                     the Janitor Thread may bring the server to Offline
                     (integer/0|1).

    Returns:         Void.
    """
    # Stop/delete Janitor Thread + Data Check Thread + inform other
    # possible threads to stop execution (if running).
    srvObj.stopJanitorThread()
    srvObj.stopDataCheckThread()
    ngamsSubscriptionThread.stopSubscriptionThread(srvObj)
    srvObj.stopUserServiceThread()
    srvObj.stopMirControlThread()
    srvObj.stopCacheControlThread()
    srvObj.setThreadRunPermission(0)
    if srvObj.getCfg().getSubscrEnable():
        srvObj.remote_subscription_creation_evt.set()

    logger.debug("Prepare NG/AMS for Offline State ...")

    # Unsubscribe possible subscriptions. This is tried only once.
    if (srvObj.getCfg().getAutoUnsubscribe()):
        for subscrObj in srvObj.getSubscrStatusList():
            subs_host, subs_port = subscrObj.getHostId(), subscrObj.getPortNo()
            try:
                resp = ngamsHttpUtils.httpGet(
                    subs_host, subs_port, NGAMS_UNSUBSCRIBE_CMD,
                    [["url", subscrObj.getId()]])
                with contextlib.closing(resp):
                    stat = ngamsStatus.to_status(
                        resp, "%s:%d" % (subs_host, subs_port),
                        NGAMS_UNSUBSCRIBE_CMD)
                if stat.getStatus() != NGAMS_SUCCESS:
                    logger.error("Error when unsubscribing from %s:%d: %s",
                                 subs_host, subs_port, stat.getMessage())
            except Exception:
                msg = "Problem occurred while cancelling subscription " +\
                      "(host/port): %s/%d. Subscriber ID: %s"
                logger.exception(msg, subscrObj.getHostId(),
                                 subscrObj.getPortNo(), subscrObj.getId())
        srvObj.resetSubscrStatusList()

    # Check if there are files located in the Staging Areas of the
    # Disks. In case yes, move these to the Back-Log Area to have them
    # treated at a later stage.
    checkStagingAreas(srvObj)

    # Dump disk info on all disks, invoke the Offline Plug-In to prepare the
    # disks for offline, and mark the disks as unmounted in the DB.
    ngamsDiskUtils.dumpDiskInfoAllDisks(srvObj.getHostId(), srvObj.getDb(),
                                        srvObj.getCfg())
    plugIn = srvObj.getCfg().getOfflinePlugIn()
    if (srvObj.getCfg().getSimulation() == 0):
        logger.info("Invoking System Offline Plug-In: %s(srvObj, reqPropsObj)",
                    plugIn)
        plugInMethod = loadPlugInEntryPoint(plugIn)
        plugInRes = plugInMethod(srvObj, reqPropsObj)
    else:
        pass
    ngamsDiskUtils.markDisksAsUnmountedInDb(srvObj.getHostId(), srvObj.getDb(),
                                            srvObj.getCfg())

    # Send out possible Retained Email Notification Messages.
    flushMsg = "NOTE: Distribution of retained Email Notification Messages " +\
               "forced at Offline"
    ngamsNotification.checkNotifRetBuf(srvObj.getHostId(), srvObj.getCfg(), 1,
                                       flushMsg)

    logger.info("NG/AMS prepared for Offline State")
Ejemplo n.º 7
0
def _create_remote_subscriptions(srvObj, stop_evt):
    """
    Creates subscriptions in remote servers so they push their data into
    ours.
    """

    subscriptions_in_cfg = srvObj.cfg.getSubscriptionsDic()
    subscriptions = [v for _, v in subscriptions_in_cfg.items()]
    subscriptions_created = 0

    def mark_as_active(s):
        # Removes s from list of subscriptions pending creation, and
        # ensures the corresponding UNSUBSCRIBE command will be called
        # at server shutdown
        srvObj.getSubscrStatusList().append(s)
        subscriptions.remove(s)

    while True:

        # Done with all of them
        if not subscriptions:
            break

        # Iterate over copy, since we modify the original inside the loop
        for subscrObj in list(subscriptions):

            if stop_evt.is_set():
                logger.info("Terminating Subscriber thread ...")
                return

            our_host, our_port = srvObj.get_self_endpoint()
            subs_host, subs_port = subscrObj.getHostId(), subscrObj.getPortNo()

            # Not subscribing to ourselves
            if srvObj.is_it_us(subs_host, subs_port):
                logger.warning("Skipping subscription to %s:%d because that's us", subs_host, subs_port)
                continue

            # Because properly supporting the "Command" configuration mechanism
            # still requires some more work, we prefer the "SubscriberUrl"
            # attribute as the main source of URL information.
            # We still support "Command", but with the following caveats:
            #  * TODO: include reverse proxy information when we add support
            #  * TODO: hardcoded http will need to be changed when we add support
            #          for https
            #  * TODO: fails with IpAddress == '0.0.0.0'
            url = subscrObj.getUrl()
            if not url:
                url = 'http://%s:%d/%s' % (our_host, our_port, subscrObj.command or 'QARCHIVE')
            logger.info("Creating subscription to %s:%d with url=%s", subs_host, subs_port, url)

            pars = [["subscr_id", subscrObj.getId()],
                    ["priority", subscrObj.getPriority()],
                    ["url",      url],
                    ["start_date", toiso8601(local=True)]]
            if subscrObj.getFilterPi():
                pars.append(["filter_plug_in", subscrObj.getFilterPi()])
            if subscrObj.getFilterPiPars():
                pars.append(["plug_in_pars", subscrObj.getFilterPiPars()])

            try:
                # Issue SUBSCRIBE command
                resp = ngamsHttpUtils.httpGet(subs_host, subs_port, cmd=NGAMS_SUBSCRIBE_CMD, pars=pars)
                with contextlib.closing(resp):
                    stat = ngamsStatus.to_status(resp, subscrObj.getHostId(), NGAMS_SUBSCRIBE_CMD)

                if stat.getStatus() != NGAMS_SUCCESS:
                    if stat.http_status == 409:
                        short_msg = "Different subscription with ID '%s' already exists, giving up"
                        long_msg = (
                            "NGAS attempted to create an automatic subscription "
                            "with ID=%s to obtain data from %s:%d, but the remote server "
                            "already has a subscription registered with the same ID, "
                            "but different details.\n\n"
                            "Instead of retrying to create this subscription over and over, "
                            "this server will give up now. To fix this either remove "
                            "the remote subscription, or change the ID of the subscription to be created "
                            "in the local server configuration."
                        )
                        logger.error(short_msg, subscrObj.getId())
                        ngamsNotification.notify(
                            srvObj.host_id, srvObj.cfg, NGAMS_NOTIF_ERROR,
                            "Automatic subscription cannot be created",
                            long_msg % (subscrObj.getId(), subs_host, subs_port),
                            force=True)
                        mark_as_active(subscrObj)
                        continue
                    else:
                        msg = "Unsuccessful NGAS XML response. Status: %s, message: %s. Will try again later"
                        logger.warning(msg, stat.getStatus(), stat.getMessage())
                        continue

                subscriptions_created += 1
                logger.info("Successfully subscribed to %s:%d with url=%s", subs_host, subs_port, subscrObj.getUrl())
                mark_as_active(subscrObj)

            except:
                logger.exception("Error while adding subscription, will try later")

        if stop_evt.wait(10):
            return

    if subscriptions_created:
        logger.info("Successfully established %d Subscription(s)", subscriptions_created)
    else:
        logger.info("No Subscriptions established")