Exemplo n.º 1
0
class RepositoryVersionSerializer(ModelSerializer,
                                  NestedHyperlinkedModelSerializer):
    pulp_href = RepositoryVersionIdentityField()
    number = serializers.IntegerField(read_only=True)
    repository = DetailRelatedField(
        view_name_pattern=r"repositories(-.*/.*)?-detail",
        read_only=True,
    )
    base_version = RepositoryVersionRelatedField(
        required=False,
        help_text=_(
            "A repository version whose content was used as the initial set of content "
            "for this repository version"),
    )
    content_summary = ContentSummarySerializer(
        help_text=
        _("Various count summaries of the content in the version and the HREF to view them."
          ),
        source="*",
        read_only=True,
    )

    class Meta:
        model = models.RepositoryVersion
        fields = ModelSerializer.Meta.fields + (
            "pulp_href",
            "number",
            "repository",
            "base_version",
            "content_summary",
        )
Exemplo n.º 2
0
class RepositoryAddRemoveContentSerializer(ModelSerializer,
                                           NestedHyperlinkedModelSerializer):
    add_content_units = serializers.ListField(
        help_text=_(
            "A list of content units to add to a new repository version. This content is "
            "added after remove_content_units are removed."),
        required=False,
    )
    remove_content_units = serializers.ListField(
        help_text=
        _("A list of content units to remove from the latest repository version. "
          "You may also specify '*' as an entry to remove all content. This content is "
          "removed before add_content_units are added."),
        required=False,
    )
    base_version = RepositoryVersionRelatedField(
        required=False,
        help_text=_(
            "A repository version whose content will be used as the initial set of content "
            "for the new repository version"),
    )

    def validate_remove_content_units(self, value):
        if len(value) > 1 and "*" in value:
            raise serializers.ValidationError(
                "Cannot supply content units and '*'.")
        return value

    class Meta:
        model = models.RepositoryVersion
        fields = ["add_content_units", "remove_content_units", "base_version"]
Exemplo n.º 3
0
class ReclaimSpaceSerializer(serializers.Serializer, ValidateFieldsMixin):
    """
    Serializer for reclaim disk space operation.
    """

    repo_hrefs = fields.ListField(
        required=True,
        help_text=_("Will reclaim space for the specified list of repos."),
    )
    repo_versions_keeplist = RepositoryVersionRelatedField(
        help_text=_("Will exclude repo versions from space reclaim."),
        many=True,
        required=False,
    )

    def validate_repo_hrefs(self, value):
        """
        Check that the repo_hrefs is not an empty list and contains all valid hrefs.
        Args:
            value (list): The list supplied by the user
        Returns:
            The list of pks (not hrefs) after validation
        Raises:
            ValidationError: If the list is empty or contains invalid hrefs.
        """
        if len(value) == 0:
            raise serializers.ValidationError("Must not be [].")
        from pulpcore.app.viewsets import NamedModelViewSet

        hrefs_to_return = []
        for href in value:
            hrefs_to_return.append(
                NamedModelViewSet.get_resource(href, Repository))

        return hrefs_to_return
Exemplo n.º 4
0
class RepositoryVersionSerializer(ModelSerializer,
                                  NestedHyperlinkedModelSerializer):
    pulp_href = RepositoryVersionIdentityField()
    number = serializers.IntegerField(read_only=True)
    base_version = RepositoryVersionRelatedField(
        required=False,
        help_text=_(
            'A repository version whose content was used as the initial set of content '
            'for this repository version'),
    )
    content_summary = ContentSummarySerializer(
        help_text=_(
            'Various count summaries of the content in the version and the HREF to view '
            'them.'),
        source="*",
        read_only=True,
    )

    class Meta:
        model = models.RepositoryVersion
        fields = ModelSerializer.Meta.fields + (
            'pulp_href',
            'number',
            'base_version',
            'content_summary',
        )
