Пример #1
0
    def get(self, request, import_queue=None):  # pylint: disable=too-many-return-statements
        task_id = request.GET.get('task')
        result_format = request.GET.get('result')
        username = request.GET.get('username')
        user = self.request.user

        if task_id:
            parsed_task = parse_bulk_import_task_id(task_id)
            username = parsed_task['username']

            if not user.is_staff and user.username != username:
                return Response(status=status.HTTP_403_FORBIDDEN)

            task = AsyncResult(task_id)

            if task.successful():
                result = task.get()
                if result_format == 'json':
                    response = Response(result.json,
                                        content_type="application/json")
                    response['Content-Encoding'] = 'gzip'
                    return response
                if result_format == 'report':
                    return Response(result.report)
                return Response(result.detailed_summary)
            if task.failed():
                return Response(dict(exception=str(task.result)),
                                status=status.HTTP_400_BAD_REQUEST)
            if task.state == 'PENDING' and not task_exists(task_id):
                return Response(dict(exception='task ' + task_id +
                                     ' not found'),
                                status=status.HTTP_404_NOT_FOUND)

            return Response(dict(task=task.id,
                                 state=task.state,
                                 username=username,
                                 queue=parsed_task['queue']),
                            status=status.HTTP_202_ACCEPTED)

        flower_tasks = flower_get('api/tasks').json()
        tasks = []
        for task_id, value in flower_tasks.items():
            if not value['name'].startswith('tasks.bulk_import'):
                continue

            task = parse_bulk_import_task_id(task_id)

            if user.is_staff or user.username == task['username']:
                if (not import_queue or task['queue'] == import_queue) and \
                        (not username or task['username'] == username):
                    tasks.append(
                        dict(task=task_id,
                             state=value['state'],
                             queue=task['queue'],
                             username=task['username']))

        return Response(tasks)
Пример #2
0
    def test_parse_bulk_import_task_id(self):
        task_uuid = str(uuid.uuid4())

        task_id = "{}-{}~{}".format(task_uuid, 'username', 'queue')
        self.assertEqual(
            parse_bulk_import_task_id(task_id),
            dict(uuid=task_uuid + '-', username='******', queue='queue'))

        task_id = "{}-{}".format(task_uuid, 'username')
        self.assertEqual(
            parse_bulk_import_task_id(task_id),
            dict(uuid=task_uuid + '-', username='******', queue='default'))
Пример #3
0
def import_response(request, import_queue, data, threads=None, inline=False):
    if not data:
        return Response(dict(exception=NO_CONTENT_TO_IMPORT),
                        status=status.HTTP_400_BAD_REQUEST)

    user = request.user
    username = user.username
    update_if_exists = request.GET.get('update_if_exists', 'true')
    if update_if_exists not in ['true', 'false']:
        return Response(dict(exception=INVALID_UPDATE_IF_EXISTS),
                        status=status.HTTP_400_BAD_REQUEST)
    update_if_exists = update_if_exists == 'true'

    data = data.decode('utf-8') if isinstance(data, bytes) else data

    try:
        task = queue_bulk_import(data, import_queue, username,
                                 update_if_exists, threads, inline)
    except AlreadyQueued:
        return Response(dict(exception=ALREADY_QUEUED),
                        status=status.HTTP_409_CONFLICT)
    parsed_task = parse_bulk_import_task_id(task.id)
    return Response(dict(task=task.id,
                         state=task.state,
                         username=username,
                         queue=parsed_task['queue']),
                    status=status.HTTP_202_ACCEPTED)
