def _save_content_artifact(self, download_result, content_artifact): """ Create/Get an Artifact and associate it to a ContentArtifact. Create (or get if already existing) an :class:`~pulpcore.plugin.models.Artifact` based on the `download_result` and associate it to the given `content_artifact`. Both the created artifact and the updated content_artifact are saved to the DB. Plugin-writers may overide this method if their content module requires additional/different steps for saving. Args: download_result (:class:`~pulpcore.plugin.download.DownloadResult`: The DownloadResult for the downloaded artifact. content_artifact (:class:`~pulpcore.plugin.models.ContentArtifact`): The ContentArtifact to associate the Artifact with. Returns: The associated :class:`~pulpcore.plugin.models.Artifact`. """ artifact = Artifact( **download_result.artifact_attributes, file=download_result.path ) with transaction.atomic(): try: with transaction.atomic(): artifact.save() except IntegrityError: artifact = Artifact.objects.get(artifact.q()) content_artifact.artifact = artifact content_artifact.save() return artifact
def _save_artifact(self, download_result, remote_artifact): """ Create/Get an Artifact and associate it to a RemoteArtifact and/or ContentArtifact. Create (or get if already existing) an :class:`~pulpcore.plugin.models.Artifact` based on the `download_result` and associate it to the `content_artifact` of the given `remote_artifact`. Both the created artifact and the updated content_artifact are saved to the DB. The `remote_artifact` is also saved for the pull-through caching use case. Plugin-writers may overide this method if their content module requires additional/different steps for saving. Args: download_result (:class:`~pulpcore.plugin.download.DownloadResult`: The DownloadResult for the downloaded artifact. remote_artifact (:class:`~pulpcore.plugin.models.RemoteArtifact`): The RemoteArtifact to associate the Artifact with. Returns: The associated :class:`~pulpcore.plugin.models.Artifact`. """ content_artifact = remote_artifact.content_artifact remote = remote_artifact.remote artifact = Artifact(**download_result.artifact_attributes, file=download_result.path) with transaction.atomic(): try: with transaction.atomic(): artifact.save() except IntegrityError: artifact = Artifact.objects.get(artifact.q()) update_content_artifact = True if content_artifact._state.adding: # This is the first time pull-through content was requested. rel_path = content_artifact.relative_path c_type = remote.get_remote_artifact_content_type(rel_path) content = c_type.init_from_artifact_and_relative_path(artifact, rel_path) try: with transaction.atomic(): content.save() content_artifact.content = content content_artifact.save() except IntegrityError: # There is already content for this Artifact content = c_type.objects.get(content.q()) artifacts = content._artifacts if artifact.sha256 != artifacts[0].sha256: raise RuntimeError( "The Artifact downloaded during pull-through does not " "match the Artifact already stored for the same " "content." ) content_artifact = ContentArtifact.objects.get(content=content) update_content_artifact = False try: with transaction.atomic(): remote_artifact.content_artifact = content_artifact remote_artifact.save() except IntegrityError: # Remote artifact must have already gotten saved during a parallel request log.info("RemoteArtifact already exists.") if update_content_artifact: content_artifact.artifact = artifact content_artifact.save() return artifact