Exemplo n.º 5
0
class FilesystemExportSerializer(ExportSerializer):
    """
    Serializer for FilesystemExports.
    """

    publication = DetailRelatedField(
        required=False,
        help_text=_("A URI of the publication to be exported."),
        view_name_pattern=r"publications(-.*/.*)-detail",
        queryset=models.Publication.objects.all(),
        write_only=True,
    )

    repository_version = RepositoryVersionRelatedField(
        help_text=_("A URI of the repository version export."),
        required=False,
        write_only=True,
    )

    def validate(self, data):
        if ("publication" not in data and "repository_version" not in data) or (
            "publication" in data and "repository_version" in data
        ):
            raise serializers.ValidationError(
                _("publication or repository_version must either be supplied but not both.")
            )
        return data

    class Meta:
        model = models.FilesystemExport
        fields = ExportSerializer.Meta.fields + ("publication", "repository_version")
Exemplo n.º 6
0
class RepositoryVersionDistributionSerializer(BaseDistributionSerializer):
    repository = DetailRelatedField(
        required=False,
        help_text=_(
            "The latest RepositoryVersion for this Repository will be served."
        ),
        view_name_pattern=r"repositories(-.*/.*)?-detail",
        queryset=models.Repository.objects.all(),
        allow_null=True,
    )
    repository_version = RepositoryVersionRelatedField(
        required=False,
        help_text=_("RepositoryVersion to be served"),
        allow_null=True)

    def __init__(self, *args, **kwargs):
        """Initialize a RepositoryVersionDistributionSerializer and emit deprecation warnings"""
        deprecation_logger.warn(
            _("PublicationDistributionSerializer is deprecated and could be removed as early as "
              "pulpcore==3.13; use pulpcore.plugin.serializers.DistributionSerializer instead. "
              "See its docstring for more details."))
        return super().__init__(*args, **kwargs)

    class Meta:
        abstract = True
        fields = BaseDistributionSerializer.Meta.fields + (
            "repository", "repository_version")

    def validate(self, data):
        super().validate(data)

        repository_in_data = "repository" in data
        repository_version_in_data = "repository_version" in data
        repository_in_instance = self.instance.repository if self.instance else None
        repository_version_in_instance = self.instance.repository_version if self.instance else None

        if repository_in_data and repository_version_in_data:
            error = True
        elif repository_in_data and repository_version_in_instance:
            error = True
        elif repository_in_instance and repository_version_in_data:
            error = True
        else:
            error = False

        if error:
            msg = _(
                "Only one of the attributes 'publication' and 'repository_version' may be used "
                "simultaneously.")
            raise serializers.ValidationError(msg)

        return data
Exemplo n.º 7
0
class RepositoryVersionDistributionSerializer(BaseDistributionSerializer):
    repository = DetailRelatedField(
        required=False,
        help_text=_(
            "The latest RepositoryVersion for this Repository will be served."
        ),
        view_name_pattern=r"repositories(-.*/.*)?-detail",
        queryset=models.Repository.objects.all(),
        allow_null=True,
    )
    repository_version = RepositoryVersionRelatedField(
        required=False,
        help_text=_("RepositoryVersion to be served"),
        allow_null=True,
    )

    class Meta:
        abstract = True
        fields = BaseDistributionSerializer.Meta.fields + (
            "repository",
            "repository_version",
        )

    def validate(self, data):
        super().validate(data)

        repository_in_data = "repository" in data
        repository_version_in_data = "repository_version" in data
        repository_in_instance = self.instance.repository if self.instance else None
        repository_version_in_instance = self.instance.repository_version if self.instance else None

        if repository_in_data and repository_version_in_data:
            error = True
        elif repository_in_data and repository_version_in_instance:
            error = True
        elif repository_in_instance and repository_version_in_data:
            error = True
        else:
            error = False

        if error:
            msg = _(
                "The attributes 'repository' and 'repository_version' must be used"
                " exclusively.")
            raise serializers.ValidationError(msg)

        return data
