~smoser/curtin/trunk.bzr-dead

« back to all changes in this revision

Viewing changes to tests/unittests/test_block_iscsi.py

  • Committer: Scott Moser
  • Date: 2017-12-20 17:33:03 UTC
  • Revision ID: smoser@ubuntu.com-20171220173303-29gha5qb8wpqrd40
README: Mention move of revision control to git.

curtin development has moved its revision control to git.
It is available at
  https://code.launchpad.net/curtin

Clone with
  git clone https://git.launchpad.net/curtin
or
  git clone git+ssh://git.launchpad.net/curtin

For more information see
  http://curtin.readthedocs.io/en/latest/topics/development.html

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
import mock
2
 
import os
3
 
 
4
 
from curtin.block import iscsi
5
 
from curtin import util
6
 
from .helpers import CiTestCase
7
 
 
8
 
 
9
 
class TestBlockIscsiPortalParsing(CiTestCase):
10
 
 
11
 
    def test_iscsi_portal_parsing_string(self):
12
 
        with self.assertRaisesRegexp(ValueError, 'not a string'):
13
 
            iscsi.assert_valid_iscsi_portal(1234)
14
 
 
15
 
    def test_iscsi_portal_parsing_no_port(self):
16
 
        # port must be specified
17
 
        with self.assertRaisesRegexp(ValueError, 'not in the format'):
18
 
            iscsi.assert_valid_iscsi_portal('192.168.1.12')
19
 
        with self.assertRaisesRegexp(ValueError, 'not in the format'):
20
 
            iscsi.assert_valid_iscsi_portal('fe80::a634:d9ff:fe40:768a')
21
 
        with self.assertRaisesRegexp(ValueError, 'not in the format'):
22
 
            iscsi.assert_valid_iscsi_portal('192.168.1.12:')
23
 
        with self.assertRaisesRegexp(ValueError, 'not in the format'):
24
 
            iscsi.assert_valid_iscsi_portal('test.example.com:')
25
 
 
26
 
    def test_iscsi_portal_parsing_valid_ip(self):
27
 
        # IP must be in [] for IPv6, if not we misparse
28
 
        host, port = iscsi.assert_valid_iscsi_portal(
29
 
            'fe80::a634:d9ff:fe40:768a:9999')
30
 
        self.assertEquals(host, 'fe80::a634:d9ff:fe40:768a')
31
 
        self.assertEquals(port, 9999)
32
 
        # IP must not be in [] if port is specified for IPv4
33
 
        with self.assertRaisesRegexp(ValueError, 'Invalid IPv6 address'):
34
 
            iscsi.assert_valid_iscsi_portal('[192.168.1.12]:9000')
35
 
        with self.assertRaisesRegexp(ValueError, 'Invalid IPv6 address'):
36
 
            iscsi.assert_valid_iscsi_portal('[test.example.com]:8000')
37
 
 
38
 
    def test_iscsi_portal_parsing_ip(self):
39
 
        with self.assertRaisesRegexp(ValueError, 'Invalid IPv6 address'):
40
 
            iscsi.assert_valid_iscsi_portal(
41
 
                '[1200::AB00:1234::2552:7777:1313]:9999')
42
 
        # cannot distinguish between bad IP and bad hostname
43
 
        host, port = iscsi.assert_valid_iscsi_portal('192.168:9000')
44
 
        self.assertEquals(host, '192.168')
45
 
        self.assertEquals(port, 9000)
46
 
 
47
 
    def test_iscsi_portal_parsing_port(self):
48
 
        with self.assertRaisesRegexp(ValueError, 'not in the format'):
49
 
            iscsi.assert_valid_iscsi_portal('192.168.1.12:ABCD')
50
 
        with self.assertRaisesRegexp(ValueError, 'not in the format'):
51
 
            iscsi.assert_valid_iscsi_portal('[fe80::a634:d9ff:fe40:768a]:ABCD')
52
 
        with self.assertRaisesRegexp(ValueError, 'not in the format'):
53
 
            iscsi.assert_valid_iscsi_portal('test.example.com:ABCD')
54
 
 
55
 
    def test_iscsi_portal_parsing_good_portals(self):
56
 
        host, port = iscsi.assert_valid_iscsi_portal('192.168.1.12:9000')
57
 
        self.assertEquals(host, '192.168.1.12')
58
 
        self.assertEquals(port, 9000)
59
 
 
60
 
        host, port = iscsi.assert_valid_iscsi_portal(
61
 
            '[fe80::a634:d9ff:fe40:768a]:9999')
62
 
        self.assertEquals(host, 'fe80::a634:d9ff:fe40:768a')
63
 
        self.assertEquals(port, 9999)
64
 
 
65
 
        host, port = iscsi.assert_valid_iscsi_portal('test.example.com:8000')
66
 
        self.assertEquals(host, 'test.example.com')
67
 
        self.assertEquals(port, 8000)
68
 
 
69
 
    # disk specification:
70
 
    # TARGETSPEC=host:proto:port:lun:targetname
71
 
    # root=iscsi:$TARGETSPEC
72
 
    # root=iscsi:user:password@$TARGETSPEC
73
 
    # root=iscsi:user:password:initiatoruser:initiatorpassword@$TARGETSPEC
74
 
    def test_iscsi_disk_basic(self):
75
 
        with self.assertRaisesRegexp(ValueError, 'must be specified'):
76
 
            iscsi.IscsiDisk('')
