From 33fb9611275b297dfe4f83980618ff4958e32751 Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Mon, 2 Sep 2024 13:50:09 +1200 Subject: [PATCH] Add block device rollback for lvm volumes and groups If mkfs fails then the rollback won't delete logical volumes or the volume group. This prevents unmounting the loop back, and subsequent image build runs will fail because the volume group still exists. This change adds lvremove and vgremove rollback actions. Change-Id: Ib93dfc43f5b3ef90fcec38538e828f135e514f8b --- diskimage_builder/block_device/level1/lvm.py | 25 ++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/diskimage_builder/block_device/level1/lvm.py b/diskimage_builder/block_device/level1/lvm.py index 1b6bfa297..16842c989 100644 --- a/diskimage_builder/block_device/level1/lvm.py +++ b/diskimage_builder/block_device/level1/lvm.py @@ -20,7 +20,6 @@ from diskimage_builder.block_device.plugin import NodeBase from diskimage_builder.block_device.plugin import PluginBase from diskimage_builder.block_device.utils import exec_sudo from diskimage_builder.block_device.utils import parse_abs_size_spec -from diskimage_builder.block_device.utils import remove_device PHYSICAL_EXTENT_BYTES = parse_abs_size_spec('4MiB') LVS_TYPES = ['thin', 'thin-pool'] @@ -70,6 +69,27 @@ logger = logging.getLogger(__name__) # call that is driven by the LVSNode object. +def lvremove(device_name): + logger.debug('Removing logical volume %s', device_name) + try: + exec_sudo(["lvchange", "--activate", "n", device_name]) + exec_sudo(["lvremove", "--yes", "/dev/%s" % device_name]) + except BlockDeviceSetupException as e: + # Do not raise an error - maybe other cleanup methods + # can at least do some more work. + logger.warning("Removing logical volume failed (%s)", e.returncode) + + +def vgremove(vg_name): + logger.debug('Removing volume group %s', vg_name) + try: + exec_sudo(["vgremove", "--yes", "--force", vg_name]) + except BlockDeviceSetupException as e: + # Do not raise an error - maybe other cleanup methods + # can at least do some more work. + logger.warning("Removing volume group failed (%s)", e.returncode) + + class PvsNode(NodeBase): def __init__(self, name, state, base, options): """Physical volume @@ -150,6 +170,7 @@ class VgsNode(NodeBase): logger.debug("Creating vg command [%s]", cmd) exec_sudo(cmd) + self.add_rollback(vgremove, self.name) # save state if 'vgs' not in self.state: self.state['vgs'] = {} @@ -232,7 +253,7 @@ class LvsNode(NodeBase): 'opts': self.options, 'device': '/dev/mapper/%s' % device_name } - self.add_rollback(remove_device, device_name) + self.add_rollback(lvremove, "%s/%s" % (self.base, self.name)) def _umount(self): exec_sudo(['lvchange', '-an',