Exemplo n.º 8
0
class PublicationSerializer(ModelSerializer):
    pulp_href = DetailIdentityField(
        view_name_pattern=r"publications(-.*/.*)-detail")
    repository_version = RepositoryVersionRelatedField(required=False)
    repository = DetailRelatedField(
        help_text=_("A URI of the repository to be published."),
        required=False,
        label=_("Repository"),
        view_name_pattern=r"repositories(-.*/.*)?-detail",
        queryset=models.Repository.objects.all(),
    )

    def validate(self, data):
        if hasattr(self, "initial_data"):
            validate_unknown_fields(self.initial_data, self.fields)

        repository = data.pop("repository",
                              None)  # not an actual field on publication
        repository_version = data.get("repository_version")
        if not repository and not repository_version:
            raise serializers.ValidationError(
                _("Either the 'repository' or 'repository_version' need to be specified"
                  ))
        elif not repository and repository_version:
            return data
        elif repository and not repository_version:
            version = repository.latest_version()
            if version:
                new_data = {"repository_version": version}
                new_data.update(data)
                return new_data
            else:
                raise serializers.ValidationError(detail=_(
                    "Repository has no version available to create Publication from"
                ))
        raise serializers.ValidationError(
            _("Either the 'repository' or 'repository_version' need to be specified "
              "but not both."))

    class Meta:
        abstract = True
        model = models.Publication
        fields = ModelSerializer.Meta.fields + ("repository_version",
                                                "repository")
Exemplo n.º 9
0
class Pulp2RepositoriesSerializer(ModelSerializer):
    """
    A serializer for the Pulp2Repositories
    """
    pulp_href = IdentityField(view_name='pulp2repositories-detail')
    pulp2_object_id = serializers.CharField(max_length=255)
    pulp2_repo_id = serializers.CharField()
    pulp2_repo_type = serializers.CharField()
    is_migrated = serializers.BooleanField(default=False)
    not_in_plan = serializers.BooleanField(default=False)

    pulp3_repository_version = RepositoryVersionRelatedField(
        required=False,
        help_text=_('RepositoryVersion to be served'),
        allow_null=True,
    )

    pulp3_remote_href = serializers.SerializerMethodField(read_only=True)
    pulp3_publication_href = serializers.SerializerMethodField(read_only=True)
    pulp3_distribution_hrefs = serializers.SerializerMethodField(
        read_only=True)
    pulp3_repository_href = serializers.SerializerMethodField(read_only=True)

    @extend_schema_serializer(many=False)
    def get_pulp3_repository_href(self, obj):
        """
        Get pulp3_repository_href from pulp2repo
        """
        rv = obj.pulp3_repository_version
        if rv:
            return get_pulp_href(rv.repository)

    @extend_schema_serializer(many=False)
    def get_pulp3_remote_href(self, obj):
        """
        Get pulp3_remote_href from pulp2repo
        """
        remote = obj.pulp3_repository_remote
        if remote:
            return get_pulp_href(remote)

    @extend_schema_serializer(many=False)
    def get_pulp3_publication_href(self, obj):
        """
        Get pulp3_publication_href from pulp3_repository_version
        """
        rv = obj.pulp3_repository_version
        if rv:
            return get_pulp_href(rv.publication_set.first())

    @extend_schema_serializer(many=True)
    def get_pulp3_distribution_hrefs(self, obj):
        """
        Get pulp3_distribution_hrefs from pulp3_repository_version
        """
        dist_list = []
        rv = obj.pulp3_repository_version
        if not rv:
            return dist_list
        result_qs = rv.publication_set.all()
        if result_qs:
            # repo_version  has publication, therefore is a PublicationDistribution
            for publication in result_qs:
                distribution_type = f'{publication.pulp_type.replace(".", "_")}distribution'
                plugin_distribution = getattr(publication, distribution_type)
                dist_list.extend(plugin_distribution.all())
        else:
            # empty result_qs means that repo_version does not need publication,
            # or repo_version was not published/distributed
            pulp_type = rv.repository.pulp_type
            distribution_type = f'{pulp_type.replace(".", "_")}distribution'
            if hasattr(rv, distribution_type):
                # repo_version is distributed directly trough RepositoryDistribution
                plugin_distribution = getattr(rv, distribution_type)
                dist_list = plugin_distribution.all()
            else:
                # repo_version was not published/distributed
                return dist_list
        return [get_pulp_href(dist) for dist in dist_list]

    class Meta:
        fields = ModelSerializer.Meta.fields + (
            "pulp2_object_id",
            "pulp2_repo_id",
            "pulp2_repo_type",
            "is_migrated",
            "not_in_plan",
            "pulp3_repository_version",
            "pulp3_remote_href",
            "pulp3_publication_href",
            "pulp3_distribution_hrefs",
            "pulp3_repository_href",
        )
        model = Pulp2Repository
