Exemple #1
0
def cancel(event):
    """
    This is bound to the "jobs.cancel" event, and will be triggered any time
    a job is canceled. This handler will process any job that has the
    handler field set to "worker_handler".
    """
    job = event.info
    if job['handler'] in ['worker_handler', 'celery_handler']:
        # Stop event propagation and prevent default, we are using a custom state
        event.stopPropagation().preventDefault()

        celeryTaskId = job.get('celeryTaskId')

        if celeryTaskId is None:
            msg = ("Unable to cancel Celery task. Job '%s' doesn't have a Celery task id."
                   % job['_id'])
            logger.warn(msg)
            return

        if job['status'] not in [CustomJobStatus.CANCELING, JobStatus.CANCELED,
                                 JobStatus.SUCCESS, JobStatus.ERROR]:
            # Set the job status to canceling
            Job().updateJob(job, status=CustomJobStatus.CANCELING)

            # Send the revoke request.
            asyncResult = AsyncResult(celeryTaskId, app=getCeleryApp())
            asyncResult.revoke()
def getJobResult(self, job):
    user = self.getCurrentUser()
    if not job.get('public', False):
        if user:
            JobModel().requireAccess(job, user, level=AccessType.READ)
        else:
            self.ensureTokenScopes('jobs.job_' + str(job['_id']))

    if 'result' in job:
        return job['result']

    celeryTaskId = job.get('celeryTaskId')
    if celeryTaskId is None:
        logger.warn("Job '{}' doesn't have a Celery task id.".format(
            job['_id']))
        return
    if job['status'] != JobStatus.SUCCESS:
        logger.warn("Job '{}' hasn't completed sucessfully.".format(
            job['_id']))
    asyncResult = getCeleryApp().AsyncResult(celeryTaskId)
    try:
        result = asyncResult.get()
    except Exception as ex:
        result = str(ex)
    return result
Exemple #3
0
    def nearestNeighborIndex(item, user, descriptorIndex):
        """
        Get the nearest neighbor index from a given item and descriptor index.

        :param item: Item to find the nn index from, usually the item that the
            user is performing the nearest neighbors search on.
        :param user: The owner of the .smqtk folder.
        :param descriptorIndex: The relevant descriptor index.
        """
        folder = ModelImporter.model('folder')

        _GirderDataElement = functools.partial(GirderDataElement,
                                               api_root=getApiUrl(),
                                               token=getCurrentToken()['_id'])

        smqtkFolder = folder.createFolder(folder.load(item['folderId'], user=user), '.smqtk',
                                          reuseExisting=True)

        try:
            meanVecFileId = localSmqtkFileIdFromName(smqtkFolder, 'mean_vec.npy')
            rotationFileId = localSmqtkFileIdFromName(smqtkFolder, 'rotation.npy')
            hash2uuidsFileId = localSmqtkFileIdFromName(smqtkFolder, 'hash2uuids.pickle')
        except Exception:
            logger.warn('SMQTK files didn\'t exist for performing NN on %s' % item['_id'])
            return None

        # TODO Should these be Girder data elements? Unnecessary HTTP requests.
        functor = ItqFunctor(mean_vec_cache=_GirderDataElement(meanVecFileId),
                             rotation_cache=_GirderDataElement(rotationFileId))

        hash2uuidsKV = MemoryKeyValueStore(_GirderDataElement(hash2uuidsFileId))

        return LSHNearestNeighborIndex(functor, descriptorIndex,
                                       hash2uuidsKV, read_only=True)