77
 
 
78
 
        # typo
79
 
        with self.assertRaisesRegexp(ValueError, 'must be specified'):
80
 
            iscsi.IscsiDisk('iscs:')
81
 
 
82
 
        # no specification
83
 
        with self.assertRaisesRegexp(ValueError, 'must be specified'):
84
 
            iscsi.IscsiDisk('iscsi:')
85
 
        with self.assertRaisesRegexp(ValueError, 'Both host and targetname'):
86
 
            iscsi.IscsiDisk('iscsi:::::')
87
 
 
88
 
    def test_iscsi_disk_ip_valid(self):
89
 
        # these are all misparses we cannot catch trivially
90
 
        i = iscsi.IscsiDisk('iscsi:192.168::::target')
91
 
        self.assertEquals(i.user, None)
92
 
        self.assertEquals(i.password, None)
93
 
        self.assertEquals(i.iuser, None)
94
 
        self.assertEquals(i.ipassword, None)
95
 
        self.assertEquals(i.host, '192.168')
96
 
        self.assertEquals(i.proto, '6')
97
 
        self.assertEquals(i.port, 3260)
98
 
        self.assertEquals(i.lun, 0)
99
 
        self.assertEquals(i.target, 'target')
100
 
 
101
 
        i = iscsi.IscsiDisk('iscsi:[fe80::]::::target')
102
 
        self.assertEquals(i.user, None)
103
 
        self.assertEquals(i.password, None)
104
 
        self.assertEquals(i.iuser, None)
105
 
        self.assertEquals(i.ipassword, None)
106
 
        self.assertEquals(i.host, 'fe80::')
107
 
        self.assertEquals(i.proto, '6')
108
 
        self.assertEquals(i.port, 3260)
109
 
        self.assertEquals(i.lun, 0)
110
 
        self.assertEquals(i.target, 'target')
111
 
 
112
 
        i = iscsi.IscsiDisk('iscsi:test.example::::target')
113
 
        self.assertEquals(i.user, None)
114
 
        self.assertEquals(i.password, None)
115
 
        self.assertEquals(i.iuser, None)
116
 
        self.assertEquals(i.ipassword, None)
117
 
        self.assertEquals(i.host, 'test.example')
118
 
        self.assertEquals(i.proto, '6')
119
 
        self.assertEquals(i.port, 3260)
120
 
        self.assertEquals(i.lun, 0)
121
 
        self.assertEquals(i.target, 'target')
122
 
 
123
 
    def test_iscsi_disk_port(self):
124
 
        with self.assertRaisesRegexp(ValueError, 'Specified iSCSI port'):
125
 
            iscsi.IscsiDisk('iscsi:192.168.1.12::ABCD::target')
126
 
        with self.assertRaisesRegexp(ValueError, 'Specified iSCSI port'):
127
 
            iscsi.IscsiDisk('iscsi:[fe80::a634:d9ff:fe40:768a:6]::ABCD::'
128
 
                            'target')
129
 
        with self.assertRaisesRegexp(ValueError, 'Specified iSCSI port'):
130
 
            iscsi.IscsiDisk('iscsi:test.example.com::ABCD::target')
131
 
 
132
 
    def test_iscsi_disk_target(self):
133
 
        with self.assertRaisesRegexp(ValueError, 'Both host and targetname'):
134
 
            iscsi.IscsiDisk('iscsi:192.168.1.12::::')
135
 
        with self.assertRaisesRegexp(ValueError, 'Both host and targetname'):
136
 
            iscsi.IscsiDisk('iscsi:[fe80::a634:d9ff:fe40:768a:6]::::')
137
 
        with self.assertRaisesRegexp(ValueError, 'Both host and targetname'):
138
 
            iscsi.IscsiDisk('iscsi:test.example.com::::')
139
 
 
140
 
    def test_iscsi_disk_ip(self):
141
 
        with self.assertRaisesRegexp(ValueError, 'Both host and targetname'):
142
 
            iscsi.IscsiDisk('iscsi:::::target')
143
 
 
144
 
    def test_iscsi_disk_auth(self):
145
 
        # user without password
146
 
        with self.assertRaises(ValueError):
147
 
            iscsi.IscsiDisk('iscsi:user@192.168.1.12::::target')
148
 
        with self.assertRaises(ValueError):
149
 
            iscsi.IscsiDisk('iscsi:user@[fe80::a634:d9ff:fe40:768a:6]::::'
150
 
                            'target')
151
 
        with self.assertRaises(ValueError):
152
 
            iscsi.IscsiDisk('iscsi:user@test.example.com::::target')
153
 
 
154
 
        # iuser without password
155
 
        with self.assertRaises(ValueError):
156
 
            iscsi.IscsiDisk('iscsi:user:password:iuser@192.168.1.12::::target')
157
 
        with self.assertRaises(ValueError):
158
 
            iscsi.IscsiDisk('iscsi:user:password:iuser@'
159
 
                            '[fe80::a634:d9ff:fe40:768a:6]::::target')
160
 
        with self.assertRaises(ValueError):
161
 
            iscsi.IscsiDisk(
162
 
                'iscsi:user:password:iuser@test.example.com::::target')
163
 
 
164
 
    def test_iscsi_disk_good_ipv4(self):
165
 
        i = iscsi.IscsiDisk('iscsi:192.168.1.12:6:3260:1:target')
