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