Ejemplo n.º 1
0
    def prepare(self, request, pk=None):
        ip = self.get_object_for_update()
        if ip.is_locked():
            raise Conflict('Information package is locked')
        sa = ip.submission_agreement

        if ip.state != 'Preparing':
            raise exceptions.ParseError('IP must be in state "Preparing"')

        if sa is None or not ip.submission_agreement_locked:
            raise exceptions.ParseError('IP requires locked SA to be prepared')

        profile_ip_sip = ProfileIP.objects.filter(
            ip=ip, profile=sa.profile_sip).first()
        profile_ip_transfer_project = ProfileIP.objects.filter(
            ip=ip, profile=sa.profile_transfer_project).first()
        profile_ip_submit_description = ProfileIP.objects.filter(
            ip=ip, profile=sa.profile_submit_description).first()

        if profile_ip_sip is None:
            raise exceptions.ParseError(
                'Information package missing SIP profile')
        if profile_ip_transfer_project is None:
            raise exceptions.ParseError(
                'Information package missing Transfer Project profile')
        if profile_ip_submit_description is None:
            raise exceptions.ParseError(
                'Information package missing Submit Description profile')

        for profile_ip in ProfileIP.objects.filter(ip=ip).iterator():
            try:
                profile_ip.clean()
            except ValidationError as e:
                raise exceptions.ParseError('%s: %s' %
                                            (profile_ip.profile.name, e[0]))

            profile_ip.LockedBy = request.user
            profile_ip.save()

        step = ProcessStep.objects.create(name="Create Physical Model",
                                          information_package=ip)
        ProcessTask.objects.create(
            name="ESSArch_Core.ip.tasks.CreatePhysicalModel",
            information_package=ip,
            responsible=self.request.user,
            processstep=step,
        )

        step.run().get()

        submit_description_data = ip.get_profile_data('submit_description')
        ip.start_date = submit_description_data.get('start_date')
        ip.end_date = submit_description_data.get('end_date')

        ip.state = "Prepared"
        ip.save(update_fields=['state', 'start_date', 'end_date'])

        return Response()
Ejemplo n.º 2
0
    def mount(self, request, pk=None):
        medium = self.get_object()

        if medium.get_type() != TAPE:
            raise exceptions.ParseError('%s is not a tape' % medium)

        if medium.tape_drive is not None:
            raise Conflict(detail='Tape already mounted')

        RobotQueue.objects.get_or_create(
            user=self.request.user,
            storage_medium=medium,
            req_type=10, status__in=[0, 2], defaults={'status': 0}
        )

        return Response(status=status.HTTP_202_ACCEPTED)
Ejemplo n.º 3
0
        def _wrapped_view(view, request, *args, **kwargs):
            obj = None

            if hasattr(view, 'get_queryset'):
                pk = kwargs.get('pk')
                model = view.get_queryset().model
                if model and pk is not None:
                    obj = get_object_or_404(model, pk=pk)

            if obj is not None:
                try:
                    with cache.lock('%s-%s' % (obj.__class__.__name__, obj.pk),
                                    timeout=timeout,
                                    sleep=sleep,
                                    blocking_timeout=blocking_timeout):
                        return view_func(view, request, *args, **kwargs)
                except LockError:
                    raise Conflict('Resource is locked')
            else:
                return view_func(view, request, *args, **kwargs)
Ejemplo n.º 4
0
    def validate(self, data):
        if self.instance is None and Profile.objects.filter(
                pk=data.get('id')).exists():
            raise Conflict('Profile already exists')

        return data
Ejemplo n.º 5
0
    def validate(self, data):
        if self.instance is None and SubmissionAgreement.objects.filter(
                pk=data.get('id')).exists():
            raise Conflict('Submission agreement already exists')

        return data