166
 
        self.assertEquals(i.user, None)
167
 
        self.assertEquals(i.password, None)
168
 
        self.assertEquals(i.iuser, None)
169
 
        self.assertEquals(i.ipassword, None)
170
 
        self.assertEquals(i.host, '192.168.1.12')
171
 
        self.assertEquals(i.proto, '6')
172
 
        self.assertEquals(i.port, 3260)
173
 
        self.assertEquals(i.lun, 1)
174
 
        self.assertEquals(i.target, 'target')
175
 
 
176
 
        i = iscsi.IscsiDisk('iscsi:192.168.1.12::3260:1:target')
177
 
        self.assertEquals(i.user, None)
178
 
        self.assertEquals(i.password, None)
179
 
        self.assertEquals(i.iuser, None)
180
 
        self.assertEquals(i.ipassword, None)
181
 
        self.assertEquals(i.host, '192.168.1.12')
182
 
        self.assertEquals(i.proto, '6')
183
 
        self.assertEquals(i.port, 3260)
184
 
        self.assertEquals(i.lun, 1)
185
 
        self.assertEquals(i.target, 'target')
186
 
 
187
 
        i = iscsi.IscsiDisk('iscsi:192.168.1.12:::1:target')
188
 
        self.assertEquals(i.user, None)
189
 
        self.assertEquals(i.password, None)
190
 
        self.assertEquals(i.iuser, None)
191
 
        self.assertEquals(i.ipassword, None)
192
 
        self.assertEquals(i.host, '192.168.1.12')
193
 
        self.assertEquals(i.proto, '6')
194
 
        self.assertEquals(i.port, 3260)
195
 
        self.assertEquals(i.lun, 1)
196
 
        self.assertEquals(i.target, 'target')
197
 
 
198
 
        i = iscsi.IscsiDisk('iscsi:user:password@192.168.1.12:::1:target')
199
 
        self.assertEquals(i.user, 'user')
200
 
        self.assertEquals(i.password, 'password')
201
 
        self.assertEquals(i.iuser, None)
202
 
        self.assertEquals(i.ipassword, None)
203
 
        self.assertEquals(i.host, '192.168.1.12')
204
 
        self.assertEquals(i.proto, '6')
205
 
        self.assertEquals(i.port, 3260)
206
 
        self.assertEquals(i.lun, 1)
207
 
        self.assertEquals(i.target, 'target')
208
 
 
209
 
        i = iscsi.IscsiDisk('iscsi:user:@192.168.1.12:::1:target')
210
 
        self.assertEquals(i.user, 'user')
211
 
        self.assertEquals(i.password, '')
212
 
        self.assertEquals(i.iuser, None)
213
 
        self.assertEquals(i.ipassword, None)
214
 
        self.assertEquals(i.host, '192.168.1.12')
215
 
        self.assertEquals(i.proto, '6')
216
 
        self.assertEquals(i.port, 3260)
217
 
        self.assertEquals(i.lun, 1)
218
 
        self.assertEquals(i.target, 'target')
219
 
 
220
 
        i = iscsi.IscsiDisk('iscsi:user:password:iuser:ipassword@'
221
 
                            '192.168.1.12:::1:target')
222
 
        self.assertEquals(i.user, 'user')
223
 
        self.assertEquals(i.password, 'password')
224
 
        self.assertEquals(i.iuser, 'iuser')
225
 
        self.assertEquals(i.ipassword, 'ipassword')
226
 
        self.assertEquals(i.host, '192.168.1.12')
227
 
        self.assertEquals(i.proto, '6')
228
 
        self.assertEquals(i.port, 3260)
229
 
        self.assertEquals(i.lun, 1)
230
 
        self.assertEquals(i.target, 'target')
231
 
 
232
 
        i = iscsi.IscsiDisk('iscsi:user:password:iuser:@'
233
 
                            '192.168.1.12:::1:target')
234
 
        self.assertEquals(i.user, 'user')
235
 
        self.assertEquals(i.password, 'password')
236
 
        self.assertEquals(i.iuser, 'iuser')
237
 
        self.assertEquals(i.ipassword, '')
238
 
        self.assertEquals(i.host, '192.168.1.12')
239
 
        self.assertEquals(i.proto, '6')
240
 
        self.assertEquals(i.port, 3260)
241
 
        self.assertEquals(i.lun, 1)
242
 
        self.assertEquals(i.target, 'target')
243
 
 
244
 
        i = iscsi.IscsiDisk('iscsi:user::iuser:@192.168.1.12:::1:target')
245
 
        self.assertEquals(i.user, 'user')
246
 
        self.assertEquals(i.password, '')
247
 
        self.assertEquals(i.iuser, 'iuser')
248
 
        self.assertEquals(i.ipassword, '')
249
 
        self.assertEquals(i.host, '192.168.1.12')
250
 
        self.assertEquals(i.proto, '6')
251
 
        self.assertEquals(i.port, 3260)
252
 
        self.assertEquals(i.lun, 1)
253
 
        self.assertEquals(i.target, 'target')
254
 
 
255
 
    def test_iscsi_disk_good_ipv6(self):
256
 
        i = iscsi.IscsiDisk(
257
 
            'iscsi:[fe80::a634:d9ff:fe40:768a:6]:5:3260:1:target')
258
 
        self.assertEquals(i.user, None)
259
 
        self.assertEquals(i.password, None)
260
 
        self.assertEquals(i.iuser, None)
