1616# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1717#
1818# FileSR: local-file storage repository
19+ from contextlib import contextmanager
1920
20- from sm_typing import Dict , Optional , List , override
21+ from sm_typing import Dict , Optional , List , override , Tuple , Union
2122
2223import SR
2324import VDI
4142from constants import CBTLOG_TAG
4243
4344geneology : Dict [str , List [str ]] = {}
44- CAPABILITIES = ["SR_PROBE" , "SR_UPDATE" , \
45- "VDI_CREATE" , "VDI_DELETE" , "VDI_ATTACH" , "VDI_DETACH" , \
45+ CAPABILITIES = ["SR_PROBE" , "SR_UPDATE" ,
46+ "VDI_CREATE" , "VDI_DELETE" , "VDI_ATTACH" , "VDI_DETACH" ,
4647 "VDI_CLONE" , "VDI_SNAPSHOT" , "VDI_RESIZE" , "VDI_MIRROR" ,
4748 "VDI_GENERATE_CONFIG" , "ATOMIC_PAUSE" , "VDI_CONFIG_CBT" ,
48- "VDI_ACTIVATE" , "VDI_DEACTIVATE" , "THIN_PROVISIONING" ]
49+ "VDI_ACTIVATE" , "VDI_DEACTIVATE" , "THIN_PROVISIONING" ,
50+ "VDI_REVERT" ]
4951
5052CONFIGURATION = [
5153 ['location' , 'local directory path (required)' ],
6870OPS_EXCLUSIVE = [
6971 "sr_create" , "sr_delete" , "sr_probe" , "sr_attach" , "sr_detach" ,
7072 "sr_scan" , "vdi_init" , "vdi_create" , "vdi_delete" , "vdi_attach" ,
71- "vdi_detach" , "vdi_resize_online" , "vdi_snapshot" , "vdi_clone" ]
73+ "vdi_detach" , "vdi_resize_online" , "vdi_snapshot" , "vdi_clone" ,
74+ "vdi_revert" ]
7275
7376DRIVER_CONFIG = {"ATTACH_FROM_CONFIG_WITH_TAPDISK" : True }
7477
@@ -447,7 +450,7 @@ class FileVDI(VDI.VDI):
447450 PARAM_QCOW2 : VdiType .QCOW2
448451 }
449452
450- def _find_path_with_retries (self , vdi_uuid , maxretry = 5 , period = 2.0 ):
453+ def _get_path_and_type (self , vdi_uuid , maxretry = 5 , period = 2.0 ) -> Tuple [ Optional [ str ], Optional [ str ]] :
451454 raw_path = os .path .join (self .sr .path , "%s.%s" % \
452455 (vdi_uuid , self .PARAM_RAW ))
453456 vhd_path = os .path .join (self .sr .path , "%s.%s" % \
@@ -456,39 +459,43 @@ def _find_path_with_retries(self, vdi_uuid, maxretry=5, period=2.0):
456459 (vdi_uuid , self .PARAM_QCOW2 ))
457460 cbt_path = os .path .join (self .sr .path , "%s.%s" %
458461 (vdi_uuid , CBTLOG_TAG ))
459- found = False
460462 tries = 0
461- while tries < maxretry and not found :
463+ while tries < maxretry :
462464 tries += 1
463465 if util .ioretry (lambda : util .pathexists (vhd_path )):
464- self .vdi_type = VdiType .VHD
465- self .path = vhd_path
466- found = True
467- elif util .ioretry (lambda : util .pathexists (qcow2_path )):
468- self .vdi_type = VdiType .QCOW2
469- self .path = qcow2_path
470- found = True
471- elif util .ioretry (lambda : util .pathexists (raw_path )):
472- self .vdi_type = VdiType .RAW
473- self .path = raw_path
474- self .hidden = False
475- found = True
476- elif util .ioretry (lambda : util .pathexists (cbt_path )):
477- self .vdi_type = VdiType .CBTLOG
478- self .path = cbt_path
479- self .hidden = False
480- found = True
481-
482- if found :
483- try :
484- self .cowutil = getCowUtil (self .vdi_type )
485- except :
486- pass
487- else :
488- util .SMlog ("VDI %s not found, retry %s of %s" % (vdi_uuid , tries , maxretry ))
489- time .sleep (period )
466+ return vhd_path , VdiType .VHD
467+
468+ if util .ioretry (lambda : util .pathexists (qcow2_path )):
469+ return qcow2_path , VdiType .QCOW2
470+
471+ if util .ioretry (lambda : util .pathexists (raw_path )):
472+ return raw_path , VdiType .RAW
473+
474+ if util .ioretry (lambda : util .pathexists (cbt_path )):
475+ return cbt_path , VdiType .CBTLOG
476+
477+ util .SMlog ("VDI %s not found, retry %s of %s" % (vdi_uuid , tries , maxretry ))
478+ time .sleep (period )
479+
480+ return None , None
490481
491- return found
482+ def _find_path_with_retries (self , vdi_uuid , maxretry = 5 , period = 2.0 ) -> bool :
483+ path , vdi_type = self ._get_path_and_type (vdi_uuid , maxretry , period )
484+ if not path or not vdi_type :
485+ return False
486+
487+ self .path = path
488+ self .vdi_type = vdi_type
489+
490+ if vdi_type in [VdiType .RAW , VdiType .CBTLOG ]:
491+ self .hidden = False
492+
493+ try :
494+ self .cowutil = getCowUtil (self .vdi_type )
495+ except :
496+ pass
497+
498+ return True
492499
493500 @override
494501 def load (self , vdi_uuid ) -> None :
@@ -739,6 +746,93 @@ def resize(self, sr_uuid, vdi_uuid, size) -> str:
739746 def clone (self , sr_uuid , vdi_uuid ) -> str :
740747 return self ._do_snapshot (sr_uuid , vdi_uuid , VDI .SNAPSHOT_DOUBLE )
741748
749+ @contextmanager
750+ def _tap_pause (self , secondary = None ):
751+ if not blktap2 .VDI .tap_pause (self .session , self .sr .uuid , self .uuid ):
752+ raise util .SMException (f"Could not pause disk { self .uuid } on sr { self .sr .uuid } " )
753+ try :
754+ yield
755+ finally :
756+ blktap2 .VDI .tap_unpause (self .session , self .sr .uuid , self .uuid , secondary )
757+
758+
759+ @override
760+ def revert (self , sr_uuid , src_uuid , dest_uuid ):
761+ util .SMlog ("---------------------------------------------------------------->" )
762+ util .SMlog (f"in: { src_uuid } - { self .uuid } " )
763+
764+ if self .label == "base copy" :
765+ raise xs_errors .XenError (f"{ self .uuid } is a base copy." )
766+
767+ dest = VDI .VDI .from_uuid (self .sr .session , dest_uuid )
768+ util .SMlog (f"out: { dest_uuid } - { dest .uuid } " )
769+
770+ if self .vdi_type != dest .vdi_type :
771+ raise xs_errors .XenError (f"{ self .uuid } and { dest .uuid } has incompatible types { self .vdi_type } != { dest .vdi_type } " )
772+
773+
774+ if not self ._checkpath (self .path ):
775+ raise xs_errors .XenError (f"Could not find { self .path } " )
776+
777+ if not dest ._checkpath (dest .path ):
778+ raise xs_errors .XenError (f"Could not find { dest .path } " )
779+
780+ if self .parent != dest .parent :
781+ raise xs_errors .XenError ("Not implemented yet" )
782+
783+ self ._ensure_not_max_depth ()
784+
785+ dest_tmp_uuid = util .gen_uuid () # Will be replaced by dest.uuid at the end
786+ dest_tmp_path = os .path .join (dest .sr .path , "%s%s" % (dest_tmp_uuid , VDI_TYPE_TO_EXTENSION [dest .vdi_type ]))
787+
788+ # snapshot = self._do_snapshot(sr_uuid, src_uuid, VDI.SNAPSHOT_SINGLE)
789+ # util.SMlog(snapshot)
790+ src_parent_path , _ = self ._get_path_and_type (self .parent )
791+ if not src_parent_path :
792+ raise xs_errors .XenError (f"Could not find parent of { self .uuid } " )
793+
794+
795+ with self ._tap_pause (), dest ._tap_pause ():
796+ # try:
797+ util .fistpoint .activate_custom_fn (
798+ "FileSR_fail_snap1" ,
799+ self .__fist_enospace )
800+ util .ioretry (lambda : self ._snap (dest_tmp_path , src_parent_path , False ))
801+ self .cowutil .setHidden (dest_tmp_path , True )
802+
803+ if self .parent != dest .parent :
804+ pass # Do more operation
805+
806+ image_info = VdiType .isCowImage (self .vdi_type )
807+ util .SMlog (f"J'ai écrittttttttttttt iciciiiiiii { dest_tmp_path } " )
808+ self ._rename (dest_tmp_path , dest .path )
809+ util .SMlog (f"J'ai renoméééééé iciciiiiiii { dest .path } " )
810+
811+ image_info = dest .cowutil .getInfo (dest .path , FileVDI .extractUuid )
812+ dest .utilisation = image_info .sizePhys
813+ dest .size = image_info .sizeVirt
814+ dest .hidden = False
815+ dest .parent = image_info .parentUuid
816+
817+ dest .cowutil .setHidden (dest .path , False )
818+ dest ._db_update ()
819+
820+ return dest .get_params ()
821+
822+
823+ # except util.CommandException as inst:
824+ # # TODO: cleanup
825+ # # XXX: it might be too late if the base disk has been marked as deleted!
826+ # # self._clonecleanup(src, dst, newsrc)
827+ # # util.end_log_entry(self.sr.path, self.path, ["error"])
828+ # # raise xs_errors.XenError('VDIClone',
829+ # # opterr='VDI clone failed error %d' % inst.code)
830+ # pass
831+
832+ util .SMlog ("<---------------------------------------------------------------" )
833+ raise xs_errors .XenError ('Heloiastrnie' )
834+
835+
742836 @override
743837 def compose (self , sr_uuid , vdi1 , vdi2 ) -> None :
744838 if not VdiType .isCowImage (self .vdi_type ):
@@ -812,6 +906,14 @@ def _create_new_parent(self, src, newsrc):
812906 def __fist_enospace (self ):
813907 raise util .CommandException (28 , "cowutil snapshot" , reason = "No space" )
814908
909+ def _ensure_not_max_depth (self ):
910+ depth = self .cowutil .getDepth (self .path )
911+ if depth == - 1 :
912+ raise xs_errors .XenError ('VDIUnavailable' , \
913+ opterr = 'failed to get image depth' )
914+ elif depth >= self .cowutil .getMaxChainLength ():
915+ raise xs_errors .XenError ('SnapshotChainTooLong' )
916+
815917 def _snapshot (self , snap_type , cbtlog = None , cbt_consistency = None , is_mirror_destination = False ):
816918 util .SMlog ("FileVDI._snapshot for %s (type %s)" % (self .uuid , snap_type ))
817919
@@ -831,12 +933,7 @@ def _snapshot(self, snap_type, cbtlog=None, cbt_consistency=None, is_mirror_dest
831933 if self .hidden :
832934 raise xs_errors .XenError ('VDIClone' , opterr = 'hidden VDI' )
833935
834- depth = self .cowutil .getDepth (self .path )
835- if depth == - 1 :
836- raise xs_errors .XenError ('VDIUnavailable' , \
837- opterr = 'failed to get image depth' )
838- elif depth >= self .cowutil .getMaxChainLength ():
839- raise xs_errors .XenError ('SnapshotChainTooLong' )
936+ self ._ensure_not_max_depth ()
840937
841938 newuuid = util .gen_uuid ()
842939 src = self .path
0 commit comments