Ejemplo n.º 6
0
    def submit(self, request, pk=None):
        """
        Submits the specified information package

        Args:
            pk: The primary key (id) of the information package to submit

        Returns:
            None
        """

        ip = self.get_object_for_update()
        if ip.is_locked():
            raise Conflict('Information package is locked')

        if ip.state != "Created":
            return Response(
                "The IP (%s) is in the state '%s' but should be 'Created'" %
                (pk, ip.state),
                status=status.HTTP_400_BAD_REQUEST)

        ip.state = 'Submitting'
        ip.save()

        sd_profile = ip.get_profile('submit_description')

        if sd_profile is None:
            return Response("The IP (%s) has no submit description profile" %
                            pk,
                            status=status.HTTP_400_BAD_REQUEST)

        email_subject = None
        email_body = None
        recipient = ip.get_email_recipient()
        if recipient:
            for arg in ['subject', 'body']:
                if arg not in request.data:
                    raise exceptions.ParseError('%s parameter missing' % arg)

            email_subject = request.data['subject']
            email_body = request.data['body']

        validators = request.data.get('validators', {})
        validate_xml_file = validators.get('validate_xml_file', False)
        validate_logical_physical_representation = validators.get(
            'validate_logical_physical_representation', False)

        workflow_spec = [
            {
                "name": "ESSArch_Core.ip.tasks.GeneratePackageMets",
                "label": "Generate package-mets",
            },
            {
                "name": "ESSArch_Core.tasks.ValidateXMLFile",
                "if": validate_xml_file,
                "label": "Validate package-mets",
                "params": {
                    "xml_filename": "{{_PACKAGE_METS_PATH}}",
                }
            },
            {
                "name":
                "ESSArch_Core.tasks.ValidateLogicalPhysicalRepresentation",
                "if": validate_logical_physical_representation,
                "label": "Diff-check against package-mets",
                "args": ["{{_OBJPATH}}", "{{_PACKAGE_METS_PATH}}"],
            },
            {
                "name": "preingest.tasks.SubmitSIP",
                "label": "Submit SIP",
            },
            {
                "name": "ESSArch_Core.tasks.UpdateIPStatus",
                "label": "Set status to submitted",
                "args": ["Submitted"],
            },
            {
                "name": "ESSArch_Core.tasks.SendEmail",
                "if": recipient,
                "label": "Send email",
                "params": {
                    "subject": email_subject,
                    "body": email_body,
                    "recipients": [recipient],
                    "attachments": [
                        "{{_PACKAGE_METS_PATH}}",
                    ],
                }
            },
        ]
        workflow = create_workflow(workflow_spec, ip)
        workflow.name = "Submit SIP"
        workflow.information_package = ip
        workflow.save()
        workflow.run()
        return Response({'status': 'submitting ip'})
Ejemplo n.º 7
0
    def create_ip(self, request, pk=None):
        """
        Creates the specified information package

        Args:
            pk: The primary key (id) of the information package to create

        Returns:
            None
        """

        ip = self.get_object_for_update()
        if ip.is_locked():
            raise Conflict('Information package is locked')

        if ip.state != "Uploaded":
            raise exceptions.ParseError(
                "The IP (%s) is in the state '%s' but should be 'Uploaded'" %
                (pk, ip.state))

        ip.state = 'Creating'
        ip.save()

        generate_premis = ip.profile_locked('preservation_metadata')

        convert_files = request.data.get('file_conversion', False)
        file_format_map = {'doc': 'pdf', 'docx': 'pdf'}

        validators = request.data.get('validators', {})
        validate_xml_file = validators.get('validate_xml_file', False)
        validate_logical_physical_representation = validators.get(
            'validate_logical_physical_representation', False)

        workflow_spec = [
            {
                "name": "ESSArch_Core.tasks.ConvertFile",
                "if": convert_files,
                "label": "Convert Files",
                "args": ["{{_OBJPATH}}", file_format_map]
            },
            {
                "name": "ESSArch_Core.ip.tasks.DownloadSchemas",
                "label": "Download Schemas",
            },
            {
                "step":
                True,
                "name":
                "Create Log File",
                "children": [
                    {
                        "name": "ESSArch_Core.ip.tasks.GenerateEventsXML",
                        "label": "Generate events xml file",
                    },
                    {
                        "name": "ESSArch_Core.tasks.AppendEvents",
                        "label": "Add events to xml file",
                    },
                    {
                        "name":
                        "ESSArch_Core.ip.tasks.AddPremisIPObjectElementToEventsFile",
                        "label": "Add premis IP object to xml file",
                    },
                ]
            },
            {
                "name": "ESSArch_Core.ip.tasks.GeneratePremis",
                "if": generate_premis,
                "label": "Generate premis",
            },
            {
                "name": "ESSArch_Core.ip.tasks.GenerateContentMets",
                "label": "Generate content-mets",
            },
            {
                "step":
                True,
                "name":
                "Validation",
                "if":
                any([
                    validate_xml_file, validate_logical_physical_representation
                ]),
                "children": [{
                    "name": "ESSArch_Core.tasks.ValidateXMLFile",
                    "if": validate_xml_file,
                    "label": "Validate content-mets",
                    "params": {
                        "xml_filename": "{{_CONTENT_METS_PATH}}",
                    }
                }, {
                    "name": "ESSArch_Core.tasks.ValidateXMLFile",
                    "if": generate_premis and validate_xml_file,
                    "label": "Validate premis",
                    "params": {
                        "xml_filename": "{{_PREMIS_PATH}}",
                    }
                }, {
                    "name":
                    "ESSArch_Core.tasks.ValidateLogicalPhysicalRepresentation",
                    "if":
                    validate_logical_physical_representation,
                    "label":
                    "Diff-check against content-mets",
                    "args": ["{{_OBJPATH}}", "{{_CONTENT_METS_PATH}}"],
                }, {
                    "name":
                    "ESSArch_Core.tasks.CompareXMLFiles",
                    "if":
                    generate_premis,
                    "label":
                    "Compare premis and content-mets",
                    "args": ["{{_PREMIS_PATH}}", "{{_CONTENT_METS_PATH}}"],
                }]
            },
            {
                "name": "ESSArch_Core.ip.tasks.CreateContainer",
                "label": "Create container",
            },
            {
                "name": "ESSArch_Core.tasks.UpdateIPStatus",
                "label": "Set status to created",
                "args": ["Created"],
            },
        ]
        workflow = create_workflow(workflow_spec, ip)
        workflow.name = "Create SIP"
        workflow.information_package = ip
        workflow.save()
        workflow.run()
        return Response({'status': 'creating ip'})