261
 
        self.assertEquals(i.ipassword, None)
262
 
        self.assertEquals(i.host, 'fe80::a634:d9ff:fe40:768a:6')
263
 
        self.assertEquals(i.proto, '6')
264
 
        self.assertEquals(i.port, 3260)
265
 
        self.assertEquals(i.lun, 1)
266
 
        self.assertEquals(i.target, 'target')
267
 
 
268
 
        i = iscsi.IscsiDisk(
269
 
            'iscsi:[fe80::a634:d9ff:fe40:768a:6]::3260:1:target')
270
 
        self.assertEquals(i.user, None)
271
 
        self.assertEquals(i.password, None)
272
 
        self.assertEquals(i.iuser, None)
273
 
        self.assertEquals(i.ipassword, None)
274
 
        self.assertEquals(i.host, 'fe80::a634:d9ff:fe40:768a:6')
275
 
        self.assertEquals(i.proto, '6')
276
 
        self.assertEquals(i.port, 3260)
277
 
        self.assertEquals(i.lun, 1)
278
 
        self.assertEquals(i.target, 'target')
279
 
 
280
 
        i = iscsi.IscsiDisk('iscsi:[fe80::a634:d9ff:fe40:768a:6]:::1:target')
281
 
        self.assertEquals(i.user, None)
282
 
        self.assertEquals(i.password, None)
283
 
        self.assertEquals(i.iuser, None)
284
 
        self.assertEquals(i.ipassword, None)
285
 
        self.assertEquals(i.host, 'fe80::a634:d9ff:fe40:768a:6')
286
 
        self.assertEquals(i.proto, '6')
287
 
        self.assertEquals(i.port, 3260)
288
 
        self.assertEquals(i.lun, 1)
289
 
        self.assertEquals(i.target, 'target')
290
 
 
291
 
        i = iscsi.IscsiDisk('iscsi:user:password@'
292
 
                            '[fe80::a634:d9ff:fe40:768a:6]:::1:target')
293
 
        self.assertEquals(i.user, 'user')
294
 
        self.assertEquals(i.password, 'password')
295
 
        self.assertEquals(i.iuser, None)
296
 
        self.assertEquals(i.ipassword, None)
297
 
        self.assertEquals(i.host, 'fe80::a634:d9ff:fe40:768a:6')
298
 
        self.assertEquals(i.proto, '6')
299
 
        self.assertEquals(i.port, 3260)
300
 
        self.assertEquals(i.lun, 1)
301
 
        self.assertEquals(i.target, 'target')
302
 
 
303
 
        i = iscsi.IscsiDisk('iscsi:user:@'
304
 
                            '[fe80::a634:d9ff:fe40:768a:6]:::1:target')
305
 
        self.assertEquals(i.user, 'user')
306
 
        self.assertEquals(i.password, '')
307
 
        self.assertEquals(i.iuser, None)
308
 
        self.assertEquals(i.ipassword, None)
309
 
        self.assertEquals(i.host, 'fe80::a634:d9ff:fe40:768a:6')
310
 
        self.assertEquals(i.proto, '6')
311
 
        self.assertEquals(i.port, 3260)
312
 
        self.assertEquals(i.lun, 1)
313
 
        self.assertEquals(i.target, 'target')
314
 
 
315
 
        i = iscsi.IscsiDisk('iscsi:user:password:iuser:ipassword@'
316
 
                            '[fe80::a634:d9ff:fe40:768a:6]:::1:target')
317
 
        self.assertEquals(i.user, 'user')
318
 
        self.assertEquals(i.password, 'password')
319
 
        self.assertEquals(i.iuser, 'iuser')
320
 
        self.assertEquals(i.ipassword, 'ipassword')
321
 
        self.assertEquals(i.host, 'fe80::a634:d9ff:fe40:768a:6')
322
 
        self.assertEquals(i.proto, '6')
323
 
        self.assertEquals(i.port, 3260)
324
 
        self.assertEquals(i.lun, 1)
325
 
        self.assertEquals(i.target, 'target')
326
 
 
327
 
        i = iscsi.IscsiDisk('iscsi:user:password:iuser:@'
328
 
                            '[fe80::a634:d9ff:fe40:768a:6]:::1:target')
329
 
        self.assertEquals(i.user, 'user')
330
 
        self.assertEquals(i.password, 'password')
331
 
        self.assertEquals(i.iuser, 'iuser')
332
 
        self.assertEquals(i.ipassword, '')
333
 
        self.assertEquals(i.host, 'fe80::a634:d9ff:fe40:768a:6')
334
 
        self.assertEquals(i.proto, '6')
335
 
        self.assertEquals(i.port, 3260)
336
 
        self.assertEquals(i.lun, 1)
337
 
        self.assertEquals(i.target, 'target')
338
 
 
339
 
        i = iscsi.IscsiDisk('iscsi:user::iuser:@'
340
 
                            '[fe80::a634:d9ff:fe40:768a:6]:::1:target')
341
 
        self.assertEquals(i.user, 'user')
342
 
        self.assertEquals(i.password, '')
343
 
        self.assertEquals(i.iuser, 'iuser')
344
 
        self.assertEquals(i.ipassword, '')
345
 
        self.assertEquals(i.host, 'fe80::a634:d9ff:fe40:768a:6')
346
 
        self.assertEquals(i.proto, '6')
347
 
        self.assertEquals(i.port, 3260)
