Skip to content

Commit da9e170

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 257d939 commit da9e170

1 file changed

Lines changed: 48 additions & 21 deletions

File tree

drivers/VDI.py

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,20 @@ def update_slaves_on_cbt_disable(self, cbtlog):
580580
# Override in implementation as required.
581581
pass
582582

583+
def _list_vdi_snapshots(self):
584+
"""List vdi of all direct snapshots of a VDI"""
585+
snapshots = []
586+
vdi_record = self.session.xenapi.VDI.get_record(self.sr.srcmd.params['vdi_ref'])
587+
try:
588+
for opaque_ref in vdi_record.get("snapshots", []):
589+
snapshot_record = self.session.xenapi.VDI.get_record(opaque_ref)
590+
snapshot_uuid = self.session.xenapi.VDI.get_uuid(opaque_ref)
591+
snapshots.append(self.from_uuid(self.session , snapshot_uuid))
592+
return snapshots
593+
except Exception as error:
594+
util.SMlog(f"Error listing snapshots for VDI {snapshot_uuid}: {error}")
595+
return []
596+
583597
def configure_blocktracking(self, sr_uuid, vdi_uuid, enable):
584598
"""Function for configuring blocktracking"""
585599
import blktap2
@@ -620,31 +634,44 @@ def configure_blocktracking(self, sr_uuid, vdi_uuid, enable):
620634
self._delete_cbt_log()
621635
raise xs_errors.XenError('CBTActivateFailed',
622636
opterr=str(error))
637+
623638
else:
624-
from lock import Lock
625-
lock = Lock("cbtlog", str(vdi_uuid))
626-
lock.acquire()
627-
try:
628-
# Find parent of leaf metadata file, if any,
629-
# and nullify its successor
630-
logpath = self._get_cbt_logpath(self.uuid)
631-
parent = self._cbt_op(self.uuid,
632-
cbtutil.get_cbt_parent, logpath)
633-
self._delete_cbt_log()
634-
parent_path = self._get_cbt_logpath(parent)
635-
if self._cbt_log_exists(parent_path):
636-
self._cbt_op(parent, cbtutil.set_cbt_child,
637-
parent_path, uuid.UUID(int=0))
638-
if disk_state:
639-
self.update_slaves_on_cbt_disable(logpath)
640-
except Exception as error:
641-
raise xs_errors.XenError('CBTDeactivateFailed', str(error))
642-
finally:
643-
lock.release()
644-
lock.cleanup("cbtlog", str(vdi_uuid))
639+
self._disable_cbt(disk_state)
640+
# Disable cbt for each child snapshots
641+
for snapshot_vdi in self._list_vdi_snapshots():
642+
snapshot_vdi._disable_cbt()
643+
645644
finally:
646645
blktap2.VDI.tap_unpause(self.session, sr_uuid, vdi_uuid)
647646

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

0 commit comments

Comments
 (0)