Exemple #4
0
    def _snapshotRecursive(self, old: Optional[Path], crt: Path,
                           new: Path) -> None:
        for c in crt.iterdir():
            newc = new / c.name
            oldc = None if old is None else old / c.name
            crtc = crt / c.name

            if oldc is not None:
                if not oldc.exists():
                    oldc = None
                else:
                    if crtc.is_dir() != oldc.is_dir():
                        # either oldc was a dir and is now a file or the other way around
                        oldc = None

            if c.is_dir():
                newc.mkdir()
                self._snapshotRecursive(oldc, crtc, newc)
            else:
                crtcstr = crtc.absolute().as_posix()
                newcstr = newc.absolute().as_posix()
                try:
                    os.link(crtcstr, newcstr)
                except:  # noqa: E722
                    logger.warn('link %s -> %s' % (crtcstr, newcstr))
                    raise
                shutil.copystat(crtcstr, newcstr)
    def nearestNeighborIndex(item, user, descriptorSet):
        """
        Get the nearest neighbor index from a given item and descriptor set.

        :param item: Item to find the nn index from, usually the item that the
            user is performing the nearest neighbors search on.
        :param user: The owner of the .smqtk folder.
        :param descriptorSet: The relevant descriptor set.
        """
        folder = ModelImporter.model('folder')

        _GirderDataElement = functools.partial(GirderDataElement,
                                               api_root=getApiUrl(),
                                               token=getCurrentToken()['_id'])

        smqtkFolder = folder.createFolder(folder.load(item['folderId'], user=user), '.smqtk',
                                          reuseExisting=True)

        try:
            meanVecFileId = localSmqtkFileIdFromName(smqtkFolder, 'mean_vec.npy')
            rotationFileId = localSmqtkFileIdFromName(smqtkFolder, 'rotation.npy')
            hash2uuidsFileId = localSmqtkFileIdFromName(smqtkFolder, 'hash2uuids.pickle')
        except Exception:
            logger.warn('SMQTK files didn\'t exist for performing NN on %s' % item['_id'])
            return None

        # TODO Should these be Girder data elements? Unnecessary HTTP requests.
        functor = ItqFunctor(mean_vec_cache=_GirderDataElement(meanVecFileId),
                             rotation_cache=_GirderDataElement(rotationFileId))

        hash2uuidsKV = MemoryKeyValueStore(_GirderDataElement(hash2uuidsFileId))

        return LSHNearestNeighborIndex(functor, descriptorSet,
                                       hash2uuidsKV, read_only=True)
Exemple #6
0
def cancel(event):
    """
    This is bound to the "jobs.cancel" event, and will be triggered any time
    a job is canceled. This handler will process any job that has the
    handler field set to "worker_handler".
    """
    job = event.info
    if job['handler'] in ['worker_handler', 'celery_handler']:
        # Stop event propagation and prevent default, we are using a custom state
        event.stopPropagation().preventDefault()

        celeryTaskId = job.get('celeryTaskId')

        if celeryTaskId is None:
            msg = ("Unable to cancel Celery task. Job '%s' doesn't have a Celery task id."
                   % job['_id'])
            logger.warn(msg)
            return

        if job['status'] not in [CustomJobStatus.CANCELING, JobStatus.CANCELED,
                                 JobStatus.SUCCESS, JobStatus.ERROR]:
            # Set the job status to canceling
            ModelImporter.model('job', 'jobs').updateJob(job, status=CustomJobStatus.CANCELING)

            # Send the revoke request.
            asyncResult = AsyncResult(celeryTaskId, app=getCeleryApp())
            asyncResult.revoke()
    def _authenticateApiKey(self, username, password):
        if not Setting().get(SettingKey.API_KEYS):
            logger.warn('API key functionality is disabled')
            return False

        token_user, token = ApiKeyModel().createToken(password[4:], days=7)
        user = self._getUser(username)
        return token_user.get('_id', 'no_token') == user['_id']
Exemple #8
0
    def refine(self, params):
        sid = str(params['item']['_id'])
        pos_uuids = params['pos_uuids']
        neg_uuids = params['neg_uuids'] if params[
            'neg_uuids'] is not None else []

        if len(pos_uuids) == 0:
            raise RestException('No positive UUIDs given.')

        with self.controller:
            if not self.controller.has_session_uuid(sid):
                raise RestException('Session ID %s not found.' % sid, 404)
            iqrs = self.controller.get_session(sid)
            iqrs.lock.acquire()  # lock BEFORE releasing controller

        descriptor_index = self._descriptorIndexFromSessionId(sid)
        neighbor_index = self._nearestNeighborIndex(sid, descriptor_index)

        if descriptor_index is None or neighbor_index is None:
            logger.error(
                'Unable to compute descriptor or neighbor index from sid %s.' %
                sid)
            raise RestException(
                'Unable to compute descriptor or neighbor index from sid %s.' %
                sid, 500)

        # Get appropriate descriptor elements from index for
        # setting new adjudication state.
        try:
            pos_descrs = set(descriptor_index.get_many_descriptors(pos_uuids))
            neg_descrs = set(descriptor_index.get_many_descriptors(neg_uuids))
        except KeyError as ex:
            logger.warn(traceback.format_exc())
            raise RestException('Descriptor UUID %s not found in index.' % ex,
                                404)

        # if a new classifier should be made upon the next
        # classification request.
        diff_pos = pos_descrs.symmetric_difference(iqrs.positive_descriptors)
        diff_neg = neg_descrs.symmetric_difference(iqrs.negative_descriptors)

        if diff_pos or diff_neg:
            logger.debug("[%s] session Classifier dirty", sid)
            self.session_classifier_dirty[sid] = True

        logger.info("[%s] Setting adjudications", sid)
        iqrs.positive_descriptors = pos_descrs
        iqrs.negative_descriptors = neg_descrs

        logger.info("[%s] Updating working index", sid)
        iqrs.update_working_index(neighbor_index)

        logger.info("[%s] Refining", sid)
        iqrs.refine()

        iqrs.lock.release()
        return sid
