Added post update removal of residual images
After performing an application update, the app environment doesn't have an image cleanup process to remove unused docker images With this update, after the update is complete the app itself compare both old and new images list and remove the unused ones TEST PLAN: - PASS: Build two application tarballs with distinct images - PASS: Apply first tarball - Pass: Set up an update process with the second tarball - PASS: Check if second tarball is applied - PASS: List images - PASS: Check if older images are still listed Story: 2011262 Task: 51686 Change-Id: I5194d9e6329dc0a35f5638222f4631debcac6a4c Signed-off-by: jbarboza <joaopedro.barbozalioneza@windriver.com>
This commit is contained in:
@@ -94,6 +94,9 @@ class OpenstackAppLifecycleOperator(base.AppLifecycleOperator):
|
||||
if hook_info.operation == constants.APP_APPLY_OP and \
|
||||
hook_info.relative_timing == constants.APP_LIFECYCLE_TIMING_PRE:
|
||||
return self._pre_update_actions(app)
|
||||
elif hook_info.operation == constants.APP_APPLY_OP and \
|
||||
hook_info.relative_timing == constants.APP_LIFECYCLE_TIMING_POST:
|
||||
return self._post_update_image_actions(app)
|
||||
|
||||
# Default behavior
|
||||
super(OpenstackAppLifecycleOperator, self).app_lifecycle_actions(context, conductor_obj, app_op, app,
|
||||
@@ -507,6 +510,20 @@ class OpenstackAppLifecycleOperator(base.AppLifecycleOperator):
|
||||
resource_name='mariadb'
|
||||
)
|
||||
|
||||
def _post_update_image_actions(self, app):
|
||||
"""Perform post update actions, deleting residual images.
|
||||
|
||||
:param app: AppOperator.Application object
|
||||
"""
|
||||
images_base_dir = app.sync_imgfile.split(app.name)[0]
|
||||
app_version_list = app_utils.get_app_version_list(images_base_dir, app.name)
|
||||
if len(app_version_list) > 1:
|
||||
LOG.info("Deleting unused images for app %s", app.name)
|
||||
residual_images = app_utils.get_residual_images(app.sync_imgfile, app.version, app_version_list)
|
||||
|
||||
if len(residual_images) > 0:
|
||||
app_utils.delete_residual_images(residual_images)
|
||||
|
||||
def _recover_backup_snapshot(self, app):
|
||||
"""Perform pre recover backup actions
|
||||
|
||||
|
||||
@@ -628,6 +628,128 @@ def update_helmrelease(release, patch):
|
||||
LOG.error(f"Unexpected error while updating helmrelease: {e}")
|
||||
|
||||
|
||||
def get_app_version_list(base_dir: str, app_name: str) -> list:
|
||||
"""
|
||||
Retrieve a list of versions for a given application from YAML files.
|
||||
|
||||
Args:
|
||||
base_dir (str): The base directory where application data is stored.
|
||||
app_name (str): The name of the application.
|
||||
|
||||
Returns:
|
||||
list: A list of versions for the specified application.
|
||||
"""
|
||||
return os.listdir(os.path.join(base_dir, app_name))
|
||||
|
||||
|
||||
def get_image_list(image_dir: str) -> list:
|
||||
"""
|
||||
Retrieve a list of images for a given application from YAML files.
|
||||
|
||||
Args:
|
||||
image_dir (str): The base directory where application data is stored.
|
||||
|
||||
Returns:
|
||||
list: A list of images for the specified application.
|
||||
"""
|
||||
with open(image_dir, 'r', encoding='utf-8') as f:
|
||||
return yaml.safe_load(f)["download_images"]
|
||||
|
||||
|
||||
def get_residual_images(image_file_dir: str, app_version: str, app_version_list: list) -> list:
|
||||
"""
|
||||
Retrieve a list of residual images for a given application.
|
||||
|
||||
Args:
|
||||
image_file_dir (str): The directory containing the image files.
|
||||
app_version (str): The specific version of the application.
|
||||
app_version_list (list): A list of all available application versions.
|
||||
|
||||
Returns:
|
||||
list: A list of residual images that are present in older versions
|
||||
but not in the current version.
|
||||
"""
|
||||
|
||||
new_images_list = get_image_list(image_file_dir)
|
||||
app_version_list.remove(app_version)
|
||||
|
||||
old_images_list = []
|
||||
last_version = app_version
|
||||
for version in app_version_list:
|
||||
file_name = image_file_dir.replace(last_version, version)
|
||||
old_images_list.extend(get_image_list(file_name))
|
||||
last_version = version
|
||||
|
||||
return list(set(old_images_list) - set(new_images_list))
|
||||
|
||||
|
||||
def delete_residual_images(image_list: list):
|
||||
"""Remove a list of images from the system registry.
|
||||
Args:
|
||||
image (list): A list of image names to be removed.
|
||||
"""
|
||||
|
||||
image_json = list_crictl_images()
|
||||
|
||||
for image in image_list:
|
||||
image_id = get_image_id(image, image_json)
|
||||
if not image_id:
|
||||
LOG.error(f"Image {image} not found in the system registry.")
|
||||
continue
|
||||
LOG.info(f"Removing residual image: {image}")
|
||||
cmd = [
|
||||
"crictl", "rmi", image_id
|
||||
]
|
||||
try:
|
||||
process = subprocess.run(
|
||||
args=["bash", "-c", f"source /etc/platform/openrc && {' '.join(cmd)}"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
shell=False)
|
||||
|
||||
LOG.info(f"Stdout: {process.stdout}")
|
||||
LOG.info(f"Stderr: {process.stderr}")
|
||||
process.check_returncode()
|
||||
except Exception as e:
|
||||
LOG.error(f"Unexpected error while removing image {image}: {e}")
|
||||
|
||||
|
||||
def list_crictl_images() -> json:
|
||||
"""List all images in the system registry.
|
||||
Returns: A dict of images in the system registry.
|
||||
"""
|
||||
cmd = [
|
||||
"crictl", "images", "--output", "json"
|
||||
]
|
||||
try:
|
||||
process = subprocess.run(
|
||||
args=["bash", "-c", f"source /etc/platform/openrc && {' '.join(cmd)}"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
shell=False)
|
||||
|
||||
LOG.info(f"Stderr: {process.stderr}")
|
||||
process.check_returncode()
|
||||
return json.loads(process.stdout)
|
||||
except Exception as e:
|
||||
LOG.error(f"Unexpected error while listing images: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def get_image_id(image_name: str, image_json: json) -> str:
|
||||
"""Get the image ID from the system registry.
|
||||
Args:
|
||||
image_name (str): The name of the image.
|
||||
image_json (json): The dict of images in the system registry.
|
||||
Returns:
|
||||
str: The image ID.
|
||||
"""
|
||||
for image in image_json["images"]:
|
||||
if image_name in image["repoTags"]:
|
||||
return image["id"]
|
||||
return None
|
||||
|
||||
|
||||
def get_number_of_controllers() -> int:
|
||||
"""Get the number of controllers in the system
|
||||
|
||||
|
||||
Reference in New Issue
Block a user