@@ -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