コード例 #1
0
def testGirderInputSpec(models):
    # Set an API_URL so we can use the spec outside of a rest request
    Setting().set(PluginSettings.API_URL, 'http://127.0.0.1')
    Setting().set(PluginSettings.DIRECT_PATH, True)

    spec = utils.girderInputSpec(models['adminFolder'], resourceType='folder')
    assert spec['id'] == str(models['adminFolder']['_id'])
    assert spec['resource_type'] == 'folder'
    assert not spec['fetch_parent']
    assert 'direct_path' not in spec

    spec = utils.girderInputSpec(models['sampleFile'], resourceType='file')
    assert spec['id'] == str(models['sampleFile']['_id'])
    assert spec['resource_type'] == 'file'
    assert not spec['fetch_parent']
    assert 'direct_path' in spec

    Setting().set(PluginSettings.DIRECT_PATH, False)
    spec = utils.girderInputSpec(models['sampleFile'], resourceType='file')
    assert not spec['fetch_parent']
    assert 'direct_path' not in spec

    Setting().set(PluginSettings.DIRECT_PATH, True)
    spec = utils.girderInputSpec(models['sampleFile'], resourceType='file', fetchParent=True)
    assert spec['fetch_parent']
    assert 'direct_path' not in spec
コード例 #2
0
    def _transformInputs(self, inputs, token):
        """
        Validates and sanitizes the input bindings. If they are Girder inputs, adds
        the necessary token info. If the token does not allow DATA_READ, or if the user
        does not have read access to the resource, raises an AccessException.
        """
        transformed = {}
        for k, v in six.viewitems(inputs):
            if v['mode'] == 'girder':
                ensureTokenScopes(token, TokenScope.DATA_READ)
                rtype = v.get('resource_type', 'file')
                if rtype not in {'file', 'item', 'folder'}:
                    raise ValidationException(
                        'Invalid input resource_type: %s.' % rtype)

                resource = self.model(rtype).load(v['id'],
                                                  level=AccessType.READ,
                                                  user=self.getCurrentUser(),
                                                  exc=True)

                transformed[k] = utils.girderInputSpec(resource,
                                                       resourceType=rtype,
                                                       token=token,
                                                       dataFormat='none')
            elif v['mode'] == 'inline':
                transformed[k] = {'mode': 'inline', 'data': v['data']}
            else:
                raise ValidationException('Invalid input mode: %s.' %
                                          v['mode'])

        return transformed
コード例 #3
0
ファイル: rest.py プロジェクト: manthey/girder
    def _transformInputs(self, inputs, token):
        """
        Validates and sanitizes the input bindings. If they are Girder inputs, adds
        the necessary token info. If the token does not allow DATA_READ, or if the user
        does not have read access to the resource, raises an AccessException.
        """
        transformed = {}
        for k, v in six.viewitems(inputs):
            if v['mode'] == 'girder':
                ensureTokenScopes(token, TokenScope.DATA_READ)
                rtype = v.get('resource_type', 'file')
                if rtype not in {'file', 'item', 'folder'}:
                    raise ValidationException('Invalid input resource_type: %s.' % rtype)

                resource = self.model(rtype).load(
                    v['id'], level=AccessType.READ, user=self.getCurrentUser(), exc=True)

                transformed[k] = utils.girderInputSpec(
                    resource, resourceType=rtype, token=token, dataFormat='none')
            elif v['mode'] == 'inline':
                transformed[k] = {
                    'mode': 'inline',
                    'data': v['data']
                }
            else:
                raise ValidationException('Invalid input mode: %s.' % v['mode'])

        return transformed
コード例 #4
0
def testWorkerStatusEndpoint(server, models):
    # Create a job to be handled by the worker plugin
    job = Job().createJob(
        title='title', type='foo', handler='worker_handler',
        user=models['admin'], public=False, args=(), kwargs={})

    job['kwargs'] = {
        'jobInfo': utils.jobInfoSpec(job),
        'inputs': [
            utils.girderInputSpec(models['adminFolder'], resourceType='folder')
        ],
        'outputs': [
            utils.girderOutputSpec(models['adminFolder'], token=models['adminToken'])
        ]
    }
    job = Job().save(job)
    assert job['status'] == JobStatus.INACTIVE

    # Schedule the job
    with mock.patch('celery.Celery') as celeryMock:
        instance = celeryMock.return_value
        instance.send_task.return_value = FakeAsyncResult()

        Job().scheduleJob(job)

    # Call the worker status endpoint
    resp = server.request('/worker/status', method='GET', user=models['admin'])
    assertStatusOk(resp)
    for key in ['report', 'stats', 'ping', 'active', 'reserved']:
        assert key in resp.json
