@@ -43,7 +43,7 @@ def setUp(self):
4343 def tearDown (self ):
4444 self .remove_stubs ()
4545
46- def create_LVHDSR (self , master = False , command = 'foo' , sr_uuid = None ):
46+ def create_LVHDSR (self , master = False , command = 'foo' , sr_uuid = None , extra_params = {} ):
4747 srcmd = mock .Mock ()
4848 srcmd .dconf = {'device' : '/dev/bar' }
4949 if master :
@@ -52,6 +52,7 @@ def create_LVHDSR(self, master=False, command='foo', sr_uuid=None):
5252 'command' : command ,
5353 'session_ref' : 'some session ref' ,
5454 'sr_ref' : 'test_sr_ref' }
55+ srcmd .params .update (extra_params )
5556 if sr_uuid is None :
5657 sr_uuid = str (uuid .uuid4 ())
5758 return LVHDSR .LVHDSR (srcmd , sr_uuid )
@@ -177,8 +178,6 @@ def get_vdi_by_uuid(vdi_uuid):
177178 lambda x : get_vdi_data ('name_description' , x ))
178179 mock_session .xenapi .VDI .get_is_a_snapshot .side_effect = (
179180 lambda x : get_vdi_data ('is_a_snapshot' , x ))
180- mock_session .xenapi .VDI .get_snapshot_of .side_effect = (
181- lambda x : get_vdi_data ('snapshot_of' , x ))
182181 mock_session .xenapi .VDI .get_snapshot_time .side_effect = (
183182 lambda x : get_vdi_data ('snapshot_time' , x ))
184183 mock_session .xenapi .VDI .get_type .side_effect = (
@@ -304,6 +303,205 @@ def convert_vdi_to_meta(self, vdi_data):
304303 }
305304 return metadata
306305
306+ @mock .patch ('sm.drivers.LVHDSR.cleanup' , autospec = True )
307+ @mock .patch ('sm.drivers.LVHDSR.IPCFlag' , autospec = True )
308+ @mock .patch ('sm.drivers.LVHDSR.Lock' , autospec = True )
309+ @mock .patch ('sm.drivers.LVHDSR.lvhdutil.getLVInfo' , autospec = True )
310+ @mock .patch ('sm.drivers.LVHDSR.lvhdutil.getVDIInfo' , autospec = True )
311+ @mock .patch ('sm.drivers.LVHDSR.SR.XenAPI' )
312+ @testlib .with_context
313+ def test_snapshotof_success (self ,
314+ context ,
315+ mock_xenapi ,
316+ mock_getVDIInfo ,
317+ mock_getLVInfo ,
318+ mock_lock ,
319+ mock_ipc ,
320+ mock_cleanup ):
321+ sr_uuid = str (uuid .uuid4 ())
322+ self .stubout ('sm.drivers.LVHDSR.lvutil._checkVG' , autospec = True )
323+ mock_lvm_cache = self .stubout ('sm.drivers.LVHDSR.lvmcache.LVMCache' )
324+ mock_get_vg_stats = self .stubout ('sm.drivers.LVHDSR.lvutil._getVGstats' , autospec = True )
325+ mock_scsi_get_size = self .stubout ('sm.drivers.LVHDSR.scsiutil.getsize' , autospec = True )
326+ mock_vhdutil_getAllVHDs = self .stubout ('sm.drivers.LVHDSR.vhdutil.getAllVHDs' , autospec = True )
327+ mock_sr_util_pathexists = self .stubout ('sm.drivers.LVHDSR.util.pathexists' , autospec = True )
328+ mock_sr_util_gen_uuid = self .stubout ('sm.drivers.LVHDSR.util.gen_uuid' , autospec = True )
329+ mock_cleanup .SR .TMP_RENAME_PREFIX = cleanup .SR .TMP_RENAME_PREFIX
330+
331+ device_size = 100 * 1024 * 1024
332+ device_free = 10 * 1024 * 1024
333+ mock_get_vg_stats .return_value = {
334+ 'physical_size' : device_size ,
335+ 'physical_utilisation' : device_free ,
336+ 'freespace' : device_size - device_free }
337+ mock_scsi_get_size .return_value = device_size
338+ mock_lvm_cache .return_value .checkLV .return_value = False
339+ mock_lvm_cache .return_value .getSize .return_value = 10240
340+
341+ mock_session = mock_xenapi .xapi_local .return_value
342+ mock_session .xenapi .SR .get_sm_config .return_value = {
343+ 'allocation' : 'thick' ,
344+ 'use_vhd' : 'true'
345+ }
346+ vdi_data = {
347+ 'vdi1_ref' : {
348+ 'uuid' : str (uuid .uuid4 ()),
349+ 'name_label' : "VDI1" ,
350+ 'name_description' : "First VDI" ,
351+ 'is_a_snapshot' : False ,
352+ 'snapshot_of' : None ,
353+ 'snapshot_time' : None ,
354+ 'type' : 'User' ,
355+ 'metadata-of-pool' : None ,
356+ 'sm-config' : {
357+ 'vdi_type' : 'vhd'
358+ }
359+ }
360+ }
361+ metadata = {}
362+
363+ def get_vdis (sr_ref ):
364+ return list (vdi_data .keys ())
365+
366+ def get_vdi_data (vdi_key , vdi_ref ):
367+ return vdi_data [vdi_ref ][vdi_key ]
368+
369+ def get_vdi_by_uuid (vdi_uuid ):
370+ return [v for v in vdi_data if vdi_data [v ]['uuid' ] == vdi_uuid ][0 ]
371+
372+ def db_introduce (uuid , label , description , sr_ref , ty , shareable , read_only , other_config , location , xenstore_data , sm_config , managed , size , utilisation , metadata_of_pool , is_a_snapshot , snapshot_time , snapshot_of , cbt_enabled ):
373+ vdi_data .update ({
374+ 'vdi3_ref' : {
375+ 'uuid' : uuid ,
376+ 'name_label' : label ,
377+ 'name_description' : description ,
378+ 'is_a_snapshot' : is_a_snapshot ,
379+ 'snapshot_of' : snapshot_of ,
380+ 'snapshot_time' : snapshot_time ,
381+ 'type' : ty ,
382+ 'metadata-of-pool' : metadata_of_pool ,
383+ 'sm-config' : {
384+ 'vdi_type' : 'vhd'
385+ }
386+ }})
387+ return 'vdi3_ref'
388+
389+ mock_session .xenapi .VDI .get_uuid .side_effect = (
390+ lambda x : get_vdi_data ('uuid' , x ))
391+ mock_session .xenapi .VDI .get_name_label .side_effect = (
392+ lambda x : get_vdi_data ('name_label' , x ))
393+ mock_session .xenapi .VDI .get_name_description .side_effect = (
394+ lambda x : get_vdi_data ('name_description' , x ))
395+ mock_session .xenapi .VDI .get_is_a_snapshot .side_effect = (
396+ lambda x : get_vdi_data ('is_a_snapshot' , x ))
397+ mock_session .xenapi .VDI .get_snapshot_of .side_effect = (
398+ lambda x : get_vdi_data ('snapshot_of' , x ))
399+ mock_session .xenapi .VDI .get_snapshot_time .side_effect = (
400+ lambda x : get_vdi_data ('snapshot_time' , x ))
401+ mock_session .xenapi .VDI .get_type .side_effect = (
402+ lambda x : get_vdi_data ('type' , x ))
403+ mock_session .xenapi .VDI .get_metadata_of_pool .side_effect = (
404+ lambda x : get_vdi_data ('metadata-of-pool' , x ))
405+ mock_session .xenapi .VDI .get_sm_config .side_effect = (
406+ lambda x : get_vdi_data ('sm-config' , x ))
407+ mock_session .xenapi .SR .get_VDIs .side_effect = get_vdis
408+ mock_session .xenapi .VDI .get_by_uuid .side_effect = get_vdi_by_uuid
409+ mock_session .xenapi .VDI .db_introduce .side_effect = db_introduce
410+
411+ sr = self .create_LVHDSR (master = True , command = 'sr_attach' ,
412+ sr_uuid = sr_uuid ,
413+ extra_params = {'driver_params' : {'type' : 'double' }, 'vdi_ref' : 'vdi1_ref' })
414+ os .makedirs (sr .path )
415+
416+ # Act (1)
417+ # This introduces the metadata volume
418+ sr .attach (sr .uuid )
419+
420+ # Create and check snapshot in metadata
421+ vdis_info = {}
422+ def addVdi (vdi_info ):
423+ uuid = vdi_info ['uuid' ]
424+ metadata [uuid ] = {
425+ 'uuid' : uuid ,
426+ 'is_a_snapshot' : vdi_info ['is_a_snapshot' ],
427+ 'snapshot_of' : vdi_info ['snapshot_of' ],
428+ 'vdi_type' : vdi_info ['vdi_type' ],
429+ 'name_label' : vdi_info ['name_label' ],
430+ 'name_description' : vdi_info ['name_description' ],
431+ 'type' : vdi_info ['type' ],
432+ 'read_only' : False ,
433+ 'managed' : True
434+ }
435+ vdi_data ['vdi3_ref' ]['snapshot_of' ] = 'vdi3_ref'
436+ vdi_data ['vdi3_ref' ]['is_a_snapshot' ] = vdi_info ['is_a_snapshot' ]
437+ vdis_info .update ({uuid : lvhdutil .VDIInfo (uuid )})
438+
439+ def write_metadata (sr_info , vdi_info ):
440+ for item in vdi_info .items ():
441+ metadata [item [0 ]] = {
442+ 'uuid' : item [1 ]['uuid' ],
443+ 'is_a_snapshot' : item [1 ]['is_a_snapshot' ],
444+ 'snapshot_of' : item [1 ]['snapshot_of' ],
445+ 'vdi_type' : item [1 ]['vdi_type' ],
446+ 'name_label' : item [1 ]['name_label' ],
447+ 'name_description' : item [1 ]['name_description' ],
448+ 'type' : item [1 ]['type' ],
449+ 'read_only' : False ,
450+ 'managed' : True ,
451+ }
452+ return metadata
453+
454+ mock_metadata = self .stubout ('sm.drivers.LVHDSR.LVMMetadataHandler' )
455+ mock_metadata .return_value .addVdi .side_effect = addVdi
456+ mock_metadata .return_value .writeMetadata .side_effect = write_metadata
457+
458+ self .stubout ('sm.journaler.Journaler.create' )
459+ self .stubout ('sm.journaler.Journaler.remove' )
460+ self .stubout ('sm.drivers.LVHDSR.RefCounter.set' )
461+ self .stubout ('sm.drivers.LVHDSR.RefCounter.put' )
462+
463+ vdi_uuid = get_vdi_data ('uuid' , 'vdi1_ref' )
464+
465+ for vdi_meta in vdi_data .values ():
466+ vdis_info .update ({vdi_meta ['uuid' ]: lvhdutil .VDIInfo (vdi_meta ['uuid' ])})
467+ mock_getVDIInfo .return_value = vdis_info
468+
469+ mock_lv = lvutil .LVInfo ('test-lv' )
470+ mock_lv .size = 10240
471+ mock_lv .active = True
472+ mock_lv .hidden = False
473+ mock_lv .vdiType = vhdutil .VDI_TYPE_VHD
474+
475+ mock_getLVInfo .return_value = {vdi_uuid : mock_lv }
476+
477+ vhdInfo = vhdutil .VHDInfo (vdi_uuid )
478+ vhdInfo .hidden = False
479+
480+ mock_vhdutil = self .stubout ('sm.drivers.LVHDSR.vhdutil' , autospec = True )
481+ mock_vhdutil .VDI_TYPE_VHD = vhdutil .VDI_TYPE_VHD
482+ mock_vhdutil .VDI_TYPE_RAW = vhdutil .VDI_TYPE_RAW
483+ mock_vhdutil .MAX_CHAIN_SIZE = vhdutil .MAX_CHAIN_SIZE
484+ mock_vhdutil .getVHDInfo .return_value = vhdInfo
485+
486+ mock_vhdutil_getAllVHDs .return_value = {vhdInfo .uuid : vhdInfo }
487+
488+ vdi = sr .vdi (vdi_uuid )
489+ vdi .vdi_type = vhdutil .VDI_TYPE_VHD
490+ mock_sr_util_pathexists .return_value = True
491+ def gen_uuid ():
492+ return str (uuid .uuid4 ())
493+ mock_sr_util_gen_uuid .side_effect = gen_uuid
494+ mock_vhdutil .getDepth .return_value = 1
495+
496+ snap = vdi .snapshot (sr .uuid , vdi_uuid )
497+ snapshot_of = metadata [get_vdi_data ('uuid' , 'vdi3_ref' )]['snapshot_of' ]
498+ self .assertEqual (snapshot_of .startswith ('OpaqueRef:' ), False )
499+
500+ # Update SR metadata and recheck snapshot field
501+ metadata = {}
502+ sr .updateSRMetadata ('thick' )
503+ snapshot_of = metadata [get_vdi_data ('uuid' , 'vdi3_ref' )]['snapshot_of' ]
504+ self .assertEqual (snapshot_of .startswith ('OpaqueRef:' ), False )
307505
308506class TestLVHDVDI (unittest .TestCase , Stubs ):
309507
0 commit comments