Skip to content

Commit 56d3e2b

Browse files
committed
tools clean: continue on errors and report the number of items that failed to be removed
Signed-off-by: Gaëtan Lehmann <gaetan.lehmann@vates.tech>
1 parent 4670b33 commit 56d3e2b

2 files changed

Lines changed: 29 additions & 11 deletions

File tree

lib/tools/cli.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ def _command_update(args: argparse.Namespace) -> None:
2424
update_pools(inventory, reboot=args.reboot, parallel=args.parallel)
2525

2626

27-
def _command_clean(args: argparse.Namespace) -> None:
27+
def _command_clean(args: argparse.Namespace) -> int:
2828
if args.inventory:
2929
inventory = load_inventory(args.inventory)
3030
else:
3131
inventory = into_inventory(args.hosts, [], args.hosting_pool)
3232

33-
clean_pools(inventory, dry_run=args.dry_run)
33+
return clean_pools(inventory, dry_run=args.dry_run)
3434

3535

3636
def _command_exec(args: argparse.Namespace) -> int:

lib/tools/tasks/clean.py

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
from .. import logger
1818

19-
def clean_pools(inventory: Inventory, dry_run: bool = False) -> None:
19+
def clean_pools(inventory: Inventory, dry_run: bool = False) -> int:
2020
"""Remove all VMs and all orphan VDIs on local storage from pool(s).
2121
2222
.. note::
@@ -31,6 +31,8 @@ def clean_pools(inventory: Inventory, dry_run: bool = False) -> None:
3131
Each host (key) holds its own config data (values, eg: `enablerepos`).
3232
:param bool dry_run:
3333
When True, only log what would be removed without actually deleting.
34+
:return:
35+
The number of VMs/VDIs/snapshots that failed to be removed.
3436
"""
3537
inventory_hosts = inventory["hosts"]
3638
pools: list[Pool] = []
@@ -42,18 +44,25 @@ def clean_pools(inventory: Inventory, dry_run: bool = False) -> None:
4244

4345
with ThreadPoolExecutor() as executor:
4446
futures = {executor.submit(clean_pool, p, dry_run): p for p in pools}
47+
failures = 0
4548
for future in futures:
4649
pool = futures[future]
4750
try:
48-
future.result()
51+
failures += future.result()
4952
except Exception as exc:
50-
logger.error(f"Cleaning pool has failed! The master {pool.master} cannot be cleaned.")
51-
raise exc
53+
logger.error(f"Cleaning pool has failed! The master {pool.master} cannot be cleaned: {exc}")
54+
failures += 1
55+
return failures
5256

53-
def clean_pool(pool: Pool, dry_run: bool) -> None:
54-
"""Remove all VMs and all orphan VDIs on local SRs from a single pool."""
57+
def clean_pool(pool: Pool, dry_run: bool) -> int:
58+
"""Remove all VMs and all orphan VDIs on local SRs from a single pool.
59+
60+
:return:
61+
The number of VMs plus number VDIs that failed to be removed from pool
62+
"""
5563
master = pool.master
5664
log_prefix = 'Would remove' if dry_run else 'Removing'
65+
failures = 0
5766

5867
vm_uuids = safe_split(master.xe(
5968
'vm-list',
@@ -68,22 +77,31 @@ def clean_pool(pool: Pool, dry_run: bool) -> None:
6877
vm = VM(vm_uuid, master)
6978
logger.info(f"[{master}] {log_prefix} VM {vm.uuid} ({vm.name()})")
7079
if not dry_run:
71-
vm.destroy(verify=True)
80+
try:
81+
vm.destroy(verify=True)
82+
except Exception as exc:
83+
logger.error(f"[{master}] Failed to remove VM {vm.uuid} ({vm.name()}): {exc}")
84+
failures += 1
7285

7386
sr_uuids = local_sr_uuids(pool)
7487
for sr_uuid in sr_uuids:
7588
for vdi_uuid in SR(sr_uuid, pool).vdi_uuids(managed=True):
7689
vdi = VDI(vdi_uuid, sr=SR(sr_uuid, pool))
7790
logger.info(f"[{master}] {log_prefix} orphan VDI {vdi.uuid} from local SR {sr_uuid}")
7891
if not dry_run:
79-
vdi.destroy()
92+
try:
93+
vdi.destroy()
94+
except Exception as exc:
95+
logger.error(f"[{master}] Failed to destroy VDI {vdi.uuid}: {exc}")
96+
failures += 1
8097

81-
if not dry_run:
98+
if not dry_run and failures == 0:
8299
for sr_uuid in sr_uuids:
83100
wait_for_not(
84101
lambda: len(SR(sr_uuid, pool).vdi_uuids(managed=True)) > 0,
85102
f"Wait for local SR {sr_uuid} to be empty",
86103
)
104+
return failures
87105

88106
def local_sr_uuids(pool: Pool) -> list[str]:
89107
"""Return the UUIDs of the pool's local (non-shared, user) SRs."""

0 commit comments

Comments
 (0)