Beispiel #1
0
    def _validate_resource_assignments(self, resource_assignment_dict,
                                       serializer):
        """
        Validates the resource assignments

        May throw ValidationError.
        Returns a validated dictionary.
        """
        if not isinstance(resource_assignment_dict, dict):
            raise ValidationError(["This field must be a JSON object"])

        unsatisfied_ips = set(
            InputPort.objects.filter(
                workflow_job__in=serializer.validated_data["workflow"].
                workflow_jobs.all(),
                connections__isnull=True,
            ))
        validated_resource_assignment_dict = {}

        # Keep track of the collection with multiple Resources or ResourceLists
        resource_collection_length = None
        resource_collection_ip = None

        for input_port, resources in resource_assignment_dict.items():
            # 1. InputPort is not satisfied
            h_ip = HyperlinkedIdentityField(view_name="inputport-detail")
            h_ip.queryset = InputPort.objects.all()
            try:
                ip = h_ip.to_internal_value(input_port)
            except ValidationError as e:
                e.detail = {input_port: e.detail}
                raise e

            if ip not in unsatisfied_ips:
                raise ValidationError(
                    {input_port: ["Assigned InputPort must be unsatisfied"]})
            unsatisfied_ips.remove(ip)
            types_of_ip = ip.input_port_type.resource_types.all()

            # 2. Resources and ResourceLists:
            if not isinstance(resources, list):
                raise ValidationError({
                    input_port:
                    ["A list of resources or resource lists is expected"]
                })

            h_res = HyperlinkedIdentityField(view_name="resource-detail")
            h_res.queryset = Resource.objects.all()
            h_resl = HyperlinkedIdentityField(view_name="resourcelist-detail")
            h_resl.queryset = ResourceList.objects.all()
            ress = []

            for index, r in enumerate(resources):
                try:
                    ress.append(h_res.to_internal_value(r))  # a Resource
                except ValidationError as e:
                    try:
                        ress.append(
                            h_resl.to_internal_value(r))  # a ResourceList
                    except ValidationError as e:
                        e.detail = {input_port: {index: e.detail}}
                        raise e

            # No empty collection
            if len(ress) == 0:
                raise ValidationError({
                    input_port:
                    ["It is not allowed to assign an empty collection"]
                })

            # Collection with multiple Resources or ResourceLists
            if len(ress) > 1:
                if resource_collection_length is None:
                    # This is the first resource collection we've encountered that has multiple items
                    resource_collection_length = len(ress)
                    resource_collection_ip = input_port
                else:
                    # Validate if the lengths are even
                    if len(ress) != resource_collection_length:
                        raise ValidationError({
                            input_port: [
                                "The number of assigned Resources of ResourceLists is not even with that of {}"
                                .format(resource_collection_ip)
                            ]
                        })

            ## Resource must be in project and resource types are matched
            ## If a ResourceList, it should not be empty and all individuals should satisfy the above requirements.
            for index, res in enumerate(ress):
                if isinstance(res, Resource):
                    if ip.input_port_type.is_list is True:
                        raise ValidationError({
                            input_port: {
                                index: [
                                    "The InputPort requires ResourceLists but is provided with Resources"
                                ]
                            }
                        })
                    if not res.resource_file:
                        raise ValidationError({
                            input_port: {
                                index: ["The resource file is not ready"]
                            }
                        })

                else:  # ResourceList
                    if ip.input_port_type.is_list is False:
                        raise ValidationError({
                            input_port: {
                                index: [
                                    "The InputPort requires Resources but is provided with ResourceLists"
                                ]
                            }
                        })

                    for i, r in enumerate(res.resources.all()):
                        if not r.resource_file:
                            raise ValidationError({
                                input_port: {
                                    index: [
                                        "The resource file of #{0} in the resource list is not ready"
                                        .format(i)
                                    ]
                                }
                            })

                if res.project != serializer.validated_data["workflow"].project:
                    raise ValidationError({
                        input_port: {
                            index: [
                                "Resource or ResourceList is not in the project of Workflow"
                            ]
                        }
                    })
                type_of_res = res.resource_type
                if type_of_res not in types_of_ip:
                    raise ValidationError({
                        input_port: {
                            index: [
                                "The resource type {0} does not match the InputPort {1}"
                                .format(type_of_res, types_of_ip)
                            ]
                        }
                    })

            validated_resource_assignment_dict[ip] = ress

        # Still we have unsatisfied input ports
        if unsatisfied_ips:
            raise ValidationError([
                "There are still unsatisfied InputPorts: {0}".format(" ".join([
                    h_ip.get_url(ip, "inputport-detail", self.request, None)
                    for ip in unsatisfied_ips
                ]))
            ])

        return validated_resource_assignment_dict