Exemple #9
0
    def refine(self, params):
        sid = str(params['item']['_id'])
        pos_uuids = params['pos_uuids']
        neg_uuids = params['neg_uuids'] if params['neg_uuids'] is not None else []

        if len(pos_uuids) == 0:
            raise RestException('No positive UUIDs given.')

        with self.controller:
            if not self.controller.has_session_uuid(sid):
                raise RestException('Session ID %s not found.' % sid, 404)
            iqrs = self.controller.get_session(sid)
            iqrs.lock.acquire()  # lock BEFORE releasing controller

        try:
            descriptor_index = self._descriptorIndexFromSessionId(sid)
            neighbor_index = self._nearestNeighborIndex(sid, descriptor_index)

            if descriptor_index is None or neighbor_index is None:
                logger.error('Unable to compute descriptor or neighbor index from sid %s.' % sid)
                raise RestException('Unable to compute descriptor or neighbor index from sid %s.' % sid, 500)

            # Get appropriate descriptor elements from index for
            # setting new adjudication state.
            try:
                pos_descrs = set(descriptor_index.get_many_descriptors(pos_uuids))
                neg_descrs = set(descriptor_index.get_many_descriptors(neg_uuids))
            except KeyError as ex:
                logger.warn(traceback.format_exc())
                raise RestException('Descriptor UUID %s not found in index.' % ex, 404)

            # if a new classifier should be made upon the next
            # classification request.
            diff_pos = pos_descrs.symmetric_difference(iqrs.positive_descriptors)
            diff_neg = neg_descrs.symmetric_difference(iqrs.negative_descriptors)

            if diff_pos or diff_neg:
                logger.debug("[%s] session Classifier dirty", sid)
                self.session_classifier_dirty[sid] = True

            logger.info("[%s] Setting adjudications", sid)
            iqrs.positive_descriptors = pos_descrs
            iqrs.negative_descriptors = neg_descrs

            logger.info("[%s] Updating working index", sid)
            iqrs.update_working_index(neighbor_index)

            logger.info("[%s] Refining", sid)
            iqrs.refine()

        finally:
            iqrs.lock.release()

        return sid
Exemple #10
0
def _runGCCommand(*args):
    p = subprocess.run(list(args),
                       stdout=subprocess.PIPE,
                       stderr=subprocess.PIPE)
    if p.returncode != 0:
        msg = 'Command %s failed with exit code %s: \n%s\n%s' % (
            args, p.returncode, p.stdout, p.stderr)
        logger.warn(msg)
        raise Exception(msg)
    logger.info('Output from command %s: %s, %s' % (args, p.stdout, p.stderr))
    return p
Exemple #11
0
    def setSessionReadOnly(self, sess):
        """
        Set the specified session to read only if possible.  Subclasses should
        implement the appropriate behavior.

        :param sess: the session to adjust.
        """
        try:
            sess.execute('SET SESSION TRANSACTION READ ONLY;')
        except sqlalchemy.exc.OperationalError:
            log.warn('Couldn\'t set session to read only')
            sess.rollback()
    def setSessionReadOnly(self, sess):
        """
        Set the specified session to read only if possible.  Subclasses should
        implement the appropriate behavior.

        :param sess: the session to adjust.
        """
        try:
            sess.execute('set default_transaction_read_only=on')
        except sqlalchemy.exc.OperationalError:
            log.warn('Couldn\'t set default_transaction to read_only')
            sess.rollback()
    def setSessionReadOnly(self, sess):
        """
        Set the specified session to read only if possible.  Subclasses should
        implement the appropriate behavior.

        :param sess: the session to adjust.
        """
        try:
            sess.execute('set default_transaction_read_only=on')
        except sqlalchemy.exc.OperationalError:
            log.warn('Couldn\'t set default_transaction to read_only')
            sess.rollback()
 def deleteFile(self, itemId):
     if self.lockModel.tryLockForDeletion(itemId):
         try:
             path = self.pathMapper.getPSPath(itemId)
             os.remove(path)
             self.lockModel.fileDeleted(itemId)
             return True
         except FileNotFoundError:
             # well, well, wasn't there to begin with
             logger.warn('File for %s did not exist' % itemId)
             self.lockModel.fileDeleted(itemId)
             return True
         finally:
             self.lockModel.unlockForDeletion(itemId)
     else:
         return False