Exemplo n.º 10
0
class PulpExportSerializer(ExportSerializer):
    """
    Serializer for PulpExports.
    """

    output_file_info = serializers.JSONField(
        help_text=
        _("Dictionary of filename: sha256hash entries for export-output-file(s)"
          ),
        read_only=True,
    )

    toc_info = serializers.JSONField(
        help_text=_(
            "Filename and sha256-checksum of table-of-contents for this export"
        ),
        read_only=True,
    )

    dry_run = serializers.BooleanField(
        help_text=_(
            "Generate report on what would be exported and disk-space required."
        ),
        default=False,
        required=False,
        write_only=True,
    )
    full = serializers.BooleanField(
        help_text=_("Do a Full (true) or Incremental (false) export."),
        default=True,
        required=False,
        write_only=True,
    )
    versions = RepositoryVersionRelatedField(
        help_text=
        _("List of explicit repo-version hrefs to export (replaces current_version)."
          ),
        many=True,
        required=False,
        write_only=True,
    )

    MAX_CHUNK_BYTES = 1024 * 1024 * 1024 * 1024  # 1 TB
    chunk_size = serializers.CharField(
        help_text=_(
            "Chunk export-tarfile into pieces of chunk_size bytes. " +
            "Recognizes units of B/KB/MB/GB/TB. A chunk has a maximum " +
            "size of 1TB."),
        required=False,
        write_only=True,
    )

    start_versions = RepositoryVersionRelatedField(
        help_text=
        _("List of explicit last-exported-repo-version hrefs (replaces last_export)."
          ),
        many=True,
        required=False,
        write_only=True,
    )

    def _validate_versions_to_repos(self, the_versions):
        """
        If specifying repo-versions explicitly, must provide a version for each exporter-repository
        """
        # make sure counts match
        the_exporter = self.context.get("exporter", None)
        num_repos = the_exporter.repositories.count()
        if num_repos != len(the_versions):
            raise serializers.ValidationError(
                _("Number of versions ({}) does not match the number of Repositories ({}) for "
                  + "the owning  Exporter!").format(num_repos,
                                                    len(the_versions)))

        # make sure the specified versions 'belong to' the exporter.repositories
        exporter_repos = set(the_exporter.repositories.all())
        version_repos = set([vers.repository for vers in the_versions])
        if exporter_repos != version_repos:
            raise serializers.ValidationError(
                _("Requested RepositoryVersions must belong to the Repositories named by the "
                  + "Exporter!"))
        return the_versions

    def validate_versions(self, versions):
        return self._validate_versions_to_repos(versions)

    def validate_start_versions(self, start_versions):
        return self._validate_versions_to_repos(start_versions)

    def validate(self, data):
        # If we requested start_versions, make sure we did not forget to specify full=False
        if data.get("start_versions", None) and data.get("full", True):
            raise serializers.ValidationError(
                _("start_versions is only valid for incremental exports (full=False)"
                  ))

        # If we requested full=False, make sure we either specified start_versions= or
        # have a previous-export for our Exporter.
        if not data.get("full", True):
            the_exporter = self.context.get("exporter", None)
            if not data.get("start_versions",
                            None) and not the_exporter.last_export:
                raise serializers.ValidationError(
                    _("Incremental export can only be requested when there is a previous export "
                      + "or start_versions= has been specified."))
        return super().validate(data)

    @staticmethod
    def _parse_size(size):
        try:
            # based on https://stackoverflow.com/a/42865957/2002471
            units = {
                "B": 1,
                "KB": 2**10,
                "MB": 2**20,
                "GB": 2**30,
                "TB": 2**40
            }
            size = size.upper()
            if not re.match(r" ", size):
                size = re.sub(r"([KMGT]?B)", r" \1", size)
            number, unit = [string.strip() for string in size.split()]
            return int(float(number) * units[unit])
        except ValueError:
            raise serializers.ValidationError(
                _("chunk_size '{}' is not valid (valid units are B/KB/MB/GB/TB)"
                  ).format(size))

    def validate_chunk_size(self, chunk_size):
        the_size = self._parse_size(chunk_size)
        if the_size <= 0:
            raise serializers.ValidationError(
                _("Chunk size {} is not greater than zero!").format(the_size))
        if the_size > self.MAX_CHUNK_BYTES:
            raise serializers.ValidationError(
                _("Chunk size in bytes {} is greater than max-chunk-size {}!").
                format(the_size, self.MAX_CHUNK_BYTES))
        return the_size

    class Meta:
        model = models.PulpExport
        fields = ExportSerializer.Meta.fields + (
            "full",
            "dry_run",
            "versions",
            "chunk_size",
            "output_file_info",
            "start_versions",
            "toc_info",
        )
