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
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)
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)
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']
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
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
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
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 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
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)
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.