Add the basics of geographic data distribution and get the tests to work.

This commit is contained in:
Jake Moshenko 2014-06-17 16:03:43 -04:00
parent 2bf12996f5
commit bf98575feb
23 changed files with 198 additions and 100 deletions

View file

@ -845,20 +845,28 @@ def get_repository(namespace_name, repository_name):
def get_repo_image(namespace_name, repository_name, image_id):
query = (Image
.select(Image, ImageStorage)
location_list = list((ImageStoragePlacement
.select(ImageStoragePlacement, Image, ImageStorage, ImageStorageLocation)
.join(ImageStorageLocation)
.switch(ImageStoragePlacement)
.join(ImageStorage)
.join(Image)
.join(Repository)
.switch(Image)
.join(ImageStorage, JOIN_LEFT_OUTER)
.where(Repository.name == repository_name,
Repository.namespace == namespace_name,
Image.docker_image_id == image_id))
Image.docker_image_id == image_id)))
try:
return query.get()
except Image.DoesNotExist:
if not location_list:
return None
location_names = {location.location.name for location in location_list}
image = location_list[0].storage.image
image.storage = location_list[0].storage
image.storage.locations = location_names
return image
def repository_is_public(namespace_name, repository_name):
joined = Repository.select().join(Visibility)
@ -940,7 +948,7 @@ def create_repository(namespace, name, creating_user, visibility='private'):
return repo
def __translate_ancestry(old_ancestry, translations, repository, username):
def __translate_ancestry(old_ancestry, translations, repository, username, preferred_location):
if old_ancestry == '/':
return '/'
@ -950,9 +958,8 @@ def __translate_ancestry(old_ancestry, translations, repository, username):
# Figure out which docker_image_id the old id refers to, then find a
# a local one
old = Image.select(Image.docker_image_id).where(Image.id == old_id).get()
image_in_repo = find_create_or_link_image(old.docker_image_id,
repository, username,
translations)
image_in_repo = find_create_or_link_image(old.docker_image_id, repository, username,
translations, preferred_location)
translations[old_id] = image_in_repo.id
return translations[old_id]
@ -962,8 +969,8 @@ def __translate_ancestry(old_ancestry, translations, repository, username):
return '/%s/' % '/'.join(new_ids)
def find_create_or_link_image(docker_image_id, repository, username,
translations):
def find_create_or_link_image(docker_image_id, repository, username, translations,
preferred_location):
with config.app_config['DB_TRANSACTION_FACTORY'](db):
repo_image = get_repo_image(repository.namespace, repository.name,
docker_image_id)
@ -990,20 +997,29 @@ def find_create_or_link_image(docker_image_id, repository, username,
msg = 'Linking image to existing storage with docker id: %s and uuid: %s'
logger.debug(msg, docker_image_id, to_copy.storage.uuid)
new_image_ancestry = __translate_ancestry(to_copy.ancestors,
translations, repository,
username)
new_image_ancestry = __translate_ancestry(to_copy.ancestors, translations, repository,
username, preferred_location)
storage = to_copy.storage
storage.locations = {placement.location.name
for placement in storage.imagestorageplacement_set}
origin_image_id = to_copy.id
except Image.DoesNotExist:
logger.debug('Creating new storage for docker id: %s', docker_image_id)
storage = ImageStorage.create()
location = ImageStorageLocation.get(name=preferred_location)
ImageStoragePlacement.create(location=location, storage=storage)
storage.locations = {preferred_location}
logger.debug('Storage locations: %s', storage.locations)
new_image = Image.create(docker_image_id=docker_image_id,
repository=repository, storage=storage,
ancestors=new_image_ancestry)
logger.debug('new_image storage locations: %s', new_image.storage.locations)
if origin_image_id:
logger.debug('Storing translation %s -> %s', origin_image_id, new_image.id)
translations[origin_image_id] = new_image.id
@ -1130,9 +1146,14 @@ def garbage_collect_repository(namespace_name, repository_name):
for storage in storage_to_remove:
logger.debug('Garbage collecting image storage: %s', storage.uuid)
storage.delete_instance()
image_path = config.store.image_path(storage.uuid)
config.store.remove(image_path)
for placement in storage.imagestorageplacement_set:
location_name = placement.location.name
placement.delete_instance()
config.store.remove(location_name, image_path)
storage.delete_instance()
return len(to_remove)