348
 
        self.assertEquals(i.lun, 1)
349
 
        self.assertEquals(i.target, 'target')
350
 
 
351
 
    def test_iscsi_disk_good_hostname(self):
352
 
        i = iscsi.IscsiDisk('iscsi:test.example.com:6:3260:1:target')
353
 
        self.assertEquals(i.user, None)
354
 
        self.assertEquals(i.password, None)
355
 
        self.assertEquals(i.iuser, None)
356
 
        self.assertEquals(i.ipassword, None)
357
 
        self.assertEquals(i.host, 'test.example.com')
358
 
        self.assertEquals(i.proto, '6')
359
 
        self.assertEquals(i.port, 3260)
360
 
        self.assertEquals(i.lun, 1)
361
 
        self.assertEquals(i.target, 'target')
362
 
 
363
 
        i = iscsi.IscsiDisk('iscsi:test.example.com::3260:1:target')
364
 
        self.assertEquals(i.user, None)
365
 
        self.assertEquals(i.password, None)
366
 
        self.assertEquals(i.iuser, None)
367
 
        self.assertEquals(i.ipassword, None)
368
 
        self.assertEquals(i.host, 'test.example.com')
369
 
        self.assertEquals(i.proto, '6')
370
 
        self.assertEquals(i.port, 3260)
371
 
        self.assertEquals(i.lun, 1)
372
 
        self.assertEquals(i.target, 'target')
373
 
 
374
 
        i = iscsi.IscsiDisk('iscsi:test.example.com:::1:target')
375
 
        self.assertEquals(i.user, None)
376
 
        self.assertEquals(i.password, None)
377
 
        self.assertEquals(i.iuser, None)
378
 
        self.assertEquals(i.ipassword, None)
379
 
        self.assertEquals(i.host, 'test.example.com')
380
 
        self.assertEquals(i.proto, '6')
381
 
        self.assertEquals(i.port, 3260)
382
 
        self.assertEquals(i.lun, 1)
383
 
        self.assertEquals(i.target, 'target')
384
 
 
385
 
        i = iscsi.IscsiDisk('iscsi:user:password@test.example.com:::1:target')
386
 
        self.assertEquals(i.user, 'user')
387
 
        self.assertEquals(i.password, 'password')
388
 
        self.assertEquals(i.iuser, None)
389
 
        self.assertEquals(i.ipassword, None)
390
 
        self.assertEquals(i.host, 'test.example.com')
391
 
        self.assertEquals(i.proto, '6')
392
 
        self.assertEquals(i.port, 3260)
393
 
        self.assertEquals(i.lun, 1)
394
 
        self.assertEquals(i.target, 'target')
395
 
 
396
 
        i = iscsi.IscsiDisk('iscsi:user:@test.example.com:::1:target')
397
 
        self.assertEquals(i.user, 'user')
398
 
        self.assertEquals(i.password, '')
399
 
        self.assertEquals(i.iuser, None)
400
 
        self.assertEquals(i.ipassword, None)
401
 
        self.assertEquals(i.host, 'test.example.com')
402
 
        self.assertEquals(i.proto, '6')
403
 
        self.assertEquals(i.port, 3260)
404
 
        self.assertEquals(i.lun, 1)
405
 
        self.assertEquals(i.target, 'target')
406
 
 
407
 
        i = iscsi.IscsiDisk('iscsi:user:password:iuser:ipassword@'
408
 
                            'test.example.com:::1:target')
409
 
        self.assertEquals(i.user, 'user')
410
 
        self.assertEquals(i.password, 'password')
411
 
        self.assertEquals(i.iuser, 'iuser')
412
 
        self.assertEquals(i.ipassword, 'ipassword')
413
 
        self.assertEquals(i.host, 'test.example.com')
414
 
        self.assertEquals(i.proto, '6')
415
 
        self.assertEquals(i.port, 3260)
416
 
        self.assertEquals(i.lun, 1)
417
 
        self.assertEquals(i.target, 'target')
418
 
 
419
 
        i = iscsi.IscsiDisk('iscsi:user:password:iuser:@'
420
 
                            'test.example.com:::1:target')
421
 
        self.assertEquals(i.user, 'user')
422
 
        self.assertEquals(i.password, 'password')
423
 
        self.assertEquals(i.iuser, 'iuser')
424
 
        self.assertEquals(i.ipassword, '')
425
 
        self.assertEquals(i.host, 'test.example.com')
426
 
        self.assertEquals(i.proto, '6')
427
 
        self.assertEquals(i.port, 3260)
428
 
        self.assertEquals(i.lun, 1)
429
 
        self.assertEquals(i.target, 'target')
430
 
 
431
 
        i = iscsi.IscsiDisk('iscsi:user::iuser:@test.example.com:::1:target')
432
 
        self.assertEquals(i.user, 'user')
433
 
        self.assertEquals(i.password, '')
434
 
        self.assertEquals(i.iuser, 'iuser')
435
 
        self.assertEquals(i.ipassword, '')
436
 
        self.assertEquals(i.host, 'test.example.com')
437
 
        self.assertEquals(i.proto, '6')
438
 
        self.assertEquals(i.port, 3260)
439
 
        self.assertEquals(i.lun, 1)
440
 
        self.assertEquals(i.target, 'target')
441
 
 
442
 
    # LP: #1679222
443
 
    def test_iscsi_target_parsing(self):