Пример #4
0
    def delete(request, _=None):  # pylint: disable=unused-argument
        task_id = request.data.get('task_id', None)
        signal = request.data.get('signal', None) or 'SIGKILL'
        if not task_id:
            return Response(status=status.HTTP_400_BAD_REQUEST)

        result = AsyncResult(task_id)
        user = request.user
        if not user.is_staff:  # non-admin users should be able to cancel their own tasks
            task_info = parse_bulk_import_task_id(task_id)
            username = task_info.get('username', None)
            if not username:
                username = get(result, 'args.1')  # for parallel child tasks
            if username != user.username:
                return Response(status=status.HTTP_403_FORBIDDEN)

        try:
            app.control.revoke(task_id, terminate=True, signal=signal)

            # Below code is needed for removing the lock from QueueOnce
            if (get(result, 'name')
                    or '').startswith('core.common.tasks.bulk_import'):
                celery_once_key = get_bulk_import_celery_once_lock_key(result)
                if celery_once_key:
                    celery_once = QueueOnce()
                    celery_once.name = result.name
                    celery_once.once_backend.clear_lock(celery_once_key)
        except Exception as ex:
            return Response(dict(errors=ex.args),
                            status=status.HTTP_400_BAD_REQUEST)

        return Response(status=status.HTTP_204_NO_CONTENT)
Пример #5
0
    def post(self, request, import_queue=None):
        user = self.request.user
        username = user.username
        update_if_exists = request.GET.get('update_if_exists', 'true')
        if update_if_exists not in ['true', 'false']:
            return Response(dict(exception=INVALID_UPDATE_IF_EXISTS),
                            status=status.HTTP_400_BAD_REQUEST)
        update_if_exists = update_if_exists == 'true'

        try:
            data = request.body.decode('utf-8') if isinstance(
                request.body, bytes) else request.body
            task = queue_bulk_import(data, import_queue, username,
                                     update_if_exists)
        except AlreadyQueued:
            return Response(dict(exception=ALREADY_QUEUED),
                            status=status.HTTP_409_CONFLICT)

        parsed_task = parse_bulk_import_task_id(task.id)

        return Response(dict(task=task.id,
                             state=task.state,
                             username=username,
                             queue=parsed_task['queue']),
                        status=status.HTTP_202_ACCEPTED)
Пример #6
0
    def get(self, request, import_queue=None):  # pylint: disable=too-many-return-statements,too-many-locals,too-many-branches
        task_id = request.GET.get('task')
        result_format = request.GET.get('result')
        username = request.GET.get('username')
        user = self.request.user

        if task_id:
            parsed_task = parse_bulk_import_task_id(task_id)
            username = parsed_task['username']

            if not user.is_staff and user.username != username:
                return Response(status=status.HTTP_403_FORBIDDEN)

            task = AsyncResult(task_id)

            if task.successful():
                result = task.get()
                if result and result_format == 'json':
                    return Response(result.get('json', None),
                                    content_type="application/json")
                if result and result_format == 'report':
                    return Response(result.get('report', None))
                if result:
                    return Response(result.get('detailed_summary', None))
            if task.failed():
                return Response(dict(exception=str(task.result)),
                                status=status.HTTP_400_BAD_REQUEST)
            if task.state == 'STARTED':
                service = RedisService()
                if service.exists(task_id):
                    return Response(dict(
                        details=service.get_formatted(task_id),
                        task=task.id,
                        state=task.state,
                        username=username,
                        queue=parsed_task['queue']),
                                    status=status.HTTP_200_OK)
            if task.state == 'PENDING' and not task_exists(task_id):
                return Response(dict(exception='task ' + task_id +
                                     ' not found'),
                                status=status.HTTP_404_NOT_FOUND)

            return Response(dict(task=task.id,
                                 state=task.state,
                                 username=username,
                                 queue=parsed_task['queue']),
                            status=status.HTTP_202_ACCEPTED)

        try:
            response = flower_get('api/tasks')
            flower_tasks = response.json()
        except Exception as ex:
            return Response(dict(
                detail=
                'Flower service returned unexpected result. Maybe check healthcheck.',
                exception=str(ex)),
                            status=status.HTTP_422_UNPROCESSABLE_ENTITY)

        tasks = []
        for task_id, value in flower_tasks.items():
            if not value.get('name', None) or not value['name'].startswith(
                    'core.common.tasks.bulk_import'):
                continue

            task = parse_bulk_import_task_id(task_id)

            if user.is_staff or user.username == task['username']:
                if (not import_queue or task['queue'] == import_queue) and \
                        (not username or task['username'] == username):
                    tasks.append(
                        dict(task=task_id,
                             state=value['state'],
                             queue=task['queue'],
                             username=task['username']))

        return Response(tasks)