Beispiel #2
0
    def _validate_resource_assignments(self, resource_assignment_dict, serializer):
        """
        Validates the resource assignments

        May throw ValidationError.
        Returns a validated dictionary.
        """
        if not isinstance(resource_assignment_dict, dict):
            raise ValidationError(['This field must be a JSON object'])

        unsatisfied_ips = set(InputPort.objects.filter(workflow_job__in=serializer.validated_data['workflow'].workflow_jobs.all(), connections__isnull=True))
        validated_resource_assignment_dict = {}
        multiple_resource_set = None
        for input_port, resources in resource_assignment_dict.iteritems():
            # 1. InputPort is not satisfied
            h_ip = HyperlinkedIdentityField(view_name="inputport-detail")
            h_ip.queryset = InputPort.objects.all()
            try:
                ip = h_ip.to_internal_value(input_port)
            except ValidationError as e:
                e.detail = {input_port: e.detail}
                raise e

            if ip not in unsatisfied_ips:
                raise ValidationError({input_port: ['Assigned InputPort must be unsatisfied']})
            unsatisfied_ips.remove(ip)
            types_of_ip = ip.input_port_type.resource_types.all()

            # 2. Resources and ResourceLists:
            if not isinstance(resources, list):
                raise ValidationError({input_port: ['A list of resources or resource lists is expected']})

            h_res = HyperlinkedIdentityField(view_name="resource-detail")
            h_res.queryset = Resource.objects.all()
            h_resl = HyperlinkedIdentityField(view_name="resourcelist-detail")
            h_resl.queryset = ResourceList.objects.all()
            ress = []

            for index, r in enumerate(resources):
                try:
                    ress.append(h_res.to_internal_value(r))  # a Resource
                except ValidationError as e:
                    try:
                        ress.append(h_resl.to_internal_value(r))  # a ResourceList
                    except ValidationError as e:
                        e.detail = {input_port: {index: e.detail}}
                        raise e


            ## No empty resource set
            if len(ress) == 0:
                raise ValidationError({input_port: ['It is not allowed to assign an empty resource set']})

            ## There must be at most one multiple resource set
            if len(ress) > 1:
                ress_set = set(map(lambda r: r.uuid, ress))
                if not multiple_resource_set:
                    multiple_resource_set = ress_set
                else:
                    if multiple_resource_set != ress_set:
                        raise ValidationError({input_port: ['It is not allowed to assign multiple resource sets']})

            ## Resource must be in project and resource types are matched
            ## If a ResourceList, it should not be empty and all individuals should satisfy the above requirements.
            for index, res in enumerate(ress):
                if isinstance(res, Resource):
                    if ip.input_port_type.is_list is True:
                        raise ValidationError({input_port: {index: ['The InputPort requires ResourceLists but is provided with Resources']}})
                    if not res.resource_file:
                        raise ValidationError({input_port: {index: ['The resource file is not ready']}})

                else:   # ResourceList
                    if ip.input_port_type.is_list is False:
                        raise ValidationError({input_port: {index: ['The InputPort requires Resources but is provided with ResourceLists']}})

                    for i, r in enumerate(res.resources.all()):
                        if not r.resource_file:
                            raise ValidationError({input_port: {index: ['The resource file of #{0} in the resource list is not ready'.format(i)]}})


                if res.project != serializer.validated_data['workflow'].project:
                    raise ValidationError({input_port: {index: ['Resource or ResourceList is not in the project of Workflow']}})
                type_of_res = res.resource_type
                if type_of_res not in types_of_ip:
                    raise ValidationError({input_port: {index: ['The resource type does not match the InputPort']}})

            validated_resource_assignment_dict[ip] = ress

        # Still we have unsatisfied input ports
        if unsatisfied_ips:
            raise ValidationError(['There are still unsatisfied InputPorts: {0}'.format(
                ' '.join([h_ip.get_url(ip, 'inputport-detail', self.request, None) for ip in unsatisfied_ips])
            )])

        return validated_resource_assignment_dict