コード例 #5
0
def testWorkerCancel(models):
    jobModel = Job()
    job = jobModel.createJob(
        title='title', type='foo', handler='worker_handler',
        user=models['admin'], public=False, args=(), kwargs={})

    job['kwargs'] = {
        'jobInfo': utils.jobInfoSpec(job),
        'inputs': [
            utils.girderInputSpec(models['adminFolder'], resourceType='folder')
        ],
        'outputs': [
            utils.girderOutputSpec(models['adminFolder'], token=models['adminToken'])
        ]
    }
    job = jobModel.save(job)
    assert job['status'] == JobStatus.INACTIVE

    # Schedule the job, make sure it is sent to celery
    with mock.patch('celery.Celery') as celeryMock, \
            mock.patch('girder_worker.girder_plugin.event_handlers.AsyncResult') as asyncResult:
        instance = celeryMock.return_value
        instance.send_task.return_value = FakeAsyncResult()

        jobModel.scheduleJob(job)
        jobModel.cancelJob(job)

        asyncResult.assert_called_with('fake_id', app=mock.ANY)
        # Check we called revoke
        asyncResult.return_value.revoke.assert_called_once()
        job = jobModel.load(job['_id'], force=True)
        assert job['status'] == CustomJobStatus.CANCELING
コード例 #6
0
def testWorker(server, models):
    # Test the settings
    resp = server.request('/system/setting', method='PUT', params={
        'list': json.dumps([{
            'key': PluginSettings.BROKER,
            'value': 'amqp://[email protected]'
        }, {
            'key': PluginSettings.BACKEND,
            'value': 'amqp://[email protected]'
        }])
    }, user=models['admin'])
    assertStatusOk(resp)

    # Create a job to be handled by the worker plugin
    jobModel = Job()
    job = jobModel.createJob(
        title='title', type='foo', handler='worker_handler',
        user=models['admin'], public=False, args=(), kwargs={})

    job['kwargs'] = {
        'jobInfo': utils.jobInfoSpec(job),
        'inputs': [
            utils.girderInputSpec(models['adminFolder'], resourceType='folder')
        ],
        'outputs': [
            utils.girderOutputSpec(models['adminFolder'], token=models['adminToken'])
        ]
    }
    job = jobModel.save(job)
    assert job['status'] == JobStatus.INACTIVE

    # Schedule the job, make sure it is sent to celery
    with mock.patch('celery.Celery') as celeryMock:
        instance = celeryMock.return_value
        instance.send_task.return_value = FakeAsyncResult()

        jobModel.scheduleJob(job)

        # Make sure we sent the job to celery
        assert len(celeryMock.mock_calls) == 2
        assert celeryMock.mock_calls[0][1] == ('girder_worker',)
        assert celeryMock.mock_calls[0][2] == {
            'broker': 'amqp://[email protected]',
            'backend': 'amqp://[email protected]'
        }

        sendTaskCalls = celeryMock.return_value.send_task.mock_calls

        assert len(sendTaskCalls) == 1
        assert sendTaskCalls[0][1] == (
            'girder_worker.run', job['args'], job['kwargs'])

        assert 'headers' in sendTaskCalls[0][2]
        assert 'jobInfoSpec' in sendTaskCalls[0][2]['headers']

        # Make sure we got and saved the celery task id
        job = jobModel.load(job['_id'], force=True)
        assert job['celeryTaskId'] == 'fake_id'
        assert job['status'] == JobStatus.QUEUED
