Example #1
0
def find_or_create_derived_storage(source_image,
                                   transformation_name,
                                   preferred_location,
                                   varying_metadata=None):
    existing = find_derived_storage_for_image(source_image,
                                              transformation_name,
                                              varying_metadata)
    if existing is not None:
        return existing

    uniqueness_hash = _get_uniqueness_hash(varying_metadata)
    trans = ImageStorageTransformation.get(name=transformation_name)
    new_storage = storage.create_v1_storage(preferred_location)

    try:
        derived = DerivedStorageForImage.create(
            source_image=source_image,
            derivative=new_storage,
            transformation=trans,
            uniqueness_hash=uniqueness_hash,
        )
    except IntegrityError:
        # Storage was created while this method executed. Just return the existing.
        ImageStoragePlacement.delete().where(
            ImageStoragePlacement.storage == new_storage).execute()
        new_storage.delete_instance()
        return find_derived_storage_for_image(source_image,
                                              transformation_name,
                                              varying_metadata)

    return derived
Example #2
0
File: image.py Project: quay/quay
def find_create_or_link_image(
    docker_image_id, repo_obj, username, translations, preferred_location
):

    # First check for the image existing in the repository. If found, we simply return it.
    repo_image = get_repo_image(repo_obj.namespace_user.username, repo_obj.name, docker_image_id)
    if repo_image:
        return repo_image

    # We next check to see if there is an existing storage the new image can link to.
    existing_image_query = (
        Image.select(Image, ImageStorage)
        .distinct()
        .join(ImageStorage)
        .switch(Image)
        .join(Repository)
        .join(RepositoryPermission, JOIN.LEFT_OUTER)
        .switch(Repository)
        .join(Namespace, on=(Repository.namespace_user == Namespace.id))
        .where(Image.docker_image_id == docker_image_id)
    )

    existing_image_query = _basequery.filter_to_repos_for_user(
        existing_image_query, _namespace_id_for_username(username)
    )

    # If there is an existing image, we try to translate its ancestry and copy its storage.
    new_image = None
    try:
        logger.debug("Looking up existing image for ID: %s", docker_image_id)
        existing_image = existing_image_query.get()

        logger.debug("Existing image %s found for ID: %s", existing_image.id, docker_image_id)
        new_image = _find_or_link_image(
            existing_image, repo_obj, username, translations, preferred_location
        )
        if new_image:
            return new_image
    except Image.DoesNotExist:
        logger.debug("No existing image found for ID: %s", docker_image_id)

    # Otherwise, create a new storage directly.
    with db_transaction():
        # Final check for an existing image, under the transaction.
        repo_image = get_repo_image(
            repo_obj.namespace_user.username, repo_obj.name, docker_image_id
        )
        if repo_image:
            return repo_image

        logger.debug("Creating new storage for docker id: %s", docker_image_id)
        new_storage = storage.create_v1_storage(preferred_location)

        return Image.create(
            docker_image_id=docker_image_id, repository=repo_obj, storage=new_storage, ancestors="/"
        )