Skip to content

Commit 2648b19

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 2648b19

File tree

1 file changed

+54
-19
lines changed

1 file changed

+54
-19
lines changed

drivers/VDI.py

Lines changed: 54 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, vdi_uuid):
580+
"""List UUIDs 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 [
585+
self.session.xenapi.VDI.get_uuid(ref)
586+
for ref in record.get("snapshots", [])
587+
if self.session.xenapi.VDI.get_uuid(ref)
588+
]
589+
except Exception as error:
590+
util.SMlog("Error listing snapshots for VDI %s : %s" % (vdi_ref, 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,50 @@ 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(vdi_uuid)
636+
639637
finally:
640638
blktap2.VDI.tap_unpause(self.session, sr_uuid, vdi_uuid)
641639

640+
def _disable_cbt(self, vdi_uuid, visited=None):
641+
# Prevent infite loop
642+
if visited is None:
643+
visited = set()
644+
if vdi_uuid in visited:
645+
return
646+
visited.add(vdi_uuid)
647+
648+
from lock import Lock
649+
lock = Lock("cbtlog", str(vdi_uuid))
650+
lock.acquire()
651+
try:
652+
self.uuid = vdi_uuid
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+
self.session.xenapi.VDI.set_cbt_enabled(vdi_ref, False)
665+
for snapshot_ref in self._list_vdi_snapshots(self.uuid):
666+
snap_ref = self.session.xenapi.VDI.get_by_uuid(snapshot_ref)
667+
snapshot_uuid = self.session.xenapi.VDI.get_uuid(snap_ref)
668+
self._disable_cbt(snapshot_uuid, visited)
669+
670+
except Exception as error:
671+
util.SMlog(f"Error disabling CBT for VDI {self.uuid}: {error}")
672+
raise xs_errors.XenError('CBTDeactivateFailed', str(error))
673+
finally:
674+
lock.release()
675+
lock.cleanup("cbtlog", str(vdi_uuid))
676+
642677
def data_destroy(self, sr_uuid, vdi_uuid):
643678
"""Delete the data associated with a CBT enabled snapshot
644679

0 commit comments

Comments
 (0)