コード例 #1
0
    def get(self, request, hpc=None, project_name=None):

        logger.debug('QuotasView--->GET: called.')

        user = get_user(request)
        if not isinstance(user, User):
            logger.warning(
                'JobsView--->GET: User not recognized.\n' +
                ' ================= USER ERRORS ====================\n' +
                user + ' ==================================================')
            return Response(user, status=status.HTTP_403_FORBIDDEN)

        if hpc:
            hpc = hpc.upper()
            if hpc not in [i[0] for i in HPC]:
                return Response('HPC not found!',
                                status=status.HTTP_404_NOT_FOUND)

            if project_name:
                try:
                    project = Project.objects.get(name=project_name, hpc=hpc)
                    try:
                        quota = Quota.objects.get(user=user, project=project)
                        serializer = QuotaSerializer(quota)
                        return Response(serializer.data,
                                        status=status.HTTP_200_OK)
                    except Quota.DoesNotExist:
                        return Response('Quota not found!',
                                        status=status.HTTP_404_NOT_FOUND)
                except Project.DoesNotExist:
                    return Response('Project not found!',
                                    status=status.HTTP_404_NOT_FOUND)
            else:
                projects = Project.objects.filter(hpc=hpc)
                quotas = Quota.objects.filter(project=projects, user=user)
                serializer = QuotaSerializer(quotas, many=True)
                return Response(serializer.data, status=status.HTTP_200_OK)
        quotas = Quota.objects.filter(user=user)
        serializer = QuotaSerializer(quotas, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)
コード例 #2
0
    def get(self, request, hpc, project_name):

        logger.debug('JobsViewExample--->GET: Called.')

        user = get_user(request)
        if not isinstance(user, User):
            logger.warning(
                'JobsViewExample--->GET: User not recognized.\n' +
                ' =================== USER ERRORS =================\n' + user +
                ' =================================================')
            return Response(user, status=status.HTTP_403_FORBIDDEN)
        hpc = hpc.upper()
        if hpc_exists(hpc):
            try:
                project = Project.objects.get(name=project_name)

                # run example on NSG
                if hpc == 'NSG':
                    job_file_example = open(
                        BASE_DIR + '/job_examples/JonesEtAl2009_r31.zip', 'r')
                    payload = {"tool": "NEURON74_PY_TG", "Runtime": 0.5}

                    data, status_code = nsg.submit_job(
                        enduser=get_nsg_enduser(user),
                        payload=payload,
                        infile=job_file_example)

                    if status_code != 201 and status_code != 200:
                        return Response(data,
                                        status=status.HTTP_400_BAD_REQUEST)

                # run example on PIZDAINT
                elif hpc == 'PIZDAINT':
                    pizdaint_job_example = {
                        "Executable": "/bin/date",
                        "Resources": {
                            "Project": "ich011",
                            "NodeConstraints": "mc",
                            "Runtime": "60"
                        }
                    }
                    data, status_code = pizdaint.submit(
                        job=pizdaint_job_example, headers={})

                    if status_code != 201 and status_code != 200:
                        return Response(
                            status=status.HTTP_503_SERVICE_UNAVAILABLE)

                data.update({
                    'owner': user.id,
                    'project': project.id,
                    'runtime': 0.5,
                    'title': 'check job submission for hpc-monitor',
                })

                serializer = JobSerializer(data=data)
                if serializer.is_valid():
                    job = serializer.save()
                    return Response(serializer.data, status=status.HTTP_200_OK)
                return Response(serializer.errors,
                                status=status.HTTP_400_BAD_REQUEST)

            except Project.DoesNotExist:
                return Response('Project not found!',
                                status=status.HTTP_404_NOT_FOUND)
