1+ import os
12import unittest
23import unittest .mock as mock
34
5+ import traceback
6+
47from uuid import uuid4
58
69import SR
710import LVHDoISCSISR
11+ import iscsilib
812from BaseISCSI import BaseISCSISR
913import SRCommand
1014import util
@@ -126,13 +130,29 @@ def test_1st_try_block_raise_RandomError(
126130class TestLVHDoISCSISR (unittest .TestCase ):
127131
128132 def setUp (self ):
129- util_patcher = mock .patch ('LVHDoISCSISR.util' )
133+ util_patcher = mock .patch ('LVHDoISCSISR.util' , autospec = True )
130134 self .mock_util = util_patcher .start ()
135+ # self.mock_util.SMlog.side_effect = print
136+ self .mock_util .isVDICommand = util .isVDICommand
131137 self .mock_util .sessions_less_than_targets = util .sessions_less_than_targets
132- baseiscsi_patcher = mock .patch ('LVHDoISCSISR.BaseISCSI.BaseISCSISR' )
138+
139+ self .base_srs = set ()
140+ baseiscsi_patcher = mock .patch ('LVHDoISCSISR.BaseISCSI.BaseISCSISR' ,
141+ autospec = True )
133142 patched_baseiscsi = baseiscsi_patcher .start ()
134- self .mock_baseiscsi = mock .create_autospec (BaseISCSISR )
135- patched_baseiscsi .return_value = self .mock_baseiscsi
143+ patched_baseiscsi .side_effect = self .baseiscsi
144+ lvhdsr_patcher = mock .patch ('LVHDoISCSISR.LVHDSR' )
145+
146+ iscsilib_patcher = mock .patch ('LVHDoISCSISR.iscsilib' ,
147+ autospec = True )
148+ self .mock_iscsilib = iscsilib_patcher .start ()
149+ self .mock_iscsilib .discovery .side_effect = self .discovery
150+ self .mock_iscsilib ._checkTGT .side_effect = self ._checkTGT
151+ self .mock_iscsilib .login .side_effect = self .iscsi_login
152+ self .discovery_data = {}
153+ self .sessions = []
154+
155+ self .mock_lvhdsr = lvhdsr_patcher .start ()
136156 self .mock_session = mock .MagicMock ()
137157 xenapi_patcher = mock .patch ('SR.XenAPI' )
138158 mock_xenapi = xenapi_patcher .start ()
@@ -153,28 +173,81 @@ def deepcopy(to_copy):
153173
154174 self .addCleanup (mock .patch .stopall )
155175
156- dummy_cmd = mock .create_autospec (SRCommand )
157- dummy_cmd .dconf = {
176+ def _checkTGT (self , tgtIQN , tgt = '' ):
177+ all_sessions = '\n ' .join (self .sessions )
178+ matched = iscsilib ._compare_sessions_to_tgt (all_sessions , tgtIQN , tgt )
179+ return matched
180+
181+ def discovery (self , target , port , chapuser , chappassword ,
182+ targetIQN = "any" , interfaceArray = ["default" ]):
183+ return self .discovery_data .get (target , [])
184+
185+ def iscsi_login (self , target , target_iqn , chauser , chappassword ,
186+ incoming_user , incoming_password , mpath ):
187+ print (f"Logging in { target } - { target_iqn } " )
188+ session_count = len (self .sessions )
189+ self .sessions .append (f'tcp: [{ session_count } ] { target } :3260,1 { target_iqn } ' )
190+
191+ @property
192+ def mock_baseiscsi (self ):
193+ assert len (self .base_srs ) == 1
194+ single_sr = None
195+ for sr in self .base_srs :
196+ single_sr = sr
197+
198+ return single_sr
199+
200+ def baseiscsi (self , srcmd , sr_uuid ):
201+ new_baseiscsi = mock .create_autospec (BaseISCSISR )
202+ local_iqn = srcmd .dconf ['localIQN' ]
203+ target_iqn = srcmd .dconf ['targetIQN' ]
204+ target = srcmd .dconf ['target' ]
205+ new_baseiscsi .localIQN = local_iqn
206+ new_baseiscsi .targetIQN = target_iqn
207+ new_baseiscsi .target = target
208+ new_baseiscsi .path = os .path .join ('/dev/iscsi' , target_iqn , target )
209+ new_baseiscsi .port = 3260
210+ new_baseiscsi .chapuser = srcmd .dconf .get ('chapuser' )
211+ new_baseiscsi .chappassword = srcmd .dconf .get ('chappassword' )
212+ new_baseiscsi .incoming_chapuser = srcmd .dconf .get ('incoming_chapuser' )
213+ new_baseiscsi .incoming_chappassword = srcmd .dconf .get ('incoming_chappassword' )
214+ self .base_srs .add (new_baseiscsi )
215+
216+ return new_baseiscsi
217+
218+ def create_test_sr (self , sr_cmd ):
219+ self .sr_uuid = str (uuid4 ())
220+ self .subject = LVHDoISCSISR .LVHDoISCSISR (
221+ sr_cmd , self .sr_uuid )
222+
223+ def create_sr_command (
224+ self , additional_dconf = None , cmd = None ,
225+ target_iqn = 'iqn.2009-01.example.test:iscsi085e938a' ):
226+
227+ sr_cmd = mock .create_autospec (SRCommand )
228+ sr_cmd .dconf = {
158229 'SCSIid' : '3600a098038313577792450384a4a6275' ,
159230 'multihomelist' : 'tgt1:3260,tgt2:3260' ,
160231 'target' : "10.70.89.34" ,
161- 'targetIQN' : 'iqn.2009-01.example.test:iscsi085e938a'
232+ 'targetIQN' : target_iqn ,
233+ 'localIQN' : 'iqn.2018-05.com.example:0d312804'
162234 }
163- dummy_cmd .params = {
235+ if additional_dconf :
236+ sr_cmd .dconf .update (additional_dconf )
237+
238+ sr_cmd .params = {
164239 'command' : 'nop' ,
165240 'session_ref' : 'test_session' ,
166241 'host_ref' : 'test_host' ,
167242 'sr_ref' : 'sr_ref'
168243 }
169- dummy_cmd .cmd = None
170-
171- self .sr_uuid = str (uuid4 ())
172- self .subject = LVHDoISCSISR .LVHDoISCSISR (
173- dummy_cmd , self .sr_uuid )
244+ sr_cmd .cmd = cmd
245+ return sr_cmd
174246
175247 def test_check_sr_pbd_not_found (self ):
176248 # Arrange
177249 self .mock_util .find_my_pbd .return_value = None
250+ self .create_test_sr (self .create_sr_command ())
178251
179252 # Act
180253 self .subject .check_sr (TEST_SR_UUID )
@@ -189,6 +262,7 @@ def test_check_sr_correct_sessions_count(self):
189262 self .mock_session .xenapi .PBD .get_other_config .return_value = {
190263 'iscsi_sessions' : 2
191264 }
265+ self .create_test_sr (self .create_sr_command ())
192266
193267 # Act
194268 self .subject .check_sr (TEST_SR_UUID )
@@ -202,7 +276,7 @@ def test_check_sr_not_enough_sessions(self):
202276 self .mock_session .xenapi .PBD .get_other_config .return_value = {
203277 'iscsi_sessions' : 1
204278 }
205-
279+ self . create_test_sr ( self . create_sr_command ())
206280
207281 # Act
208282 self .subject .check_sr (TEST_SR_UUID )
@@ -211,3 +285,76 @@ def test_check_sr_not_enough_sessions(self):
211285 self .mock_baseiscsi .attach .assert_called_with (
212286 TEST_SR_UUID
213287 )
288+
289+ def test_sr_attach_multi_session (self ):
290+ # Arrange
291+ self .mock_util .find_my_pbd .return_value = 'my_pbd'
292+ additional_dconf = {
293+ 'multiSession' : '10.207.6.60,3260,iqn.2009-11.com.infinidat:storage:infinibox-sn-3393|'
294+ '10.207.3.65,3260,iqn.2009-11.com.infinidat:storage:infinibox-sn-3394|'
295+ '10.207.3.61,3260,iqn.2009-11.com.infinidat:storage:infinibox-sn-3393|'
296+ '10.207.6.61,3260,iqn.2009-11.com.infinidat:storage:infinibox-sn-3393|'
297+ '10.207.3.63,3260,iqn.2009-11.com.infinidat:storage:infinibox-sn-3394|'
298+ '10.207.6.62,3260,iqn.2009-11.com.infinidat:storage:infinibox-sn-3393|'
299+ '10.207.3.62,3260,iqn.2009-11.com.infinidat:storage:infinibox-sn-3393|'
300+ '10.207.3.60,3260,iqn.2009-11.com.infinidat:storage:infinibox-sn-3393|'
301+ '10.207.6.64,3260,iqn.2009-11.com.infinidat:storage:infinibox-sn-3394|'
302+ '10.207.6.65,3260,iqn.2009-11.com.infinidat:storage:infinibox-sn-3394|'
303+ '10.207.3.64,3260,iqn.2009-11.com.infinidat:storage:infinibox-sn-3394|'
304+ '10.207.6.63,3260,iqn.2009-11.com.infinidat:storage:infinibox-sn-3394|'
305+ }
306+
307+ tpg_data = [
308+ [
309+ ('10.207.3.60:3260' , 1 , 'iqn.2009-11.com.infinidat:storage:infinibox-sn-3393' ),
310+ ('10.207.3.61:3260' , 1 , 'iqn.2009-11.com.infinidat:storage:infinibox-sn-3393' ),
311+ ('10.207.3.62:3260' , 1 , 'iqn.2009-11.com.infinidat:storage:infinibox-sn-3393' )],
312+ [
313+ ('10.207.3.63:3260' , 1 , 'iqn.2009-11.com.infinidat:storage:infinibox-sn-3394' ),
314+ ('10.207.3.64:3260' , 1 , 'iqn.2009-11.com.infinidat:storage:infinibox-sn-3394' ),
315+ ('10.207.3.65:3260' , 1 , 'iqn.2009-11.com.infinidat:storage:infinibox-sn-3394' )],
316+ [
317+ ('10.207.6.60:3260' , 2 , 'iqn.2009-11.com.infinidat:storage:infinibox-sn-3393' ),
318+ ('10.207.6.61:3260' , 2 , 'iqn.2009-11.com.infinidat:storage:infinibox-sn-3393' ),
319+ ('10.207.6.62:3260' , 2 , 'iqn.2009-11.com.infinidat:storage:infinibox-sn-3393' )
320+ ],
321+ [
322+ ('10.207.6.63:3260' , 2 , 'iqn.2009-11.com.infinidat:storage:infinibox-sn-3394' ),
323+ ('10.207.6.64:3260' , 2 , 'iqn.2009-11.com.infinidat:storage:infinibox-sn-3394' ),
324+ ('10.207.6.65:3260' , 2 , 'iqn.2009-11.com.infinidat:storage:infinibox-sn-3394' )
325+ ]
326+ ]
327+
328+ self .discovery_data = {
329+ '10.207.3.60' : tpg_data [0 ],
330+ '10.207.3.61' : tpg_data [0 ],
331+ '10.207.3.62' : tpg_data [0 ],
332+ '10.207.3.63' : tpg_data [1 ],
333+ '10.207.3.64' : tpg_data [1 ],
334+ '10.207.3.65' : tpg_data [1 ],
335+ '10.207.6.60' : tpg_data [2 ],
336+ '10.207.6.61' : tpg_data [2 ],
337+ '10.207.6.62' : tpg_data [2 ],
338+ '10.207.6.63' : tpg_data [3 ],
339+ '10.207.6.64' : tpg_data [3 ],
340+ '10.207.6.65' : tpg_data [3 ]
341+ }
342+
343+ # Create SR
344+ self .create_test_sr (self .create_sr_command (
345+ additional_dconf = additional_dconf ,
346+ cmd = 'sr_attach' ,
347+ target_iqn = '*' ))
348+
349+ # Act
350+ self .subject .attach (TEST_SR_UUID )
351+
352+ # Assert
353+ # print(f"iscsilib calls {self.mock_iscsilib.mock_calls}")
354+ attach_count = 0
355+ for sr in self .base_srs :
356+ attach_count += sr .attach .call_count
357+
358+ self .assertEqual (12 , attach_count )
359+ self .assertEqual (12 , self .mock_iscsilib .discovery .call_count )
360+ self .assertEqual (12 , self .mock_iscsilib .login .call_count )
0 commit comments