Skip to content

Commit 832aef0

Browse files
committed
fix(cbt): implement recursive CBT deactivation
- Recursive CBT disabling on VDI all child snapshots - Delete CBT log files when present This resolves issues where CBT deactivation was incomplete when processing multi-level snapshot chains. Fixes: incomplete CBT deactivation on snapshot chains Signed-off-by: Goulven Riou <[email protected]>
1 parent 1cec251 commit 832aef0

File tree

1 file changed

+44
-19
lines changed

1 file changed

+44
-19
lines changed

drivers/VDI.py

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,17 @@ def in_sync_with_xenapi_record(self, x):
576576
return False
577577
return True
578578

579+
def _list_vdi_snapshots(self, vdi_uuid):
580+
"""List vdi_ref of all direct snapshots of a VDI"""
581+
try:
582+
vdi_ref = self.session.xenapi.VDI.get_by_uuid(vdi_uuid)
583+
record = self.session.xenapi.VDI.get_record(vdi_ref)
584+
return record.get("snapshots", [])
585+
586+
except Exception as error:
587+
util.SMlog(f"Error listing snapshots for VDI {vdi_uuid}: {error}")
588+
return []
589+
579590
def configure_blocktracking(self, sr_uuid, vdi_uuid, enable):
580591
"""Function for configuring blocktracking"""
581592
import blktap2
@@ -616,29 +627,43 @@ def configure_blocktracking(self, sr_uuid, vdi_uuid, enable):
616627
self._delete_cbt_log()
617628
raise xs_errors.XenError('CBTActivateFailed',
618629
opterr=str(error))
630+
619631
else:
620-
from lock import Lock
621-
lock = Lock("cbtlog", str(vdi_uuid))
622-
lock.acquire()
623-
try:
624-
# Find parent of leaf metadata file, if any,
625-
# and nullify its successor
626-
logpath = self._get_cbt_logpath(self.uuid)
627-
parent = self._cbt_op(self.uuid,
628-
cbtutil.get_cbt_parent, logpath)
629-
self._delete_cbt_log()
630-
parent_path = self._get_cbt_logpath(parent)
631-
if self._cbt_log_exists(parent_path):
632-
self._cbt_op(parent, cbtutil.set_cbt_child,
633-
parent_path, uuid.UUID(int=0))
634-
except Exception as error:
635-
raise xs_errors.XenError('CBTDeactivateFailed', str(error))
636-
finally:
637-
lock.release()
638-
lock.cleanup("cbtlog", str(vdi_uuid))
632+
self._disable_cbt(vdi_uuid)
633+
639634
finally:
640635
blktap2.VDI.tap_unpause(self.session, sr_uuid, vdi_uuid)
641636

637+
def _disable_cbt(self, vdi_uuid ):
638+
"""Disables CBT for the specified VDI and updates associated metadata."""
639+
from lock import Lock
640+
lock = Lock("cbtlog", str(vdi_uuid))
641+
lock.acquire()
642+
try:
643+
self.uuid = vdi_uuid
644+
vdi_ref = self.session.xenapi.VDI.get_by_uuid(self.uuid)
645+
vdi_record = self.session.xenapi.VDI.get_record(vdi_ref)
646+
logpath = self._get_cbt_logpath(self.uuid)
647+
if self._cbt_log_exists(logpath):
648+
parent = self._cbt_op(self.uuid, cbtutil.get_cbt_parent, logpath)
649+
self._delete_cbt_log()
650+
# Find parent of leaf metadata file, if any,
651+
# and nullify its successor
652+
parent_path = self._get_cbt_logpath(parent)
653+
if self._cbt_log_exists(parent_path):
654+
self._cbt_op(parent, cbtutil.set_cbt_child, parent_path, uuid.UUID(int=0))
655+
self.session.xenapi.VDI.set_cbt_enabled(vdi_ref, False)
656+
for snapshot_ref in self._list_vdi_snapshots(self.uuid):
657+
snapshot_uuid = self.session.xenapi.VDI.get_uuid(snapshot_ref)
658+
self._disable_cbt(snapshot_uuid)
659+
660+
except Exception as error:
661+
util.SMlog(f"Error disabling CBT for VDI {self.uuid}: {error}")
662+
raise xs_errors.XenError('CBTDeactivateFailed', str(error))
663+
finally:
664+
lock.release()
665+
lock.cleanup("cbtlog", str(vdi_uuid))
666+
642667
def data_destroy(self, sr_uuid, vdi_uuid):
643668
"""Delete the data associated with a CBT enabled snapshot
644669

0 commit comments

Comments
 (0)