Exemplo n.º 11
0
class Pulp2RepositoriesSerializer(ModelSerializer):
    """
    A serializer for the Pulp2Repositories
    """
    pulp_href = IdentityField(
        view_name='pulp2repositories-detail'
    )
    pulp2_object_id = serializers.CharField(max_length=255)
    pulp2_repo_id = serializers.CharField()
    pulp2_repo_type = serializers.CharField()
    is_migrated = serializers.BooleanField(default=False)
    not_in_plan = serializers.BooleanField(default=False)

    pulp3_repository_version = RepositoryVersionRelatedField(
        required=False,
        help_text=_('RepositoryVersion to be served'),
        allow_null=True,
    )

    pulp3_remote_href = serializers.SerializerMethodField(read_only=True)
    pulp3_publication_href = serializers.SerializerMethodField(read_only=True)
    pulp3_distribution_hrefs = serializers.SerializerMethodField(read_only=True)
    pulp3_repository_href = serializers.SerializerMethodField(read_only=True)

    @extend_schema_field(field=serializers.CharField)
    def get_pulp3_repository_href(self, obj):
        """
        Get pulp3_repository_href from pulp2repo
        """
        rv = obj.pulp3_repository_version
        if rv:
            return get_pulp_href(rv.repository)

    @extend_schema_field(field=serializers.CharField)
    def get_pulp3_remote_href(self, obj):
        """
        Get pulp3_remote_href from pulp2repo
        """
        remote = obj.pulp3_repository_remote
        if remote:
            return get_pulp_href(remote)

    @extend_schema_field(field=serializers.CharField)
    def get_pulp3_publication_href(self, obj):
        """
        Get pulp3_publication_href from pulp3_repository_version
        """
        rv = obj.pulp3_repository_version
        if rv:
            return get_pulp_href(rv.publication_set.filter(complete=True).first())

    @extend_schema_field(field=serializers.ListField(child=serializers.CharField()))
    def get_pulp3_distribution_hrefs(self, obj):
        """
        Get pulp3_distribution_hrefs from pulp3_repository_version
        """
        pulp2dists = obj.pulp2_dists.filter(not_in_plan=False, is_migrated=True)
        return [get_pulp_href(dist.pulp3_distribution) for dist in pulp2dists]

    class Meta:
        fields = ModelSerializer.Meta.fields + (
            "pulp2_object_id",
            "pulp2_repo_id",
            "pulp2_repo_type",
            "is_migrated",
            "not_in_plan",
            "pulp3_repository_version",
            "pulp3_remote_href",
            "pulp3_publication_href",
            "pulp3_distribution_hrefs",
            "pulp3_repository_href",
        )
        model = Pulp2Repository