444
 
        i = iscsi.IscsiDisk(
445
 
            'iscsi:192.168.1.12::::iqn.2017-04.com.example.test:target-name')
446
 
        self.assertEquals(i.user, None)
447
 
        self.assertEquals(i.password, None)
448
 
        self.assertEquals(i.iuser, None)
449
 
        self.assertEquals(i.ipassword, None)
450
 
        self.assertEquals(i.host, '192.168.1.12')
451
 
        self.assertEquals(i.proto, '6')
452
 
        self.assertEquals(i.port, 3260)
453
 
        self.assertEquals(i.lun, 0)
454
 
        self.assertEquals(i.target, 'iqn.2017-04.com.example.test:target-name')
455
 
 
456
 
        i = iscsi.IscsiDisk(
457
 
            'iscsi:[fe80::a634:d9ff:fe40:768a:6]::::'
458
 
            'iqn.2017-04.com.example.test:target-name')
459
 
        self.assertEquals(i.user, None)
460
 
        self.assertEquals(i.password, None)
461
 
        self.assertEquals(i.iuser, None)
462
 
        self.assertEquals(i.ipassword, None)
463
 
        self.assertEquals(i.host, 'fe80::a634:d9ff:fe40:768a:6')
464
 
        self.assertEquals(i.proto, '6')
465
 
        self.assertEquals(i.port, 3260)
466
 
        self.assertEquals(i.lun, 0)
467
 
        self.assertEquals(i.target, 'iqn.2017-04.com.example.test:target-name')
468
 
 
469
 
        i = iscsi.IscsiDisk(
470
 
            'iscsi:test.example.com::::'
471
 
            'iqn.2017-04.com.example.test:target-name')
472
 
        self.assertEquals(i.user, None)
473
 
        self.assertEquals(i.password, None)
474
 
        self.assertEquals(i.iuser, None)
475
 
        self.assertEquals(i.ipassword, None)
476
 
        self.assertEquals(i.host, 'test.example.com')
477
 
        self.assertEquals(i.proto, '6')
478
 
        self.assertEquals(i.port, 3260)
479
 
        self.assertEquals(i.lun, 0)
480
 
        self.assertEquals(i.target, 'iqn.2017-04.com.example.test:target-name')
481
 
 
482
 
 
483
 
class TestBlockIscsiVolPath(CiTestCase):
484
 
    # non-iscsi backed disk returns false
485
 
    # regular iscsi-backed disk returns true
486
 
    # layered setup without an iscsi member returns false
487
 
    # layered setup with an iscsi member returns true
488
 
 
489
 
    def setUp(self):
490
 
        super(TestBlockIscsiVolPath, self).setUp()
491
 
        self.add_patch('curtin.block.iscsi.get_device_slave_knames',
492
 
                       'mock_get_device_slave_knames')
493
 
        self.add_patch('curtin.block.iscsi.path_to_kname',
494
 
                       'mock_path_to_kname')
495
 
        self.add_patch('curtin.block.iscsi.kname_is_iscsi',
496
 
                       'mock_kname_is_iscsi')
497
 
 
498
 
    def test_volpath_is_iscsi_false(self):
499
 
        volume_path = '/dev/wark'
500
 
        kname = 'wark'
501
 
        slaves = []
502
 
        self.mock_get_device_slave_knames.return_value = slaves
503
 
        self.mock_path_to_kname.return_value = kname
504
 
        self.mock_kname_is_iscsi.return_value = 'iscsi' in kname
505
 
 
506
 
        is_iscsi = iscsi.volpath_is_iscsi(volume_path)
507
 
 
508
 
        self.assertFalse(is_iscsi)
509
 
        self.mock_get_device_slave_knames.assert_called_with(volume_path)
510
 
        self.mock_path_to_kname.assert_called_with(volume_path)
511
 
        self.mock_kname_is_iscsi.assert_called_with(kname)
512
 
 
513
 
    def test_volpath_is_iscsi_true(self):
514
 
        volume_path = '/dev/wark'
515
 
        kname = 'wark-iscsi-lun-2'
516
 
        slaves = []
517
 
        self.mock_get_device_slave_knames.return_value = slaves
518
 
        self.mock_path_to_kname.return_value = kname
519
 
        self.mock_kname_is_iscsi.return_value = 'iscsi' in kname
520
 
 
521
 
        is_iscsi = iscsi.volpath_is_iscsi(volume_path)
522
 
 
523
 
        self.assertTrue(is_iscsi)
524
 
        self.mock_get_device_slave_knames.assert_called_with(volume_path)
525
 
        self.mock_path_to_kname.assert_called_with(volume_path)
526
 
        self.mock_kname_is_iscsi.assert_called_with(kname)
527
 
 
528
 
    def test_volpath_is_iscsi_layered_true(self):
529
 
        volume_path = '/dev/wark'
530
 
        slaves = ['wark', 'bzr', 'super-iscsi-lun-27']
531
 
        self.mock_get_device_slave_knames.return_value = slaves
532
 
        self.mock_path_to_kname.side_effect = lambda x: x
533
 
        self.mock_kname_is_iscsi.side_effect = lambda x: 'iscsi' in x
534
 
 
535
 
        is_iscsi = iscsi.volpath_is_iscsi(volume_path)
536
 
 
537
 
        self.assertTrue(is_iscsi)
538
 
        self.mock_get_device_slave_knames.assert_called_with(volume_path)
