@@ -141,22 +141,50 @@ def mock_handles(type_str):
141141 self .mock_target .vdi .sr .handles .side_effect = mock_handles
142142 self .mock_target .session = self .mock_session
143143 mock_target .session = self .mock_session
144+ self .caps = {}
145+ self .mock_target .has_cap .side_effect = self .get_caps
144146
145147 self .vdi_uuid = str (uuid .uuid4 ())
146148 self .sr_uuid = str (uuid .uuid4 ())
147149
148150 self .vdi = blktap2 .VDI (self .vdi_uuid , mock_target , None )
151+ self .vdi .target .vdi .uuid = self .vdi_uuid
152+
153+ phylink_patcher = mock .patch ('blktap2.VDI.PhyLink' )
154+ self .mock_phylink = phylink_patcher .start ()
155+ self .mock_phylink .from_uuid .return_value = blktap2 .VDI .PhyLink ("dummy path" )
156+ self .mock_phylink .readlink .side_effect = None
149157
150158 log_patcher = mock .patch ('blktap2.util.SMlog' , autospec = True )
151159 self .mock_log = log_patcher .start ()
152160
161+ self .log_lines = []
153162 def log_stderr (message , ident = "SM" , priority = syslog .LOG_INFO ):
163+ self .log_lines .append (message )
154164 print (message , file = sys .stderr )
165+
155166 self .mock_log .side_effect = log_stderr
156167
157168 sm_vdi_patcher = mock .patch ('blktap2.sm' )
158169 self .mock_sm_vdi = sm_vdi_patcher .start ()
159170
171+ sr_patcher = mock .patch ('SR.SR' , autospec = True )
172+ self .mock_sr = sr_patcher .start ()
173+ def from_uuid (_ , sr_uuid ):
174+ sr = mock .create_autospec ('SR.SR' )
175+ sr .path = os .path .join ('/run/' , sr_uuid )
176+ return sr
177+ self .mock_sr .from_uuid .side_effect = from_uuid
178+
179+ vhdutil_patcher = mock .patch ("blktap2.vhdutil" , autospec = True )
180+ self .mock_vhdutil = vhdutil_patcher .start ()
181+
182+ mkdir_patcher = mock .patch ('blktap2.os.mkdir' , autospec = True )
183+ self .mock_mkdir = mkdir_patcher .start ()
184+
185+ def get_caps (self , name ):
186+ return name in self .caps
187+
160188 def test_tap_wanted_returns_true_for_udev_device (self ):
161189 result = self .vdi .tap_wanted ()
162190
@@ -407,6 +435,110 @@ def test_activate_rw_already_activating_fail(
407435 self .assertEqual (46 , srose .exception .errno )
408436 self .assertIn ( 'MAP_DUPLICATE_KEY' , str (srose .exception ))
409437
438+ def test_setup_cache_not_allowed (self ):
439+ params = {'vdi_allow_caching' : 'false' }
440+
441+ self .vdi .setup_cache (self .sr_uuid , self .vdi_uuid , params )
442+
443+ def test_setup_cache_no_capability (self ):
444+ params = {'vdi_allow_caching' : 'true' }
445+
446+ self .caps = {}
447+
448+ self .vdi .setup_cache (self .sr_uuid , self .vdi_uuid , params )
449+
450+ self .assertIn ('local caching not supported by this SR' , self .log_lines [- 1 ])
451+
452+ def test_setup_cache_reset_no_cap (self ):
453+ params = {'vdi_allow_caching' : 'true' ,
454+ 'vdi_on_boot' : 'reset' }
455+
456+ self .caps = {"SR_CACHING" }
457+
458+ self .vdi .setup_cache (self .sr_uuid , self .vdi_uuid , params )
459+
460+ self .assertIn ('scratch mode not supported by this SR' , self .log_lines [- 1 ])
461+
462+ def test_setup_cache_no_local_cache_sr (self ):
463+ params = {'vdi_allow_caching' : 'true' }
464+
465+ self .caps = {"SR_CACHING" }
466+
467+ self .vdi .setup_cache (self .sr_uuid , self .vdi_uuid , params )
468+
469+ self .assertIn ('Local cache SR not specified, not enabling' , self .log_lines [- 1 ])
470+
471+ def test_setup_cache_no_parent (self ):
472+ local_cache_sr = str (uuid .uuid4 ())
473+ params = {'vdi_allow_caching' : 'true' ,
474+ 'local_cache_sr' : local_cache_sr }
475+
476+ self .caps = {"SR_CACHING" }
477+
478+ self .vdi .setup_cache (self .sr_uuid , self .vdi_uuid , params )
479+
480+ self .assertRegex (self .log_lines [- 1 ], r'Parent VDI .* has parent, not enabling' )
481+
482+ @mock .patch ('blktap2.Blktap' , autospec = True )
483+ @mock .patch ("blktap2.Tapdisk.launch_on_tap" )
484+ @mock .patch ("blktap2.Tapdisk.find_by_path" )
485+ def test_setup_cache_success_prt_td_present (self , mock_find_by_path , mock_launch , mock_blktap ):
486+ local_cache_sr = str (uuid .uuid4 ())
487+ params = {'vdi_allow_caching' : 'true' ,
488+ 'local_cache_sr' : local_cache_sr }
489+
490+ self .caps = {"SR_CACHING" }
491+
492+ mock_vdi_uuid = str (uuid .uuid4 ())
493+ mock_vdi = mock .create_autospec (blktap2 .VDI )
494+ self .mock_target .vdi .sr .vdi .return_value = mock_vdi
495+ mock_vdi .parent = None
496+ mock_vdi .uuid = mock_vdi_uuid
497+ mock_vdi .path = "prt_path"
498+
499+ # Return some sizes (all the same here)
500+ self .mock_vhdutil .getSizeVirt .return_value = 20 * 1024 * 1024
501+
502+ prt_tapdisk = blktap2 .Tapdisk (
503+ 1457 , 3 , 'vhd' , 'dummy' , 1 )
504+ # Find the parent, don't find the leaf
505+ prt_path = os .path .join ('/run/' , local_cache_sr , f'{ mock_vdi_uuid } .vhdcache' )
506+ paths = {
507+ prt_path : prt_tapdisk
508+ }
509+ def find_by_path (path ):
510+ return paths .get (path )
511+ mock_find_by_path .side_effect = find_by_path
512+
513+ self .vdi .setup_cache (self .sr_uuid , self .vdi_uuid , params )
514+ mock_launch .assert_called_once ()
515+
516+ @mock .patch ('blktap2.Blktap' , autospec = True )
517+ @mock .patch ("blktap2.Tapdisk.launch_on_tap" )
518+ @mock .patch ("blktap2.Tapdisk.find_by_path" )
519+ def test_setup_cache_success_no_prt_td_present (self , mock_find_by_path , mock_launch , mock_blktap ):
520+ local_cache_sr = str (uuid .uuid4 ())
521+ params = {'vdi_allow_caching' : 'true' ,
522+ 'local_cache_sr' : local_cache_sr }
523+
524+ self .caps = {"SR_CACHING" }
525+
526+ mock_vdi_uuid = str (uuid .uuid4 ())
527+ mock_vdi = mock .create_autospec (blktap2 .VDI )
528+ self .mock_target .vdi .sr .vdi .return_value = mock_vdi
529+ mock_vdi .parent = None
530+ mock_vdi .uuid = mock_vdi_uuid
531+ mock_vdi .path = "prt_path"
532+
533+ # Return some sizes (all the same here)
534+ self .mock_vhdutil .getSizeVirt .return_value = 20 * 1024 * 1024
535+
536+ # No existing tapdisk paths
537+ mock_find_by_path .return_value = {}
538+
539+ self .vdi .setup_cache (self .sr_uuid , self .vdi_uuid , params )
540+ self .assertEqual (2 , mock_launch .call_count )
541+
410542
411543class TestTapCtl (unittest .TestCase ):
412544
0 commit comments