Пример #1
0
    def _finalize_blob_storage(self, app_config):
        """ When an upload is successful, this ends the uploading process from the storage's perspective.

            Returns True if the blob already existed. """
        computed_digest = digest_tools.sha256_digest_from_hashlib(
            self.blob_upload.sha_state)
        final_blob_location = digest_tools.content_path(computed_digest)

        # Close the database connection before we perform this operation, as it can take a while
        # and we shouldn't hold the connection during that time.
        with CloseForLongOperation(app_config):
            # Move the storage into place, or if this was a re-upload, cancel it
            already_existed = self.storage.exists(
                {self.blob_upload.location_name}, final_blob_location)
            if already_existed:
                # It already existed, clean up our upload which served as proof that the
                # uploader had the blob.
                self.storage.cancel_chunked_upload(
                    {self.blob_upload.location_name},
                    self.blob_upload.upload_id,
                    self.blob_upload.storage_metadata,
                )
            else:
                # We were the first ones to upload this image (at least to this location)
                # Let's copy it into place
                self.storage.complete_chunked_upload(
                    {self.blob_upload.location_name},
                    self.blob_upload.upload_id,
                    final_blob_location,
                    self.blob_upload.storage_metadata,
                )

        return already_existed
Пример #2
0
    def commit_to_blob(self, app_config, expected_digest=None):
        """
        Commits the blob upload to a blob under the repository. The resulting blob will be marked to
        not be GCed for some period of time (as configured by `committed_blob_expiration`).

        If expected_digest is specified, the content digest of the data uploaded for the blob is
        compared to that given and, if it does not match, a BlobDigestMismatchException is raised.
        The digest given must be of type `Digest` and not a string.
        """
        # Compare the content digest.
        if expected_digest is not None:
            self._validate_digest(expected_digest)

        # Finalize the storage.
        storage_already_existed = self._finalize_blob_storage(app_config)

        # Convert the upload to a blob.
        computed_digest_str = digest_tools.sha256_digest_from_hashlib(
            self.blob_upload.sha_state)

        with db_transaction():
            blob = registry_model.commit_blob_upload(
                self.blob_upload, computed_digest_str,
                self.settings.committed_blob_expiration)
            if blob is None:
                return None

        self.committed_blob = blob
        return blob
Пример #3
0
 def _validate_digest(self, expected_digest):
     """
 Verifies that the digest's SHA matches that of the uploaded data.
 """
     computed_digest = digest_tools.sha256_digest_from_hashlib(
         self.blob_upload.sha_state)
     if not digest_tools.digests_equal(computed_digest, expected_digest):
         logger.error(
             'Digest mismatch for upload %s: Expected digest %s, found digest %s',
             self.blob_upload.upload_id, expected_digest, computed_digest)
         raise BlobDigestMismatchException()