539
 
        self.mock_path_to_kname.assert_called_with(volume_path)
540
 
        self.mock_kname_is_iscsi.assert_has_calls([
541
 
            mock.call(x) for x in slaves])
542
 
 
543
 
    def test_volpath_is_iscsi_layered_false(self):
544
 
        volume_path = '/dev/wark'
545
 
        slaves = ['wark', 'bzr', 'nvmen27p47']
546
 
        self.mock_get_device_slave_knames.return_value = slaves
547
 
        self.mock_path_to_kname.side_effect = lambda x: x
548
 
        self.mock_kname_is_iscsi.side_effect = lambda x: 'iscsi' in x
549
 
 
550
 
        is_iscsi = iscsi.volpath_is_iscsi(volume_path)
551
 
 
552
 
        self.assertFalse(is_iscsi)
553
 
        self.mock_get_device_slave_knames.assert_called_with(volume_path)
554
 
        self.mock_path_to_kname.assert_called_with(volume_path)
555
 
        self.mock_kname_is_iscsi.assert_has_calls([
556
 
            mock.call(x) for x in slaves])
557
 
 
558
 
    def test_volpath_is_iscsi_missing_param(self):
559
 
        with self.assertRaises(ValueError):
560
 
            iscsi.volpath_is_iscsi(None)
561
 
 
562
 
 
563
 
class TestBlockIscsiDiskFromConfig(CiTestCase):
564
 
    # Test iscsi parsing of storage config for iscsi configure disks
565
 
 
566
 
    def setUp(self):
567
 
        super(TestBlockIscsiDiskFromConfig, self).setUp()
568
 
        self.add_patch('curtin.block.iscsi.util.subp', 'mock_subp')
569
 
 
570
 
    def test_parse_iscsi_disk_from_config(self):
571
 
        """Test parsing iscsi volume path creates the same iscsi disk"""
572
 
        target = 'curtin-659d5f45-4f23-46cb-b826-f2937b896e09'
573
 
        iscsi_path = 'iscsi:10.245.168.20::20112:1:' + target
574
 
        cfg = {
575
 
            'storage': {
576
 
                'config': [{'type': 'disk',
577
 
                            'id': 'iscsidev1',
578
 
                            'path': iscsi_path,
579
 
                            'name': 'iscsi_disk1',
580
 
                            'ptable': 'msdos',
581
 
                            'wipe': 'superblock'}]
582
 
                }
583
 
        }
584
 
        expected_iscsi_disk = iscsi.IscsiDisk(iscsi_path)
585
 
        iscsi_disk = iscsi.get_iscsi_disks_from_config(cfg).pop()
586
 
        # utilize IscsiDisk str method for equality check
587
 
        self.assertEqual(str(expected_iscsi_disk), str(iscsi_disk))
588
 
 
589
 
    def test_parse_iscsi_disk_from_config_no_iscsi(self):
590
 
        """Test parsing storage config with no iscsi disks included"""
591
 
        cfg = {
592
 
            'storage': {
593
 
                'config': [{'type': 'disk',
594
 
                            'id': 'ssd1',
595
 
                            'path': 'dev/slash/foo1',
596
 
                            'name': 'the-fast-one',
597
 
                            'ptable': 'gpt',
598
 
                            'wipe': 'superblock'}]
599
 
                }
600
 
        }
601
 
        expected_iscsi_disks = []
602
 
        iscsi_disks = iscsi.get_iscsi_disks_from_config(cfg)
603
 
        self.assertEqual(expected_iscsi_disks, iscsi_disks)
604
 
 
605
 
    def test_parse_iscsi_disk_from_config_invalid_iscsi(self):
606
 
        """Test parsing storage config with no iscsi disks included"""
607
 
        cfg = {
608
 
            'storage': {
609
 
                'config': [{'type': 'disk',
610
 
                            'id': 'iscsidev2',
611
 
                            'path': 'iscsi:garbage',
612
 
                            'name': 'noob-city',
613
 
                            'ptable': 'msdos',
614
 
                            'wipe': 'superblock'}]
615
 
                }
616
 
        }
617
 
        with self.assertRaises(ValueError):
618
 
            iscsi.get_iscsi_disks_from_config(cfg)
619
 
 
620
 
    def test_parse_iscsi_disk_from_config_empty(self):
621
 
        """Test parse_iscsi_disks handles empty/invalid config"""
622
 
        expected_iscsi_disks = []
623
 
        iscsi_disks = iscsi.get_iscsi_disks_from_config({})
624
 
        self.assertEqual(expected_iscsi_disks, iscsi_disks)
625
 
 
626
 
        cfg = {'storage': {'config': []}}
627
 
        iscsi_disks = iscsi.get_iscsi_disks_from_config(cfg)
628
 
        self.assertEqual(expected_iscsi_disks, iscsi_disks)
629
 
 
630
 
    def test_parse_iscsi_disk_from_config_none(self):
631
 
        """Test parse_iscsi_disks handles no config"""
632
 
        expected_iscsi_disks = []
633
 
        iscsi_disks = iscsi.get_iscsi_disks_from_config({})
634
 
        self.assertEqual(expected_iscsi_disks, iscsi_disks)
635
 
 
636
 
        cfg = None
637
 
        iscsi_disks = iscsi.get_iscsi_disks_from_config(cfg)
638
 
        self.assertEqual(expected_iscsi_disks, iscsi_disks)
