From 3f70400ced7addcef6246a3261c3a7f7aa11d6fb Mon Sep 17 00:00:00 2001 From: Disassembler Date: Thu, 16 Apr 2020 18:29:05 +0200 Subject: [PATCH] Fix app update logic determining layers to retain --- usr/lib/python3.8/vmmgr/vmmgr.py | 37 +++++++++++++++++++------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/usr/lib/python3.8/vmmgr/vmmgr.py b/usr/lib/python3.8/vmmgr/vmmgr.py index 0441b4f..7f76a8b 100644 --- a/usr/lib/python3.8/vmmgr/vmmgr.py +++ b/usr/lib/python3.8/vmmgr/vmmgr.py @@ -200,8 +200,10 @@ def install_app(app_name, queue): for container in new_containers: required_images.extend(repo_online.get_image(container['image'])['layers']) local_images = repo_local.get_images() - # Layers need to be downloaded in correct order - for layer in list(dict.fromkeys(required_images)): + # Create (deduplicate) set of layers while retaining the correct order + required_images = list(dict.fromkeys(required_images)) + # Download layers in correct order + for layer in required_images: if layer not in local_images: queue.download_image(Image(layer, False)) queue.install_app(App(app_name, False, False)) @@ -212,8 +214,11 @@ def uninstall_app(app_name, queue): queue.uninstall_app(app) # Remove unused layers removed_containers = [container.name for container in app.containers] - retained_containers = [definition for name,definition in repo_local.get_containers().items() if name not in removed_containers] - remove_unused_layers(retained_containers, queue) + retained_layers = set() + for name,definition in repo_local.get_containers().items(): + if name not in removed_containers: + retained_layers.update(definition['layers']) + remove_unused_layers(retained_layers, queue) def update_app(app_name, queue): # Enqueue layers and application download, registration and update script execution @@ -222,27 +227,29 @@ def update_app(app_name, queue): for container in new_containers: required_images.extend(repo_online.get_image(container['image'])['layers']) local_images = repo_local.get_images() - # Layers need to be downloaded in correct order - for layer in list(dict.fromkeys(required_images)): + # Create (deduplicate) set of layers while retaining the correct order + required_images = list(dict.fromkeys(required_images)) + # Download layers in correct order + for layer in required_images: if layer not in local_images: queue.download_image(Image(layer, False)) app = App(app_name, False) queue.update_app(app) # Remove unused layers removed_containers = [container.name for container in app.containers] - retained_containers = [definition for name,definition in repo_local.get_containers().items() if name not in removed_containers] + new_containers - remove_unused_layers(retained_containers, queue) + retained_layers = set(required_images) + for name,definition in repo_local.get_containers().items(): + if name not in removed_containers: + retained_layers.update(definition['layers']) + remove_unused_layers(retained_layers, queue) -def remove_unused_layers(retained_containers, queue): +def remove_unused_layers(retained_layers, queue): # Enqueue removal of images which won't be used in any locally defined containers anymore - used_images = set() - for definition in retained_containers: - used_images.update(definition['layers']) - # Build dependency tree to safely remove the images in order of dependency depsolver = DepSolver() - for image in set(repo_local.get_images()) - used_images: + # Build dependency tree to safely remove the images in order of dependency + for image in set(repo_local.get_images()) - retained_layers: image = Image(image) - depsolver.add(image.name, set(image.layers) - used_images, image) + depsolver.add(image.name, set(image.layers) - retained_layers, image) # Enqueue the removal actions for image in reversed(depsolver.solve()): queue.delete_image(image)