Beispiel #3
0
    def _validate_resource_assignments(self, resource_assignment_dict, serializer):
        """
        Validates the resource assignments

        May throw ValidationError.
        Returns a validated dictionary.
        """
        if not isinstance(resource_assignment_dict, dict):
            raise ValidationError(['This field must be a JSON object'])

        unsatisfied_ips = set(InputPort.objects.filter(workflow_job__in=serializer.validated_data['workflow'].workflow_jobs.all(), connections__isnull=True))
        validated_resource_assignment_dict = {}
        multiple_resource_set = None
        for input_port, resources in resource_assignment_dict.iteritems():
            # 1. InputPort is not satisfied
            h_ip = HyperlinkedIdentityField(view_name="inputport-detail")
            h_ip.queryset = InputPort.objects.all()
            try:
                ip = h_ip.to_internal_value(input_port)
            except ValidationError as e:
                e.detail = {input_port: e.detail}
                raise e

            if ip not in unsatisfied_ips:
                raise ValidationError({input_port: ['Assigned InputPort must be unsatisfied']})
            unsatisfied_ips.remove(ip)
            types_of_ip = ip.input_port_type.resource_types.all()

            # 2. Resources and ResourceLists:
            if not isinstance(resources, list):
                raise ValidationError({input_port: ['A list of resources or resource lists is expected']})

            h_res = HyperlinkedIdentityField(view_name="resource-detail")
            h_res.queryset = Resource.objects.all()
            h_resl = HyperlinkedIdentityField(view_name="resourcelist-detail")
            h_resl.queryset = ResourceList.objects.all()
            ress = []

            for index, r in enumerate(resources):
                try:
                    ress.append(h_res.to_internal_value(r))  # a Resource
                except ValidationError as e:
                    try:
                        ress.append(h_resl.to_internal_value(r))  # a ResourceList
                    except ValidationError as e:
                        e.detail = {input_port: {index: e.detail}}
                        raise e


            ## No empty resource set
            if len(ress) == 0:
                raise ValidationError({input_port: ['It is not allowed to assign an empty resource set']})

            ## There must be at most one multiple resource set
            if len(ress) > 1:
                ress_set = set(map(lambda r: r.uuid, ress))
                if not multiple_resource_set:
                    multiple_resource_set = ress_set
                else:
                    if multiple_resource_set != ress_set:
                        raise ValidationError({input_port: ['It is not allowed to assign multiple resource sets']})

            ## Resource must be in project and resource types are matched
            ## If a ResourceList, it should not be empty and all individuals should satisfy the above requirements.
            for index, res in enumerate(ress):
                if isinstance(res, Resource):
                    if ip.input_port_type.is_list is True:
                        raise ValidationError({input_port: {index: ['The InputPort requires ResourceLists but is provided with Resources']}})
                    if not res.resource_file:
                        raise ValidationError({input_port: {index: ['The resource file is not ready']}})

                else:   # ResourceList
                    if ip.input_port_type.is_list is False:
                        raise ValidationError({input_port: {index: ['The InputPort requires Resources but is provided with ResourceLists']}})

                    for i, r in enumerate(res.resources.all()):
                        if not r.resource_file:
                            raise ValidationError({input_port: {index: ['The resource file of #{0} in the resource list is not ready'.format(i)]}})


                if res.project != serializer.validated_data['workflow'].project:
                    raise ValidationError({input_port: {index: ['Resource or ResourceList is not in the project of Workflow']}})
                type_of_res = res.resource_type
                if type_of_res not in types_of_ip:
                    raise ValidationError({input_port: {index: ['The resource type does not match the InputPort']}})

            validated_resource_assignment_dict[ip] = ress

        # Still we have unsatisfied input ports
        if unsatisfied_ips:
            raise ValidationError(['There are still unsatisfied InputPorts: {0}'.format(
                ' '.join([h_ip.get_url(ip, 'inputport-detail', self.request, None) for ip in unsatisfied_ips])
            )])

        return validated_resource_assignment_dict