コード例 #3
0
    def get(self, request, hpc, project_name, job_id, fileid=None):
        """
        Perform the GET request to NSG-R to retrieve a specific job's files list or to download a file.

        :param request: the request object.
        :param jobid: jobid required to perform the request. Specify the job in which user wants to get the files.
        :param fileid: if fileid is set, the request return the specific file user wants to get.
        :return: return the file specified by fileid or the job's files list.
        """
        logger.debug('FilesView--->GET: called.')

        user = get_user(request)

        if not isinstance(user, User):
            logger.warning(
                'FilesView--->GET: User not recognized.\n' +
                ' ================= USER ERRORS ====================\n' +
                user + ' ==================================================')
            return Response(user, status=status.HTTP_403_FORBIDDEN)
        hpc = hpc.upper()
        if hpc not in [i[0] for i in HPC]:
            return Response('HPC not found!', status=status.HTTP_404_NOT_FOUND)
        try:
            project = Project.objects.get(name=project_name)
            try:
                job = Job.objects.get(owner=user,
                                      project=project,
                                      job_id=job_id)
                if job.project.hpc == 'NSG':
                    # getting files list from NSG
                    if not fileid:
                        if job.terminal_stage:
                            files, status_code = nsg.get_job_files_list(
                                enduser=get_nsg_enduser(user), jobid=job_id)
                        else:
                            files, status_code = nsg.list_workingdir_files(
                                enduser=get_nsg_enduser(user), jobid=job_id)
                        return Response(files, status=status_code)
                        # getting file object from NSG
                    else:
                        if job.terminal_stage:
                            outfile, status_code = nsg.download_output_file(
                                enduser=get_nsg_enduser(user),
                                jobid=job_id,
                                fileid=fileid)
                        else:
                            outfile, status_code = nsg.download_working_directory_file(
                                enduser=get_nsg_enduser(user),
                                jobid=job_id,
                                filename=fileid)
                        return FileResponse(outfile, status=status_code)

                elif job.project.hpc == 'PIZDAINT':
                    # getting files list from PIZDAINT
                    if not fileid:
                        file_list, status_code = pizdaint.get_job_files_list(
                            job_id=job_id)
                        return Response(data=file_list, status=status_code)
                    else:
                        outfile, status_code = pizdaint.download_job_file(
                            job_id=job_id, file_id=fileid)
                        return FileResponse(outfile, status=status_code)

            except Job.DoesNotExist:
                return Response('Job not found!',
                                status=status.HTTP_404_NOT_FOUND)
        except Project.DoesNotExist:
            return Response('Project not found!',
                            status=status.HTTP_404_NOT_FOUND)
コード例 #4
0
    def delete(self, request, hpc, project_name, job_id):
        """
        Delete or Cancel a job.
        Deleting a job means that the job was completed and user choose to delete it from the HPC or it can happen
        that the job goes in timeout on HPC system and it is deleted.
        Canceling a job means that the job is not completed yet and it will be canceled restoring all the user quota
        allocated to run the job, it can happen because the job was submitted by mistake.
        """

        logger.debug('JobsView--->DELETE: Called.')

        user = get_user(request)
        if not isinstance(user, User):
            logger.warning(
                'JobsView--->DELETE: User not recognized.\n' +
                ' ================= USER ERRORS ====================\n' +
                user + ' ==================================================')
            return Response(user, status=status.HTTP_403_FORBIDDEN)

        hpc = hpc.upper()
        if not hpc_exists(hpc):
            return Response('HPC not found!', status=status.HTTP_404_NOT_FOUND)

        try:
            project = Project.objects.get(hpc=hpc, name=project_name)
            job = Job.objects.get(job_id=job_id, project=project)
            if job.stage == 'DELETED' or job.stage == 'CANCELED':
                return Response('Job is already deleted/canceled',
                                status=status.HTTP_200_OK)
            if hpc == 'NSG':
                content, status_code = nsg.delete_job(
                    enduser=get_nsg_enduser(user), jobid=job_id)
                if status_code == 204:
                    # update job
                    if job.terminal_stage:
                        # delete job if is completed
                        job.stage = 'DELETED'
                    else:
                        # cancel job if it is not completed yet and restore quota
                        job.stage = 'CANCELED'
                        quota = Quota.objects.get(user=user,
                                                  project=job.project)
                        quota.add(time=job.runtime)
                else:
                    # if the delete request goes wrong returns the error and the status_code
                    return Response(content, status=status_code)
            elif hpc == 'PIZDAINT':
                content, status_code = pizdaint.abort_job(job_id=job_id)
                if status_code != 200:
                    # if the delete request goes wrong returns the error and the status_code
                    return Response(content, status=status_code)
                if content == 'Aborted':
                    # update job
                    if job_terminal_stage:
                        # deleted job if is completed
                        job.stage = 'DELETED'
                    else:
                        # cancel job if it is not completed yet and restore quota
                        job.stage = 'CANCELED'
                        quota = Quota.objects.get(user=user,
                                                  project=job.project)
                        quota.add(time=job.runtime)
            job.save()
            serializer = JobSerializer(job)
            return Response(serializer.data, status=status.HTTP_200_OK)
        except Project.DoesNotExist:
            return Response('Project not found!',
                            status=status.HTTP_404_NOT_FOUND)
        except Job.DoesNotExist:
            return Response('Job not found!', status=status.HTTP_404_NOT_FOUND)