コード例 #7
0
def testWorkerDifferentTask(server, models):
    # Test the settings
    resp = server.request('/system/setting', method='PUT', params={
        'key': PluginSettings.API_URL,
        'value': 'bad value'
    }, user=models['admin'])
    assertStatus(resp, 400)
    assert resp.json['message'] == 'API URL must start with http:// or https://.'

    resp = server.request('/system/setting', method='PUT', params={
        'list': json.dumps([{
            'key': PluginSettings.BROKER,
            'value': 'amqp://[email protected]'
        }, {
            'key': PluginSettings.BACKEND,
            'value': 'amqp://[email protected]'
        }])
    }, user=models['admin'])
    assertStatusOk(resp)

    # Create a job to be handled by the worker plugin
    jobModel = Job()
    job = jobModel.createJob(
        title='title', type='foo', handler='worker_handler',
        user=models['admin'], public=False, args=(), kwargs={},
        otherFields={
            'celeryTaskName': 'some_other.task',
            'celeryQueue': 'my_other_q'
        })

    job['kwargs'] = {
        'jobInfo': utils.jobInfoSpec(job),
        'inputs': [
            utils.girderInputSpec(models['adminFolder'], resourceType='folder')
        ],
        'outputs': [
            utils.girderOutputSpec(models['adminFolder'], token=models['adminToken'])
        ]
    }
    job = jobModel.save(job)

    # Schedule the job, make sure it is sent to celery
    app = celery.getCeleryApp()
    with mock.patch.object(app, 'send_task') as sendTask:
        sendTask.return_value = FakeAsyncResult()

        jobModel.scheduleJob(job)

        sendTaskCalls = sendTask.mock_calls
        assert len(sendTaskCalls) == 1
        assert sendTaskCalls[0][1] == (
            'some_other.task', job['args'], job['kwargs'])
        assert 'queue' in sendTaskCalls[0][2]
        assert sendTaskCalls[0][2]['queue'] == 'my_other_q'
コード例 #8
0
ファイル: submission.py プロジェクト: girder/covalic
    def scoreSubmission(self, submission, apiUrl):
        """
        Run a Girder Worker job to score a submission.
        """
        phase = Phase().load(submission['phaseId'], force=True)
        folder = Folder().load(submission['folderId'], force=True)
        user = User().load(submission['creatorId'], force=True)

        otherFields = {}
        if 'overallScore' in submission:
            otherFields['rescoring'] = True

        jobTitle = '%s submission: %s' % (phase['name'], folder['name'])
        job = Job().createJob(
            title=jobTitle, type='covalic_score', handler='worker_handler', user=user,
            otherFields=otherFields)

        scoreUserId = Setting().get(PluginSettings.SCORING_USER_ID)
        if not scoreUserId:
            raise GirderException(
                'No scoring user ID is set. Please set one on the plugin configuration page.')

        scoreUser = User().load(scoreUserId, force=True)
        if not scoreUser:
            raise GirderException('Invalid scoring user setting (%s).' % scoreUserId)

        scoreToken = Token().createToken(user=scoreUser, days=7)
        Folder().setUserAccess(
            folder, user=scoreUser, level=AccessType.READ, save=True)

        groundTruth = Folder().load(phase['groundTruthFolderId'], force=True)

        if not Phase().hasAccess(phase, user=scoreUser, level=AccessType.ADMIN):
            Phase().setUserAccess(
                phase, user=scoreUser, level=AccessType.ADMIN, save=True)

        if not Folder().hasAccess(groundTruth, user=scoreUser, level=AccessType.READ):
            Folder().setUserAccess(
                groundTruth, user=scoreUser, level=AccessType.READ, save=True)

        task = phase.get('scoreTask', {})
        image = task.get('dockerImage') or 'girder/covalic-metrics:latest'
        containerArgs = task.get('dockerArgs') or [
            '--groundtruth=$input{groundtruth}',
            '--submission=$input{submission}'
        ]

        kwargs = {
            'task': {
                'name': jobTitle,
                'mode': 'docker',
                'docker_image': image,
                'container_args': containerArgs,
                'inputs': [{
                    'id': 'submission',
                    'type': 'string',
                    'format': 'text',
                    'target': 'filepath',
                    'filename': 'submission.zip'
                }, {
                    'id': 'groundtruth',
                    'type': 'string',
                    'format': 'text',
                    'target': 'filepath',
                    'filename': 'groundtruth.zip'
                }],
                'outputs': [{
                    'id': '_stdout',
                    'format': 'string',
                    'type': 'string'
                }]
            },
            'inputs': {
                'submission': utils.girderInputSpec(
                    folder, 'folder', token=scoreToken),
                'groundtruth': utils.girderInputSpec(
                    groundTruth, 'folder', token=scoreToken)
            },
            'outputs': {
                '_stdout': {
                    'mode': 'http',
                    'method': 'POST',
                    'format': 'string',
                    'url': '/'.join((apiUrl, 'covalic_submission',
                                     str(submission['_id']), 'score')),
                    'headers': {'Girder-Token': scoreToken['_id']}
                }
            },
            'jobInfo': utils.jobInfoSpec(job),
            'validate': False,
            'auto_convert': False,
            'cleanup': True
        }
        job['kwargs'] = kwargs
        job['covalicSubmissionId'] = submission['_id']
        job = Job().save(job)
        Job().scheduleJob(job)

        submission['jobId'] = job['_id']
        return self.save(submission, validate=False)