639
 
 
640
 
 
641
 
class TestBlockIscsiDisconnect(CiTestCase):
642
 
    # test that when disconnecting iscsi targets we
643
 
    # check that the target has an active session before
644
 
    # issuing a disconnect command
645
 
 
646
 
    def setUp(self):
647
 
        super(TestBlockIscsiDisconnect, self).setUp()
648
 
        self.add_patch('curtin.block.iscsi.util.subp', 'mock_subp')
649
 
        self.add_patch('curtin.block.iscsi.iscsiadm_sessions',
650
 
                       'mock_iscsi_sessions')
651
 
        # fake target_root + iscsi nodes dir
652
 
        self.target_path = self.tmp_dir()
653
 
        self.iscsi_nodes = os.path.join(self.target_path, 'etc/iscsi/nodes')
654
 
        util.ensure_dir(self.iscsi_nodes)
655
 
 
656
 
    def _fmt_disconnect(self, target, portal):
657
 
        return ['iscsiadm', '--mode=node', '--targetname=%s' % target,
658
 
                '--portal=%s' % portal, '--logout']
659
 
 
660
 
    def _setup_nodes(self, sessions, connection):
661
 
        # setup iscsi_nodes dir (<fakeroot>/etc/iscsi/nodes) with content
662
 
        for s in sessions:
663
 
            sdir = os.path.join(self.iscsi_nodes, s)
664
 
            connpath = os.path.join(sdir, connection)
665
 
            util.ensure_dir(sdir)
666
 
            util.write_file(connpath, content="")
667
 
 
668
 
    def test_disconnect_target_disk(self):
669
 
        """Test iscsi disconnecting multiple sessions, all present"""
670
 
 
671
 
        sessions = [
672
 
            'curtin-53ab23ff-a887-449a-80a8-288151208091',
673
 
            'curtin-94b62de1-c579-42c0-879e-8a28178e64c5',
674
 
            'curtin-556aeecd-a227-41b7-83d7-2bb471c574b4',
675
 
            'curtin-fd0f644b-7858-420f-9997-3ea2aefe87b9'
676
 
        ]
677
 
        connection = '10.245.168.20,16395,1'
678
 
        self._setup_nodes(sessions, connection)
679
 
 
680
 
        self.mock_iscsi_sessions.return_value = "\n".join(sessions)
681
 
 
682
 
        iscsi.disconnect_target_disks(self.target_path)
683
 
 
684
 
        expected_calls = []
685
 
        for session in sessions:
686
 
            (host, port, _) = connection.split(',')
687
 
            disconnect = self._fmt_disconnect(session, "%s:%s" % (host, port))
688
 
            calls = [
689
 
                mock.call(['sync']),
690
 
                mock.call(disconnect, capture=True, log_captured=True),
691
 
                mock.call(['udevadm', 'settle']),
692
 
            ]
693
 
            expected_calls.extend(calls)
694
 
 
695
 
        self.mock_subp.assert_has_calls(expected_calls, any_order=True)
696
 
 
697
 
    def test_disconnect_target_disk_skip_disconnected(self):
698
 
        """Test iscsi does not attempt to disconnect already closed sessions"""
699
 
        sessions = [
700
 
            'curtin-53ab23ff-a887-449a-80a8-288151208091',
701
 
            'curtin-94b62de1-c579-42c0-879e-8a28178e64c5',
702
 
            'curtin-556aeecd-a227-41b7-83d7-2bb471c574b4',
703
 
            'curtin-fd0f644b-7858-420f-9997-3ea2aefe87b9'
704
 
        ]
705
 
        connection = '10.245.168.20,16395,1'
706
 
        self._setup_nodes(sessions, connection)
707
 
        # Test with all sessions are already disconnected
708
 
        self.mock_iscsi_sessions.return_value = ""
709
 
 
710
 
        iscsi.disconnect_target_disks(self.target_path)
711
 
 
712
 
        self.mock_subp.assert_has_calls([], any_order=True)
713
 
 
714
 
    @mock.patch('curtin.block.iscsi.iscsiadm_logout')
715
 
    def test_disconnect_target_disk_raises_runtime_error(self, mock_logout):
716
 
        """Test iscsi raises RuntimeError if we fail to logout"""
717
 
        sessions = [
718
 
            'curtin-53ab23ff-a887-449a-80a8-288151208091',
719
 
        ]
720
 
        connection = '10.245.168.20,16395,1'
721
 
        self._setup_nodes(sessions, connection)
722
 
        self.mock_iscsi_sessions.return_value = "\n".join(sessions)
723
 
        mock_logout.side_effect = util.ProcessExecutionError()
724
 
 
725
 
        with self.assertRaises(RuntimeError):
726
 
            iscsi.disconnect_target_disks(self.target_path)
727
 
 
728
 
        expected_calls = []
729
 
        for session in sessions:
730
 
            (host, port, _) = connection.split(',')
731
 
            disconnect = self._fmt_disconnect(session, "%s:%s" % (host, port))
732
 
            calls = [
733
 
                mock.call(['sync']),
734
 
                mock.call(disconnect, capture=True, log_captured=True),
735
 
                mock.call(['udevadm', 'settle']),
736
 
            ]
737
 
            expected_calls.extend(calls)
738
 
 
739
 
        self.mock_subp.assert_has_calls([], any_order=True)
740
 
 
741
 
# vi: ts=4 expandtab syntax=python