Ejemplo n.º 8
0
    def create(self, request, *args, **kwargs):
        """
        Prepares a new information package (IP) using the following tasks:

        1. Creates a new IP in the database.

        2. Creates a directory in the prepare directory with the name set to
        the id of the new IP.

        3. Creates an event in the database connected to the IP and with the
        detail "Prepare IP".

        Args:

        Returns:
            None
        """

        self.check_permissions(request)

        try:
            label = request.data['label']
        except KeyError:
            raise exceptions.ParseError('Missing parameter label')

        object_identifier_value = request.data.get('object_identifier_value')
        responsible = self.request.user

        if responsible.user_profile.current_organization is None:
            raise exceptions.ParseError(
                'You must be part of an organization to prepare an IP')

        prepare_path = Path.objects.get(entity="path_preingest_prepare").value
        if object_identifier_value:
            ip_exists = InformationPackage.objects.filter(
                object_identifier_value=object_identifier_value).exists()
            if ip_exists:
                raise Conflict(
                    'IP with object identifer value "%s" already exists' %
                    object_identifier_value)

            if os.path.exists(
                    os.path.join(prepare_path, object_identifier_value)):
                raise Conflict(
                    'IP with identifier "%s" already exists on disk' %
                    object_identifier_value)

        perms = copy.deepcopy(getattr(settings, 'IP_CREATION_PERMS_MAP', {}))
        try:
            with transaction.atomic():
                ip = InformationPackage.objects.create(
                    object_identifier_value=object_identifier_value,
                    label=label,
                    responsible=responsible,
                    state="Preparing",
                    package_type=InformationPackage.SIP)
                ip.entry_date = ip.create_date
                extra = {
                    'event_type': 10100,
                    'object': str(ip.pk),
                    'agent': request.user.username,
                    'outcome': EventIP.SUCCESS
                }
                self.logger.info(
                    "Prepared {obj}".format(obj=ip.object_identifier_value),
                    extra=extra)

                member = Member.objects.get(django_user=responsible)
                user_perms = perms.pop('owner', [])
                organization = member.django_user.user_profile.current_organization
                organization.assign_object(ip, custom_permissions=perms)
                organization.add_object(ip)

                for perm in user_perms:
                    perm_name = get_permission_name(perm, ip)
                    assign_perm(perm_name, member.django_user, ip)

                obj_path = normalize_path(
                    os.path.join(prepare_path, ip.object_identifier_value))
                os.mkdir(obj_path)
                ip.object_path = obj_path
                ip.save()
                extra = {
                    'event_type': 10200,
                    'object': str(ip.pk),
                    'agent': request.user.username,
                    'outcome': EventIP.SUCCESS
                }
                self.logger.info("Created IP root directory", extra=extra)
        except IntegrityError:
            try:
                shutil.rmtree(obj_path)
            except OSError as e:
                pass
            raise

        return Response({"detail": "Prepared IP"},
                        status=status.HTTP_201_CREATED)