Exemple #15
0
    def _loadTileSource(cls, item, **kwargs):
        if 'largeImage' not in item:
            raise TileSourceException('No large image file in this item.')
        if item['largeImage'].get('expected'):
            raise TileSourceException('The large image file for this item is '
                                      'still pending creation.')

        sourceName = item['largeImage']['sourceName']
        try:
            # First try to use the tilesource we recorded as the preferred one.
            # This is faster than trying to find the best source each time.
            tileSource = girder_tilesource.AvailableGirderTileSources[
                sourceName](item, **kwargs)
        except TileSourceException:
            # We could try any source
            # tileSource = girder_tilesource.getGirderTileSource(item, **kwargs)
            # but, instead, log that the original source no longer works are
            # reraise the exception
            logger.warn('The original tile source for item %s is not working' %
                        item['_id'])
            raise
        return tileSource
    def transfer(self):
        # this isn't very scalable and there isn't much wisdom in wasting a thread on a transfer
        # that is directed by another machine, but we waste an entire process or more on the
        # gridftp server processes anyway, so this may not quite be the bottleneck
        self._maybeStartServer()
        userEndpointId = self.server.getUserEndpointId(self.user)
        tc = self.clients.getUserTransferClient(self.user)

        tmpName = str(uuid.uuid4())
        transfer = TransferData(tc,
                                self._getSourceEndpointId(),
                                userEndpointId,
                                label=str(self.transferId))
        transfer['notify_on_succeeded'] = False
        transfer['notify_on_failed'] = False
        transfer['notify_on_inactive'] = False
        transfer.add_item(self._getSourcePath(), tmpName)
        res = tc.submit_transfer(transfer)
        if res['code'] != 'Accepted':
            raise Exception('Transfer submission failed: %s - %s' %
                            (res.code, res.message))
        taskId = res['task_id']
        self._updateTransfer(tmpName, taskId)
        while True:
            task = tc.get_task(taskId)
            status = task['status']
            if status == 'ACTIVE':
                # update bytes
                pass
            elif status == 'INACTIVE':
                # credential expiration
                # TODO: deal with this properly or ensure it does not happen
                msg = 'Credential expired for Globus task %s, transfer %s.' % (
                    taskId, self.transferId)
                logger.warn(msg)
                raise Exception(msg)
            elif status == 'SUCCEEDED':
                dir = os.path.dirname(self.psPath)
                try:
                    os.makedirs(dir)
                except OSError:
                    if not os.path.exists(dir):
                        raise Exception(
                            'Could not create transfer destination directory: %s'
                            % dir)
                shutil.move(
                    '%s/%s' % (self.server.getUserDir(self.user), tmpName),
                    self.psPath)
                return
            elif status == 'FAILED':
                if task['fatal_error']:
                    raise Exception(
                        'Globus transfer %s failed: %s' %
                        (self.transferId, task['fatal_error']['description']))
                else:
                    raise Exception(
                        'Globus transfer %s failed for unknown reasons' %
                        self.transferId)
            else:
                raise Exception(
                    'Unknown globus task status %s for transfer %s' %
                    (status, self.transferId))
            time.sleep(10)
Exemple #17
0
try:
    from girder import logger
except ImportError:
    import logging as logger
    logger.getLogger().setLevel(logger.INFO)
try:
    from libtiff import libtiff_ctypes
except ValueError as exc:
    # If the python libtiff module doesn't contain a pregenerated module for
    # the appropriate version of libtiff, it tries to generate a module from
    # the libtiff header file.  If it can't find this file (possibly because it
    # is in a virtual environment), it raises a ValueError instead of an
    # ImportError.  We convert this to an ImportError, so that we will print a
    # more lucid error message and just fail to load this one tile source
    # instead of failing to load the whole plugin.
    logger.warn(
        'Failed to import libtiff; try upgrading the python module (%s)' % exc)
    raise ImportError(str(exc))
try:
    import PIL.Image
except ImportError:
    PIL = None

# This suppress warnings about unknown tags
libtiff_ctypes.suppress_warnings()


def etreeToDict(t):
    """
    Convert an xml etree to a nested dictionary without schema names in the
    keys.