1616# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1717#
1818# FileSR: local-file storage repository
19+ import contextlib
1920from contextlib import contextmanager
2021
2122from sm_typing import Dict , Optional , List , override , Tuple
2223
24+ import cbtutil
2325import SR
2426import VDI
2527import SRCommand
@@ -768,7 +770,10 @@ def _tap_pause(self, secondary=None):
768770 blktap2 .VDI .tap_unpause (self .session , self .sr .uuid , self .uuid , secondary )
769771
770772 @override
771- def _do_revert (self , dest : "FileVDI" , cbtlog : Optional [str ] = None ):
773+ def _do_revert (self ,
774+ dest : "FileVDI" , # type: ignore # self and dest are the same type
775+ cbtlog : Optional [str ] = None
776+ ):
772777 # Sanity checks
773778 if not self ._checkpath (self .path ):
774779 raise xs_errors .XenError (f"Could not find { self .path } " )
@@ -778,20 +783,29 @@ def _do_revert(self, dest: "FileVDI", cbtlog: Optional[str] = None):
778783
779784 self ._ensure_not_max_depth ()
780785
781- # Get first common parent
786+ cbt_consistency_state = False
787+ if cbtlog :
788+ cbt_consistency_state = blktap2 .VDI .tap_status (self .session , self .uuid )
789+ util .SMlog ("Saving log consistency state of %s for vdi: %s" %
790+ (cbt_consistency_state , self .uuid ))
791+
792+ util .SMlog (f"---------------------------------------------> { self .parent } " )
793+ # Get downward child
782794 if self .parent == dest .parent :
783795 downward_child = None
784796 else :
785797 children = [child for child in self .sr .get_children_of (self .parent ) if child != self .uuid ]
786798 if not children :
787799 downward_child = None
800+ elif len (children ) > 1 :
801+ raise xs_errors .SRException (f"Too many children for { self .parent } . Expected 1, found { len (children ) + 1 } " )
788802 else :
789803 downward_child = VDI .VDI .from_uuid (self .sr .session , children [0 ])
790804
791805 with self ._tap_pause (), dest ._tap_pause ():
792- self ._revert (dest , downward_child , cbtlog )
806+ self ._revert (dest , downward_child , cbtlog , cbt_consistency_state )
793807
794- def _revert (self , dest : "FileVDI" , downward_child : Optional ["FileVDI" ], cbtlog : Optional [str ]):
808+ def _revert (self , dest : "FileVDI" , downward_child : Optional ["FileVDI" ], cbtlog : Optional [str ], cbt_consistency_state : bool ):
795809 """This assumes that self and dest VDIs has been paused"""
796810 dest_tmp_uuid = util .gen_uuid () # Will be replaced by dest.uuid at the end
797811 dest_tmp_path = os .path .join (dest .sr .path , "%s%s" % (dest_tmp_uuid , VDI_TYPE_TO_EXTENSION [dest .vdi_type ]))
@@ -807,13 +821,6 @@ def update_vdi_from_file(vdi, path):
807821 if vdi .parent :
808822 vdi .sm_config ['vhd-parent' ] = vdi .parent
809823
810- # try:
811- util .fistpoint .activate_custom_fn (
812- "FileSR_fail_snap1" ,
813- self .__fist_enospace )
814- util .ioretry (lambda : self ._snap (dest_tmp_path , src_parent .path , False ))
815- self .cowutil .setHidden (dest_tmp_path , False )
816-
817824 if downward_child :
818825 # Create a new parent VDI based on src parent and attach the rest of the snapshoot tree to it
819826 src_parent_clone_uuid = util .gen_uuid ()
@@ -824,56 +831,118 @@ def update_vdi_from_file(vdi, path):
824831
825832 downward_child .sm_config = downward_child .session .xenapi .VDI .get_sm_config (downward_child .sr .srcmd .params ['vdi_ref' ])
826833
827- util .fistpoint .activate_custom_fn (
828- "FileSR_fail_snap2" ,
829- self .__fist_enospace )
830- util .ioretry (lambda : self ._snap (src_parent_clone_path , src_parent .path , False ))
831- self .cowutil .setHidden (src_parent_clone_path , False )
832-
834+ # Used both for snapshot and cleanup
833835 is_raw = self .VDI_TYPE == VdiType .RAW
834- self .cowutil .setParent (src_parent_clone_path , src_parent .path , is_raw )
835- self .cowutil .setParent (downward_child .path , src_parent_clone_path , is_raw )
836- self .cowutil .setParent (self .path , src_parent_clone_path , is_raw )
836+ downward_child_old_parent , _ = downward_child ._get_path_and_type (downward_child .parent )
837+ src_old_parent = src_parent .path
838+ if not downward_child_old_parent :
839+ raise xs_errors .SRException (f"Error getting parent path of { downward_child .uuid } " )
837840
838- # Introduce new readonly vdi to db
839- src_parent_clone = VDI .VDI (self .sr , src_parent_clone_uuid )
841+ try :
842+ util .fistpoint .activate_custom_fn (
843+ "FileSR_fail_snap2" ,
844+ self .__fist_enospace )
845+ util .ioretry (lambda : self ._snap (src_parent_clone_path , src_parent .path , False ))
846+ self .cowutil .setHidden (src_parent_clone_path , False )
840847
841- # FileVDI emulation for update_vdi_from_file
842- src_parent_clone .path = src_parent_clone_path
843- src_parent_clone .parent = src_parent .uuid
844- src_parent_clone .cowutil = self .cowutil
848+ self .cowutil .setParent (src_parent_clone_path , src_parent .path , is_raw )
849+ self .cowutil .setParent (downward_child .path , src_parent_clone_path , is_raw )
850+ self .cowutil .setParent (self .path , src_parent_clone_path , is_raw )
845851
846- src_parent_clone .label = "base copy"
847- src_parent_clone .read_only = True
848- src_parent_clone .location = src_parent_clone_uuid
849- src_parent_clone .sm_config = {}
850- # TODO: fix the raw snapshot case
851- src_parent_clone .sm_config ["image-format" ] = getImageStringFromVdiType (self .vdi_type )
852- if "key_hash" in downward_child .sm_config :
853- src_parent_clone .sm_config ['key_hash' ] = downward_child .sm_config ['key_hash' ]
854- update_vdi_from_file (src_parent_clone , src_parent_clone_uuid )
852+ # Introduce new readonly vdi to db
853+ src_parent_clone = FileVDI (self .sr , src_parent_clone_uuid )
855854
856- self .sm_config = self .session .xenapi .VDI .get_sm_config (self .sr .srcmd .params ['vdi_ref' ])
857- update_vdi_from_file (self , self .path )
855+ src_parent_clone .label = "base copy"
856+ src_parent_clone .read_only = True
857+ src_parent_clone .location = src_parent_clone_uuid
858+ src_parent_clone .sm_config = {}
859+ # TODO: fix the raw snapshot case
860+ src_parent_clone .sm_config ["image-format" ] = getImageStringFromVdiType (self .vdi_type )
861+ if "key_hash" in downward_child .sm_config :
862+ src_parent_clone .sm_config ['key_hash' ] = downward_child .sm_config ['key_hash' ]
863+ src_parent_clone .cbt_enabled = bool (cbtlog )
858864
859- update_vdi_from_file (downward_child , downward_child . path )
865+ update_vdi_from_file (src_parent_clone , src_parent_clone_uuid )
860866
861- src_parent_clone ._db_introduce ()
867+ self .sm_config = self .session .xenapi .VDI .get_sm_config (self .sr .srcmd .params ['vdi_ref' ])
868+ update_vdi_from_file (self , self .path )
862869
863- downward_child . _db_update ( )
870+ update_vdi_from_file ( downward_child , downward_child . path )
864871
865- self . _db_update ()
872+ src_parent_clone . _db_introduce ()
866873
867- self .cowutil .setHidden (src_parent_clone_path , True )
874+ if cbtlog :
875+ # Set downward_child's parent as src_parent_clone
876+ downward_child_cbt_path = downward_child ._get_cbt_logpath (downward_child .uuid )
877+ if util .pathexists (downward_child_cbt_path ):
878+ downward_child ._cbt_op (
879+ downward_child .uuid ,
880+ cbtutil .set_cbt_parent ,
881+ downward_child_cbt_path ,
882+ src_parent_clone .uuid ,
883+ )
884+ # Set self's parent as src_parent_clone
885+ self ._cbt_op (
886+ self .uuid ,
887+ cbtutil .set_cbt_parent ,
888+ self ._get_cbt_logpath (self .uuid ),
889+ src_parent_clone .uuid ,
890+ )
891+
892+ downward_child ._db_update ()
893+
894+ self ._db_update ()
895+
896+ self .cowutil .setHidden (src_parent_clone .path , True )
897+ except Exception as e :
898+ # Restore parents
899+ util .SMlog (f"Error during revert of { self .uuid } , rolling back and cleaning up" )
900+ self .cowutil .setParent (downward_child .path , downward_child_old_parent , is_raw )
901+ self .cowutil .setParent (self .path , src_old_parent , is_raw )
868902
869- util .ioretry (lambda : self ._rename (dest_tmp_path , dest .path ),
870- errlist = [errno .EIO , errno .EACCES ])
903+ update_vdi_from_file (downward_child , downward_child .path )
904+ update_vdi_from_file (self , self .path )
905+
906+ util .SMlog (f"Deleting { src_parent_clone_uuid } " )
907+ with contextlib .suppress (Exception ):
908+ src_parent_clone = FileVDI (self .sr , src_parent_clone_uuid )
909+ src_parent_clone .delete (src_parent_clone .sr , src_parent_clone .uuid )
910+ if util .ioretry (lambda : util .pathexists (src_parent_clone_path )):
911+ self ._unlink (src_parent_clone_path )
912+
913+ downward_child ._db_update ()
914+ self ._db_update ()
915+ raise e
916+
917+ try :
918+ util .fistpoint .activate_custom_fn (
919+ "FileSR_fail_snap1" ,
920+ self .__fist_enospace )
921+ util .ioretry (lambda : self ._snap (dest_tmp_path , src_parent .path , False ))
922+ self .cowutil .setHidden (dest_tmp_path , False )
923+ except Exception as e :
924+ if util .ioretry (lambda : util .pathexists (dest_tmp_path )):
925+ self ._unlink (dest_tmp_path )
926+ raise e
871927
872928 dest .sm_config = dest .session .xenapi .VDI .get_sm_config (dest .sr .srcmd .params ['vdi_ref' ])
929+ if cbtlog :
930+ dest .cbt_enabled = True
931+ try :
932+ # copy self -> dest
933+ # set consistency
934+ # set dest as child
935+ dest ._cbt_snapshot (self .uuid , cbt_consistency_state ) # Broken part
936+ except :
937+ # CBT operation failed.
938+ util .end_log_entry (dest .sr .path , dest .path , ["error" ])
939+ raise
940+
941+ util .ioretry (lambda : self ._rename (dest_tmp_path , dest .path ),
942+ errlist = [errno .EIO , errno .EACCES ])
873943 update_vdi_from_file (dest , dest .path )
874944
875945 dest ._db_update ()
876- # except:
877946 #cleanup
878947
879948 @override
0 commit comments