コード例 #5
0
    def post(self, request, hpc, project_name=None):
        """
        The POST method allow user to submit a job to the chosen HPC. If project name is not set, then the default
        one of the HPC is automatically selected.

        The filename must be set into headers as 'Content-Disposition: attachment; filename=some_filename'.

        If project is not found on the chosen HPC, a 400 error code is returned.

        Parameter fields must to be pass as header's payload
            'tool' indicates which tool user want to use to run job;
            'n_cores' indicates how many cores are used to run job;
            'n_nodes' indicates how many nodes want to use;
            'runtime' indicate how many cpu-hours are assigned to run job;

        :return: Response object with data of successes job submissions and 201 status code otherwise
                 data errors and 401 status code if user has not enough quota or error 400 if the request
                 is in a bad format.
        """
        # logger.debug('JobsView--->POST: Called.')

        user = get_user(request)

        # check if user is not anonymous
        if not isinstance(user, User):
            # logger.warning('JobsView--->POST: User not recognized.\n' +
            #               ' ================= USER ERRORS ====================\n' + user +
            #               ' ==================================================')
            return Response(user, status=status.HTTP_403_FORBIDDEN)

        hpc = hpc.upper()

        # if project is not set then submit on the default one of the specified hpc
        if not project_name:
            project_name = PROJECT[hpc]
        # else set the one user demands
        try:
            project = Project.objects.get(name=project_name, hpc=hpc)
        except Project.DoesNotExist:
            # logger.warning('JobsView--->POST: Project not found.')
            return Response('Project not found!',
                            status=status.HTTP_404_NOT_FOUND)
        # logger.info('JobsView--->POST: Project set: ' + str(project) + '.')

        # checking for user quota
        try:
            quota = Quota.objects.get(user=user, project=project)
        except Quota.DoesNotExist:
            # logger.warning('JobsView--->POST: User ' + str(user) + ' not have quota.')
            return Response('User has not quota!',
                            status=status.HTTP_401_UNAUTHORIZED)

        # =================== PAYLOAD FORM = {"key": "value"} - doesn't work with single quotes =======================
        # payload must to be extract from request.META because with fileUploading it's not possible to get request.data
        try:
            raw_payload = request.META['HTTP_PAYLOAD']
            payload = json.loads(raw_payload)
        except KeyError:
            # logger.info('JobsView--->POST: Payload not found!')
            return Response('Request incomplete. Parameters missing!',
                            status=status.HTTP_400_BAD_REQUEST)

        print request.FILES['file']

        # check for job file
        try:
            job_file = request.FILES['file']
            job_file_name = job_file.name
            job_file_content = job_file.read()
            job_file.seek(0)
        except KeyError:
            if hpc == 'NSG':
                # logger.info('JobsView--->POST: Input file not found!')
                return Response('Request incomplete. Input file missing!',
                                status=status.HTTP_400_BAD_REQUEST)

        try:
            runtime = float(payload['runtime']) * 60 * 60
        except ValueError:
            return Response('Wrong runtime value',
                            status=status.HTTP_400_BAD_REQUEST)

        # check if user has enough quota to run the job
        try:
            quota.sub(time=runtime)
        except ValueError:
            # check for jobs status of the selected project if user has not enough quota
            update_job_status_and_quota(user=user, project=project)
            # logger.info('Updating jobs for user ' + str(user) + '.')

            # if quota is still not enough return a 'Quota not enough' message to user
            try:
                quota.sub(time=runtime)
            except ValueError:
                # logger.warning('User ' + str(user) + ' hasn't enough quota on this project ' + str(project) + ' to run the job.')
                return Response(data='Quota not enough!',
                                status=status.HTTP_401_UNAUTHORIZED)

        # check for job title parameters into payload
        try:
            job_title = payload['title']
        except KeyError:
            job_title = ''

        # submit on NSG
        if hpc == 'NSG':
            job_description = payload
            data, status_code = nsg.submit_job(enduser=get_nsg_enduser(user),
                                               payload=job_description,
                                               infile=job_file)
            # restore job's runtime if submit goes wrong
            if status_code != 201 and status_code != 200:
                quota.add(runtime)
                return Response(data, status=status.HTTP_400_BAD_REQUEST)

        # submit on PIZDAINT
        elif hpc == 'PIZDAINT':
            inputs = []
            try:
                job_file_name = request.META['HTTP_CONTENT_DISPOSITION'].split(
                    'filename=')[1]
                job_input = {'To': job_file_name, 'Data': job_file.read()}
                inputs = [job_input]
                job_file_content = job_input['Data']
            except KeyError:
                logger.info('No input file for pizdaint job')
            try:
                check_pizdaint_value(payload)
            except ValueError:
                return Response(
                    'Core number must be at least equal to 12 and node number at least equal to 1!',
                    status=status.HTTP_400_BAD_REQUEST)
            job_description = {
                "Executable": payload['command'],
                "Resources": {
                    "Project": "ich011",
                    "Nodes": payload['node_number'],
                    "CPUsPerNode": payload['core_number'],
                    "Runtime": str(runtime / 60) + 'm',
                    "NodeConstraints": "mc",
                },
            }
            data, status_code = pizdaint.submit(job=job_description,
                                                headers={},
                                                inputs=inputs)

            # restore job's runtime if submit goes wrong
            if status_code != 201 and status_code != 200:
                quota.add(time=runtime)
                return Response(data, status=status.HTTP_400_BAD_REQUEST)

        # update other job values
        data.update({
            'owner': user.id,
            'project': project.id,
            'title': job_title,
            'runtime': payload['runtime'],
            'end_date': None
        })

        # serializer and save the job if everything is ok
        serializer = JobSerializer(data=data)
        if serializer.is_valid():
            job = serializer.save()
            dump_job(user_id=user.id,
                     hpc_name=hpc.lower(),
                     job_id=job.id,
                     job_description=json.dumps(job_description),
                     job_file_name=job_file_name,
                     job_file_content=job_file_content)
            #logger.debug('JobsView--->POST: Job "' + str(job) + '" submitted.')
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
コード例 #6
0
    def get(self, request, hpc=None, project_name=None, job_id=None):
        """
        The request queries for job or jobs object to the local database.
        If the request is send from an AdminUser, the response returns all jobs object.

        If all parameters are omitted, then the method returns all user's jobs.
        If only hpc_name is specified, then the method all user's jobs submitted on that HPC.
        If the project_name is specified, then the method returns all user's jobs submitted on that project of that HPC.
        If also the job_id is specified, then the method returns the single job with that id submitted on that project of that HPC.

        """
        logger.debug('JobsView--->GET: Called.')
        user = get_user(request)
        if not isinstance(user, User):
            logger.warning(
                'JobsView--->GET: User not recognized.\n' +
                ' ================= USER ERRORS ====================\n' +
                user + ' ==================================================')
            return Response(user, status=status.HTTP_403_FORBIDDEN)
        # if hpc is set, check if it exists and then returns all user's job submitted on that HPC
        if hpc:
            hpc = hpc.upper()
            if hpc_exists(hpc):
                # if project_name is set returns all user's job submitted on that project of that HPC
                if project_name:
                    try:
                        project = Project.objects.get(name=project_name)
                        # if job_id is set returns the job instance with that job_id on that project on that HPC
                        if job_id:
                            try:
                                # update and return the single job
                                update_job_status_and_quota(user=user,
                                                            project=project,
                                                            job_id=job_id)
                                job = Job.objects.get(owner=user,
                                                      project=project,
                                                      job_id=job_id)
                                serializer = JobSerializer(job)
                                return Response(serializer.data,
                                                status=status.HTTP_200_OK)
                            except Job.DoesNotExist:
                                return Response(
                                    'Job not found!',
                                    status=status.HTTP_404_NOT_FOUND)
                        # update and return all jobs for the specified project
                        update_job_status_and_quota(user=user, project=project)
                        jobs = Job.objects.filter(owner=user, project=project)
                        serializer = JobSerializer(jobs, many=True)
                        return Response(serializer.data,
                                        status=status.HTTP_200_OK)
                    except Project.DoesNotExist:
                        return Response('Project not found!',
                                        status=status.HTTP_404_NOT_FOUND)
                # update and return all jobs submitted into the specified hpc
                update_job_status_and_quota(user=user, hpc=hpc)
                projects = Project.objects.filter(hpc=hpc)
                jobs = Job.objects.filter(owner=user, project=projects)
                serializer = JobSerializer(jobs, many=True)
                return Response(serializer.data, status=status.HTTP_200_OK)
            else:
                # if hpc is wrong returns 404 error code
                return Response('HPC not found!',
                                status=status.HTTP_404_NOT_FOUND)
        # update and return all user's jobs
        update_job_status_and_quota(user=user)
        jobs = Job.objects.filter(owner=user)
        serializer = JobSerializer(jobs, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)