Skip to content

Commit 1bf1559

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 f3d5fa7 commit 1bf1559

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
@@ -555,6 +555,20 @@ def update_slaves_on_cbt_disable(self, cbtlog):
555555
# Override in implementation as required.
556556
pass
557557

558+
def _list_vdi_snapshots(self):
559+
"""List vdi of all direct snapshots of a VDI"""
560+
snapshots = []
561+
vdi_record = self.session.xenapi.VDI.get_record(self.sr.srcmd.params['vdi_ref'])
562+
try:
563+
for opaque_ref in vdi_record.get("snapshots", []):
564+
snapshot_record = self.session.xenapi.VDI.get_record(opaque_ref)
565+
snapshot_uuid = self.session.xenapi.VDI.get_uuid(opaque_ref)
566+
snapshots.append(self.from_uuid(self.session , snapshot_uuid))
567+
return snapshots
568+
except Exception as error:
569+
util.SMlog(f"Error listing snapshots for VDI {snapshot_uuid}: {error}")
570+
return []
571+
558572
def configure_blocktracking(self, sr_uuid, vdi_uuid, enable):
559573
"""Function for configuring blocktracking"""
560574
import blktap2
@@ -598,31 +612,44 @@ def configure_blocktracking(self, sr_uuid, vdi_uuid, enable):
598612
self._delete_cbt_log()
599613
raise xs_errors.XenError('CBTActivateFailed',
600614
opterr=str(error))
615+
601616
else:
602-
from lock import Lock
603-
lock = Lock("cbtlog", str(vdi_uuid))
604-
lock.acquire()
605-
try:
606-
# Find parent of leaf metadata file, if any,
607-
# and nullify its successor
608-
logpath = self._get_cbt_logpath(self.uuid)
609-
parent = self._cbt_op(self.uuid,
610-
cbtutil.get_cbt_parent, logpath)
611-
self._delete_cbt_log()
612-
parent_path = self._get_cbt_logpath(parent)
613-
if self._cbt_log_exists(parent_path):
614-
self._cbt_op(parent, cbtutil.set_cbt_child,
615-
parent_path, uuid.UUID(int=0))
616-
if disk_state:
617-
self.update_slaves_on_cbt_disable(logpath)
618-
except Exception as error:
619-
raise xs_errors.XenError('CBTDeactivateFailed', str(error))
620-
finally:
621-
lock.release()
622-
lock.cleanup("cbtlog", str(vdi_uuid))
617+
self._disable_cbt(disk_state)
618+
# Disable cbt for each child snapshots
619+
for snapshot_vdi in self._list_vdi_snapshots():
620+
snapshot_vdi._disable_cbt()
621+
623622
finally:
624623
blktap2.VDI.tap_unpause(self.session, sr_uuid, vdi_uuid)
625624

625+
def _disable_cbt(self, disk_state=None):
626+
"""Disables CBT for the specified VDI and updates associated metadata."""
627+
from lock import Lock
628+
lock = Lock("cbtlog", str(self.uuid))
629+
lock.acquire()
630+
try:
631+
vdi_ref = self.session.xenapi.VDI.get_by_uuid(self.uuid)
632+
vdi_record = self.session.xenapi.VDI.get_record(vdi_ref)
633+
logpath = self._get_cbt_logpath(self.uuid)
634+
if self._cbt_log_exists(logpath):
635+
parent = self._cbt_op(self.uuid, cbtutil.get_cbt_parent, logpath)
636+
self._delete_cbt_log()
637+
# Find parent of leaf metadata file, if any,
638+
# and nullify its successor
639+
parent_path = self._get_cbt_logpath(parent)
640+
if self._cbt_log_exists(parent_path):
641+
self._cbt_op(parent, cbtutil.set_cbt_child, parent_path, uuid.UUID(int=0))
642+
if disk_state:
643+
self.update_slaves_on_cbt_disable(logpath)
644+
self.session.xenapi.VDI.set_cbt_enabled(vdi_ref, False)
645+
except Exception as error:
646+
util.SMlog(f"Error disabling CBT for VDI {self.uuid}: {error}")
647+
raise xs_errors.XenError('CBTDeactivateFailed', str(error))
648+
finally:
649+
lock.release()
650+
lock.cleanup("cbtlog", str(self.uuid))
651+
652+
626653
def data_destroy(self, sr_uuid, vdi_uuid):
627654
"""Delete the data associated with a CBT enabled snapshot
628655

0 commit comments

Comments
 (0)