|
| 1 | +import createrepo_c as cr |
1 | 2 | import logging |
2 | 3 | import traceback |
3 | 4 | from gettext import gettext as _ |
4 | 5 |
|
| 6 | +from django.conf import settings |
| 7 | +from django.db import DatabaseError |
5 | 8 | from drf_spectacular.utils import extend_schema_serializer |
6 | 9 | from rest_framework import serializers |
7 | 10 | from rest_framework.exceptions import NotAcceptable |
8 | 11 |
|
| 12 | +from pulpcore.plugin.models import Artifact, PulpTemporaryFile |
9 | 13 | from pulpcore.plugin.serializers import ( |
| 14 | + ArtifactSerializer, |
10 | 15 | ContentChecksumSerializer, |
11 | 16 | SingleArtifactContentUploadSerializer, |
12 | 17 | ) |
@@ -382,3 +387,67 @@ class Meta: |
382 | 387 | "checksum_type", |
383 | 388 | ) |
384 | 389 | model = Package |
| 390 | + |
| 391 | + |
| 392 | +class PackageUploadSerializer(PackageSerializer): |
| 393 | + """ |
| 394 | + Serializer for requests to synchronously upload RPM packages. |
| 395 | + """ |
| 396 | + |
| 397 | + class Meta(PackageSerializer.Meta): |
| 398 | + # This API does not support uploading to a repository |
| 399 | + fields = tuple(f for f in PackageSerializer.Meta.fields if f != "repository") |
| 400 | + model = Package |
| 401 | + # Name used for the OpenAPI request object |
| 402 | + ref_name = "PackageUpload" |
| 403 | + |
| 404 | + def validate(self, data): |
| 405 | + uploaded_file = data.get("file") |
| 406 | + # export META from rpm and prepare dict as saveable format |
| 407 | + try: |
| 408 | + cr_object = cr.package_from_rpm( |
| 409 | + uploaded_file.file.name, changelog_limit=settings.KEEP_CHANGELOG_LIMIT |
| 410 | + ) |
| 411 | + new_pkg = Package.createrepo_to_dict(cr_object) |
| 412 | + except OSError as e: |
| 413 | + log.info(traceback.format_exc()) |
| 414 | + raise NotAcceptable(detail="RPM file cannot be parsed for metadata") from e |
| 415 | + |
| 416 | + # Get or create the Artifact |
| 417 | + if "file" in data: |
| 418 | + file = data.pop("file") |
| 419 | + # if artifact already exists, let's use it |
| 420 | + try: |
| 421 | + artifact = Artifact.objects.get( |
| 422 | + sha256=file.hashers["sha256"].hexdigest(), pulp_domain=get_domain_pk() |
| 423 | + ) |
| 424 | + if not artifact.pulp_domain.get_storage().exists(artifact.file.name): |
| 425 | + artifact.file = file |
| 426 | + artifact.save() |
| 427 | + else: |
| 428 | + artifact.touch() |
| 429 | + except (Artifact.DoesNotExist, DatabaseError): |
| 430 | + artifact_data = {"file": file} |
| 431 | + serializer = ArtifactSerializer(data=artifact_data) |
| 432 | + serializer.is_valid(raise_exception=True) |
| 433 | + artifact = serializer.save() |
| 434 | + data["artifact"] = artifact |
| 435 | + |
| 436 | + filename = ( |
| 437 | + format_nvra( |
| 438 | + new_pkg["name"], |
| 439 | + new_pkg["version"], |
| 440 | + new_pkg["release"], |
| 441 | + new_pkg["arch"], |
| 442 | + ) |
| 443 | + + ".rpm" |
| 444 | + ) |
| 445 | + |
| 446 | + if not data.get("relative_path"): |
| 447 | + data["relative_path"] = filename |
| 448 | + new_pkg["location_href"] = filename |
| 449 | + else: |
| 450 | + new_pkg["location_href"] = data["relative_path"] |
| 451 | + |
| 452 | + data.update(new_pkg) |
| 453 | + return data |
0 commit comments