Skip to content

Commit c9dcd5f

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 <goulven.riou@vates.tech>
1 parent 1cec251 commit c9dcd5f

File tree

1 file changed

+45
-19
lines changed

1 file changed

+45
-19
lines changed

drivers/VDI.py

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

579+
def _list_vdi_snapshots(self):
580+
"""List vdi of all direct snapshots of a VDI"""
581+
snapshots = []
582+
vdi_record = self.session.xenapi.VDI.get_record(self.sr.srcmd.params['vdi_ref'])
583+
try:
584+
for opaque_ref in vdi_record.get("snapshots", []):
585+
snapshot_record = self.session.xenapi.VDI.get_record(opaque_ref)
586+
snapshot_uuid = self.session.xenapi.VDI.get_uuid(opaque_ref)
587+
snapshots.append(self.from_uuid(self.session , snapshot_uuid))
588+
return snapshots
589+
except Exception as error:
590+
util.SMlog(f"Error listing snapshots for VDI {snapshot_uuid}: {error}")
591+
return []
592+
579593
def configure_blocktracking(self, sr_uuid, vdi_uuid, enable):
580594
"""Function for configuring blocktracking"""
581595
import blktap2
@@ -616,29 +630,41 @@ def configure_blocktracking(self, sr_uuid, vdi_uuid, enable):
616630
self._delete_cbt_log()
617631
raise xs_errors.XenError('CBTActivateFailed',
618632
opterr=str(error))
633+
619634
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))
635+
self._disable_cbt()
636+
# Disable cbt for each child snapshots
637+
for snapshot_vdi in self._list_vdi_snapshots():
638+
snapshot_vdi._disable_cbt()
639+
639640
finally:
640641
blktap2.VDI.tap_unpause(self.session, sr_uuid, vdi_uuid)
641642

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

0 commit comments

Comments
 (0)