From 2360ec2a79b0d3ce20378efd1c5df65fbaccabe2 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 22 Apr 2026 23:09:42 +0100 Subject: [PATCH] [cloud] Delete underlying snapshots when deleting Alibaba Cloud images The underlying snapshots are not automatically deleted along with the image, and there is no flag that can be set to cause them to be automatically deleted. Tag the underlying snapshots for deletion before deleting the image, delete the image, and then delete any such tagged snapshots (including any that may remain from a previous failed deletion attempt). Signed-off-by: Michael Brown --- contrib/cloud/ali-import | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/contrib/cloud/ali-import b/contrib/cloud/ali-import index 88c08cb7f..0794a5c59 100755 --- a/contrib/cloud/ali-import +++ b/contrib/cloud/ali-import @@ -82,6 +82,7 @@ OSS_FORBIDDEN_REGION_CODE = 'ForbidCreateNewBucket' OSS_BUCKET_NAME_LEN = 63 IPXE_STORAGE_PREFIX = 'ipxe-upload-temp-' +IPXE_SNAPSHOT_DELETE_TAG = 'ipxe-snapshot-delete' POLL_INTERVAL_SEC = 5 POLL_MAX_RETRIES = 100 @@ -389,6 +390,21 @@ def delete_image(clients, name): for image in rsp.body.images.image or (): logger.info("delete image %s %s (%s)" % (clients.region, image.image_name, image.image_id)) + # Tag associated snapshots for deletion + for disk in image.disk_device_mappings.disk_device_mapping or (): + snapshot_id = disk.snapshot_id + tag = ecs.models.TagResourcesRequestTag( + key=IPXE_SNAPSHOT_DELETE_TAG, + value=IPXE_SNAPSHOT_DELETE_TAG, + ) + req = ecs.models.TagResourcesRequest( + region_id=clients.region, + resource_type='snapshot', + resource_id=[snapshot_id], + tag=[tag], + ) + rsp = clients.ecs.tag_resources_with_options(req, RUNTIME_OPTS) + # Unpublish image if image.is_public: req = ecs.models.ModifyImageSharePermissionRequest( region_id=clients.region, @@ -398,11 +414,31 @@ def delete_image(clients, name): rsp = clients.ecs.modify_image_share_permission_with_options( req, RUNTIME_OPTS ) + # Delete image req = ecs.models.DeleteImageRequest( region_id=clients.region, image_id=image.image_id ) rsp = clients.ecs.delete_image_with_options(req, RUNTIME_OPTS) + # Delete any snapshots tagged for deletion + tag = ecs.models.ListTagResourcesRequestTag( + key=IPXE_SNAPSHOT_DELETE_TAG, + value=IPXE_SNAPSHOT_DELETE_TAG, + ) + req = ecs.models.ListTagResourcesRequest( + region_id=clients.region, + resource_type='snapshot', + tag=[tag], + ) + rsp = clients.ecs.list_tag_resources_with_options(req, RUNTIME_OPTS) + for snapshot in rsp.body.tag_resources.tag_resource or (): + logger.info("delete snapshot %s %s" % + (clients.region, snapshot.resource_id)) + req = ecs.models.DeleteSnapshotRequest( + snapshot_id=snapshot.resource_id, + force=True, + ) + rsp = clients.ecs.delete_snapshot_with_options(req, RUNTIME_OPTS) def wait_for_task(clients, task_id): """Wait for task to complete"""