]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/tests/test_iscsi.py
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / pybind / mgr / dashboard / tests / test_iscsi.py
1 # pylint: disable=too-many-public-methods
2
3 import copy
4 import errno
5 import json
6 import unittest
7
8 try:
9 import mock
10 except ImportError:
11 import unittest.mock as mock
12
13 from . import CmdException, ControllerTestCase, CLICommandTestMixin, KVStoreMockMixin
14 from .. import mgr
15 from ..controllers.iscsi import Iscsi, IscsiTarget
16 from ..services.iscsi_client import IscsiClient
17 from ..services.orchestrator import OrchClient
18 from ..rest_client import RequestException
19
20
21 class IscsiTestCli(unittest.TestCase, CLICommandTestMixin):
22
23 def setUp(self):
24 self.mock_kv_store()
25 # pylint: disable=protected-access
26 IscsiClientMock._instance = IscsiClientMock()
27 IscsiClient.instance = IscsiClientMock.instance
28
29 def test_cli_add_gateway_invalid_url(self):
30 with self.assertRaises(CmdException) as ctx:
31 self.exec_cmd('iscsi-gateway-add', name='node1',
32 service_url='http:/hello.com')
33
34 self.assertEqual(ctx.exception.retcode, -errno.EINVAL)
35 self.assertEqual(str(ctx.exception),
36 "Invalid service URL 'http:/hello.com'. Valid format: "
37 "'<scheme>://<username>:<password>@<host>[:port]'.")
38
39 def test_cli_add_gateway(self):
40 self.exec_cmd('iscsi-gateway-add', name='node1',
41 service_url='https://admin:admin@10.17.5.1:5001')
42 self.exec_cmd('iscsi-gateway-add', name='node2',
43 service_url='https://admin:admin@10.17.5.2:5001')
44 iscsi_config = json.loads(self.get_key("_iscsi_config"))
45 self.assertEqual(iscsi_config['gateways'], {
46 'node1': {
47 'service_url': 'https://admin:admin@10.17.5.1:5001'
48 },
49 'node2': {
50 'service_url': 'https://admin:admin@10.17.5.2:5001'
51 }
52 })
53
54 def test_cli_remove_gateway(self):
55 self.test_cli_add_gateway()
56 self.exec_cmd('iscsi-gateway-rm', name='node1')
57 iscsi_config = json.loads(self.get_key("_iscsi_config"))
58 self.assertEqual(iscsi_config['gateways'], {
59 'node2': {
60 'service_url': 'https://admin:admin@10.17.5.2:5001'
61 }
62 })
63
64
65 class IscsiTestController(ControllerTestCase, KVStoreMockMixin):
66
67 @classmethod
68 def setup_server(cls):
69 OrchClient().available = lambda: False
70 mgr.rados.side_effect = None
71 # pylint: disable=protected-access
72 Iscsi._cp_config['tools.authenticate.on'] = False
73 IscsiTarget._cp_config['tools.authenticate.on'] = False
74 cls.setup_controllers([Iscsi, IscsiTarget])
75
76 def setUp(self):
77 self.mock_kv_store()
78 self.CONFIG_KEY_DICT['_iscsi_config'] = '''
79 {
80 "gateways": {
81 "node1": {
82 "service_url": "https://admin:admin@10.17.5.1:5001"
83 },
84 "node2": {
85 "service_url": "https://admin:admin@10.17.5.2:5001"
86 }
87 }
88 }
89 '''
90 # pylint: disable=protected-access
91 IscsiClientMock._instance = IscsiClientMock()
92 IscsiClient.instance = IscsiClientMock.instance
93
94 def test_enable_discoveryauth(self):
95 discoveryauth = {
96 'user': 'myiscsiusername',
97 'password': 'myiscsipassword',
98 'mutual_user': 'myiscsiusername2',
99 'mutual_password': 'myiscsipassword2'
100 }
101 self._put('/api/iscsi/discoveryauth', discoveryauth)
102 self.assertStatus(200)
103 self.assertJsonBody(discoveryauth)
104 self._get('/api/iscsi/discoveryauth')
105 self.assertStatus(200)
106 self.assertJsonBody(discoveryauth)
107
108 def test_disable_discoveryauth(self):
109 discoveryauth = {
110 'user': '',
111 'password': '',
112 'mutual_user': '',
113 'mutual_password': ''
114 }
115 self._put('/api/iscsi/discoveryauth', discoveryauth)
116 self.assertStatus(200)
117 self.assertJsonBody(discoveryauth)
118 self._get('/api/iscsi/discoveryauth')
119 self.assertStatus(200)
120 self.assertJsonBody(discoveryauth)
121
122 def test_list_empty(self):
123 self._get('/api/iscsi/target')
124 self.assertStatus(200)
125 self.assertJsonBody([])
126
127 @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
128 def test_list(self, _validate_image_mock):
129 target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw1"
130 request = copy.deepcopy(iscsi_target_request)
131 request['target_iqn'] = target_iqn
132 self._task_post('/api/iscsi/target', request)
133 self.assertStatus(201)
134 self._get('/api/iscsi/target')
135 self.assertStatus(200)
136 response = copy.deepcopy(iscsi_target_response)
137 response['target_iqn'] = target_iqn
138 self.assertJsonBody([response])
139
140 @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
141 def test_create(self, _validate_image_mock):
142 target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw2"
143 request = copy.deepcopy(iscsi_target_request)
144 request['target_iqn'] = target_iqn
145 self._task_post('/api/iscsi/target', request)
146 self.assertStatus(201)
147 self._get('/api/iscsi/target/{}'.format(request['target_iqn']))
148 self.assertStatus(200)
149 response = copy.deepcopy(iscsi_target_response)
150 response['target_iqn'] = target_iqn
151 self.assertJsonBody(response)
152
153 @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
154 def test_delete(self, _validate_image_mock):
155 target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw3"
156 request = copy.deepcopy(iscsi_target_request)
157 request['target_iqn'] = target_iqn
158 self._task_post('/api/iscsi/target', request)
159 self.assertStatus(201)
160 self._task_delete('/api/iscsi/target/{}'.format(request['target_iqn']))
161 self.assertStatus(204)
162 self._get('/api/iscsi/target')
163 self.assertStatus(200)
164 self.assertJsonBody([])
165
166 @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
167 def test_add_client(self, _validate_image_mock):
168 target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw4"
169 create_request = copy.deepcopy(iscsi_target_request)
170 create_request['target_iqn'] = target_iqn
171 update_request = copy.deepcopy(create_request)
172 update_request['new_target_iqn'] = target_iqn
173 update_request['clients'].append(
174 {
175 "luns": [{"image": "lun1", "pool": "rbd"}],
176 "client_iqn": "iqn.1994-05.com.redhat:rh7-client3",
177 "auth": {
178 "password": "myiscsipassword5",
179 "user": "myiscsiusername5",
180 "mutual_password": "myiscsipassword6",
181 "mutual_user": "myiscsiusername6"}
182 })
183 response = copy.deepcopy(iscsi_target_response)
184 response['target_iqn'] = target_iqn
185 response['clients'].append(
186 {
187 "luns": [{"image": "lun1", "pool": "rbd"}],
188 "client_iqn": "iqn.1994-05.com.redhat:rh7-client3",
189 "auth": {
190 "password": "myiscsipassword5",
191 "user": "myiscsiusername5",
192 "mutual_password": "myiscsipassword6",
193 "mutual_user": "myiscsiusername6"},
194 "info": {
195 "alias": "",
196 "ip_address": [],
197 "state": {}
198 }
199 })
200 self._update_iscsi_target(create_request, update_request, response)
201
202 @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
203 def test_change_client_password(self, _validate_image_mock):
204 target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw5"
205 create_request = copy.deepcopy(iscsi_target_request)
206 create_request['target_iqn'] = target_iqn
207 update_request = copy.deepcopy(create_request)
208 update_request['new_target_iqn'] = target_iqn
209 update_request['clients'][0]['auth']['password'] = 'mynewiscsipassword'
210 response = copy.deepcopy(iscsi_target_response)
211 response['target_iqn'] = target_iqn
212 response['clients'][0]['auth']['password'] = 'mynewiscsipassword'
213 self._update_iscsi_target(create_request, update_request, response)
214
215 @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
216 def test_rename_client(self, _validate_image_mock):
217 target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw6"
218 create_request = copy.deepcopy(iscsi_target_request)
219 create_request['target_iqn'] = target_iqn
220 update_request = copy.deepcopy(create_request)
221 update_request['new_target_iqn'] = target_iqn
222 update_request['clients'][0]['client_iqn'] = 'iqn.1994-05.com.redhat:rh7-client0'
223 response = copy.deepcopy(iscsi_target_response)
224 response['target_iqn'] = target_iqn
225 response['clients'][0]['client_iqn'] = 'iqn.1994-05.com.redhat:rh7-client0'
226 self._update_iscsi_target(create_request, update_request, response)
227
228 @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
229 def test_add_disk(self, _validate_image_mock):
230 target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw7"
231 create_request = copy.deepcopy(iscsi_target_request)
232 create_request['target_iqn'] = target_iqn
233 update_request = copy.deepcopy(create_request)
234 update_request['new_target_iqn'] = target_iqn
235 update_request['disks'].append(
236 {
237 "image": "lun3",
238 "pool": "rbd",
239 "controls": {},
240 "backstore": "user:rbd"
241 })
242 update_request['clients'][0]['luns'].append({"image": "lun3", "pool": "rbd"})
243 response = copy.deepcopy(iscsi_target_response)
244 response['target_iqn'] = target_iqn
245 response['disks'].append(
246 {
247 "image": "lun3",
248 "pool": "rbd",
249 "controls": {},
250 "backstore": "user:rbd",
251 "wwn": "64af6678-9694-4367-bacc-f8eb0baa2",
252 "lun": 2
253
254 })
255 response['clients'][0]['luns'].append({"image": "lun3", "pool": "rbd"})
256 self._update_iscsi_target(create_request, update_request, response)
257
258 @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
259 def test_change_disk_image(self, _validate_image_mock):
260 target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw8"
261 create_request = copy.deepcopy(iscsi_target_request)
262 create_request['target_iqn'] = target_iqn
263 update_request = copy.deepcopy(create_request)
264 update_request['new_target_iqn'] = target_iqn
265 update_request['disks'][0]['image'] = 'lun0'
266 update_request['clients'][0]['luns'][0]['image'] = 'lun0'
267 response = copy.deepcopy(iscsi_target_response)
268 response['target_iqn'] = target_iqn
269 response['disks'][0]['image'] = 'lun0'
270 response['clients'][0]['luns'][0]['image'] = 'lun0'
271 self._update_iscsi_target(create_request, update_request, response)
272
273 @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
274 def test_change_disk_controls(self, _validate_image_mock):
275 target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw9"
276 create_request = copy.deepcopy(iscsi_target_request)
277 create_request['target_iqn'] = target_iqn
278 update_request = copy.deepcopy(create_request)
279 update_request['new_target_iqn'] = target_iqn
280 update_request['disks'][0]['controls'] = {"qfull_timeout": 15}
281 response = copy.deepcopy(iscsi_target_response)
282 response['target_iqn'] = target_iqn
283 response['disks'][0]['controls'] = {"qfull_timeout": 15}
284 self._update_iscsi_target(create_request, update_request, response)
285
286 @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
287 def test_rename_target(self, _validate_image_mock):
288 target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw10"
289 new_target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw11"
290 create_request = copy.deepcopy(iscsi_target_request)
291 create_request['target_iqn'] = target_iqn
292 update_request = copy.deepcopy(create_request)
293 update_request['new_target_iqn'] = new_target_iqn
294 response = copy.deepcopy(iscsi_target_response)
295 response['target_iqn'] = new_target_iqn
296 self._update_iscsi_target(create_request, update_request, response)
297
298 @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
299 def test_rename_group(self, _validate_image_mock):
300 target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw12"
301 create_request = copy.deepcopy(iscsi_target_request)
302 create_request['target_iqn'] = target_iqn
303 update_request = copy.deepcopy(create_request)
304 update_request['new_target_iqn'] = target_iqn
305 update_request['groups'][0]['group_id'] = 'mygroup0'
306 response = copy.deepcopy(iscsi_target_response)
307 response['target_iqn'] = target_iqn
308 response['groups'][0]['group_id'] = 'mygroup0'
309 self._update_iscsi_target(create_request, update_request, response)
310
311 @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
312 def test_add_client_to_group(self, _validate_image_mock):
313 target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw13"
314 create_request = copy.deepcopy(iscsi_target_request)
315 create_request['target_iqn'] = target_iqn
316 update_request = copy.deepcopy(create_request)
317 update_request['new_target_iqn'] = target_iqn
318 update_request['clients'].append(
319 {
320 "luns": [],
321 "client_iqn": "iqn.1994-05.com.redhat:rh7-client3",
322 "auth": {
323 "password": None,
324 "user": None,
325 "mutual_password": None,
326 "mutual_user": None}
327 })
328 update_request['groups'][0]['members'].append('iqn.1994-05.com.redhat:rh7-client3')
329 response = copy.deepcopy(iscsi_target_response)
330 response['target_iqn'] = target_iqn
331 response['clients'].append(
332 {
333 "luns": [],
334 "client_iqn": "iqn.1994-05.com.redhat:rh7-client3",
335 "auth": {
336 "password": None,
337 "user": None,
338 "mutual_password": None,
339 "mutual_user": None},
340 "info": {
341 "alias": "",
342 "ip_address": [],
343 "state": {}
344 }
345 })
346 response['groups'][0]['members'].append('iqn.1994-05.com.redhat:rh7-client3')
347 self._update_iscsi_target(create_request, update_request, response)
348
349 @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
350 def test_remove_client_from_group(self, _validate_image_mock):
351 target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw14"
352 create_request = copy.deepcopy(iscsi_target_request)
353 create_request['target_iqn'] = target_iqn
354 update_request = copy.deepcopy(create_request)
355 update_request['new_target_iqn'] = target_iqn
356 update_request['groups'][0]['members'].remove('iqn.1994-05.com.redhat:rh7-client2')
357 response = copy.deepcopy(iscsi_target_response)
358 response['target_iqn'] = target_iqn
359 response['groups'][0]['members'].remove('iqn.1994-05.com.redhat:rh7-client2')
360 self._update_iscsi_target(create_request, update_request, response)
361
362 @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
363 def test_remove_groups(self, _validate_image_mock):
364 target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw15"
365 create_request = copy.deepcopy(iscsi_target_request)
366 create_request['target_iqn'] = target_iqn
367 update_request = copy.deepcopy(create_request)
368 update_request['new_target_iqn'] = target_iqn
369 update_request['groups'] = []
370 response = copy.deepcopy(iscsi_target_response)
371 response['target_iqn'] = target_iqn
372 response['groups'] = []
373 self._update_iscsi_target(create_request, update_request, response)
374
375 @mock.patch('dashboard.controllers.iscsi.IscsiTarget._validate_image')
376 def test_add_client_to_multiple_groups(self, _validate_image_mock):
377 target_iqn = "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw16"
378 create_request = copy.deepcopy(iscsi_target_request)
379 create_request['target_iqn'] = target_iqn
380 create_request['groups'].append(copy.deepcopy(create_request['groups'][0]))
381 create_request['groups'][1]['group_id'] = 'mygroup2'
382 self._task_post('/api/iscsi/target', create_request)
383 self.assertStatus(400)
384 self.assertJsonBody({
385 'detail': 'Each initiator can only be part of 1 group at a time',
386 'code': 'initiator_in_multiple_groups',
387 'component': 'iscsi'
388 })
389
390 def _update_iscsi_target(self, create_request, update_request, response):
391 self._task_post('/api/iscsi/target', create_request)
392 self.assertStatus(201)
393 self._task_put('/api/iscsi/target/{}'.format(create_request['target_iqn']), update_request)
394 self.assertStatus(200)
395 self._get('/api/iscsi/target/{}'.format(update_request['new_target_iqn']))
396 self.assertStatus(200)
397 self.assertJsonBody(response)
398
399
400 iscsi_target_request = {
401 "target_iqn": "iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw",
402 "portals": [
403 {"ip": "192.168.100.202", "host": "node2"},
404 {"ip": "10.0.2.15", "host": "node2"},
405 {"ip": "192.168.100.203", "host": "node3"}
406 ],
407 "disks": [
408 {"image": "lun1", "pool": "rbd", "backstore": "user:rbd",
409 "controls": {"max_data_area_mb": 128}},
410 {"image": "lun2", "pool": "rbd", "backstore": "user:rbd",
411 "controls": {"max_data_area_mb": 128}}
412 ],
413 "clients": [
414 {
415 "luns": [{"image": "lun1", "pool": "rbd"}],
416 "client_iqn": "iqn.1994-05.com.redhat:rh7-client",
417 "auth": {
418 "password": "myiscsipassword1",
419 "user": "myiscsiusername1",
420 "mutual_password": "myiscsipassword2",
421 "mutual_user": "myiscsiusername2"}
422 },
423 {
424 "luns": [],
425 "client_iqn": "iqn.1994-05.com.redhat:rh7-client2",
426 "auth": {
427 "password": "myiscsipassword3",
428 "user": "myiscsiusername3",
429 "mutual_password": "myiscsipassword4",
430 "mutual_user": "myiscsiusername4"
431 }
432 }
433 ],
434 "acl_enabled": True,
435 "auth": {
436 "password": "",
437 "user": "",
438 "mutual_password": "",
439 "mutual_user": ""},
440 "target_controls": {},
441 "groups": [
442 {
443 "group_id": "mygroup",
444 "disks": [{"pool": "rbd", "image": "lun2"}],
445 "members": ["iqn.1994-05.com.redhat:rh7-client2"]
446 }
447 ]
448 }
449
450 iscsi_target_response = {
451 'target_iqn': 'iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw',
452 'portals': [
453 {'host': 'node2', 'ip': '10.0.2.15'},
454 {'host': 'node2', 'ip': '192.168.100.202'},
455 {'host': 'node3', 'ip': '192.168.100.203'}
456 ],
457 'disks': [
458 {'pool': 'rbd', 'image': 'lun1', 'backstore': 'user:rbd',
459 'wwn': '64af6678-9694-4367-bacc-f8eb0baa0', 'lun': 0,
460 'controls': {'max_data_area_mb': 128}},
461 {'pool': 'rbd', 'image': 'lun2', 'backstore': 'user:rbd',
462 'wwn': '64af6678-9694-4367-bacc-f8eb0baa1', 'lun': 1,
463 'controls': {'max_data_area_mb': 128}}
464 ],
465 'clients': [
466 {
467 'client_iqn': 'iqn.1994-05.com.redhat:rh7-client',
468 'luns': [{'pool': 'rbd', 'image': 'lun1'}],
469 'auth': {
470 'user': 'myiscsiusername1',
471 'password': 'myiscsipassword1',
472 'mutual_password': 'myiscsipassword2',
473 'mutual_user': 'myiscsiusername2'
474 },
475 'info': {
476 'alias': '',
477 'ip_address': [],
478 'state': {}
479 }
480 },
481 {
482 'client_iqn': 'iqn.1994-05.com.redhat:rh7-client2',
483 'luns': [],
484 'auth': {
485 'user': 'myiscsiusername3',
486 'password': 'myiscsipassword3',
487 'mutual_password': 'myiscsipassword4',
488 'mutual_user': 'myiscsiusername4'
489 },
490 'info': {
491 'alias': '',
492 'ip_address': [],
493 'state': {}
494 }
495 }
496 ],
497 "acl_enabled": True,
498 "auth": {
499 "password": "",
500 "user": "",
501 "mutual_password": "",
502 "mutual_user": ""},
503 'groups': [
504 {
505 'group_id': 'mygroup',
506 'disks': [{'pool': 'rbd', 'image': 'lun2'}],
507 'members': ['iqn.1994-05.com.redhat:rh7-client2']
508 }
509 ],
510 'target_controls': {},
511 'info': {
512 'num_sessions': 0
513 }
514 }
515
516
517 class IscsiClientMock(object):
518
519 _instance = None
520
521 def __init__(self):
522 self.gateway_name = None
523 self.service_url = None
524 self.config = {
525 "created": "2019/01/17 08:57:16",
526 "discovery_auth": {
527 "username": "",
528 "password": "",
529 "password_encryption_enabled": False,
530 "mutual_username": "",
531 "mutual_password": "",
532 "mutual_password_encryption_enabled": False
533 },
534 "disks": {},
535 "epoch": 0,
536 "gateways": {},
537 "targets": {},
538 "updated": "",
539 "version": 11
540 }
541
542 @classmethod
543 def instance(cls, gateway_name=None, service_url=None):
544 cls._instance.gateway_name = gateway_name
545 cls._instance.service_url = service_url
546 # pylint: disable=unused-argument
547 return cls._instance
548
549 def ping(self):
550 return {
551 "message": "pong"
552 }
553
554 def get_settings(self):
555 return {
556 "backstores": [
557 "user:rbd"
558 ],
559 "config": {
560 "minimum_gateways": 2
561 },
562 "default_backstore": "user:rbd",
563 "required_rbd_features": {
564 "rbd": 0,
565 "user:rbd": 4,
566 },
567 "unsupported_rbd_features": {
568 "rbd": 88,
569 "user:rbd": 0,
570 },
571 "disk_default_controls": {
572 "user:rbd": {
573 "hw_max_sectors": 1024,
574 "max_data_area_mb": 8,
575 "osd_op_timeout": 30,
576 "qfull_timeout": 5
577 }
578 },
579 "target_default_controls": {
580 "cmdsn_depth": 128,
581 "dataout_timeout": 20,
582 "first_burst_length": 262144,
583 "immediate_data": "Yes",
584 "initial_r2t": "Yes",
585 "max_burst_length": 524288,
586 "max_outstanding_r2t": 1,
587 "max_recv_data_segment_length": 262144,
588 "max_xmit_data_segment_length": 262144,
589 "nopin_response_timeout": 5,
590 "nopin_timeout": 5
591 }
592 }
593
594 def get_config(self):
595 return copy.deepcopy(self.config)
596
597 def create_target(self, target_iqn, target_controls):
598 self.config['targets'][target_iqn] = {
599 "clients": {},
600 "acl_enabled": True,
601 "auth": {
602 "username": "",
603 "password": "",
604 "password_encryption_enabled": False,
605 "mutual_username": "",
606 "mutual_password": "",
607 "mutual_password_encryption_enabled": False
608 },
609 "controls": target_controls,
610 "created": "2019/01/17 09:22:34",
611 "disks": {},
612 "groups": {},
613 "portals": {}
614 }
615
616 def create_gateway(self, target_iqn, gateway_name, ip_addresses):
617 target_config = self.config['targets'][target_iqn]
618 if 'ip_list' not in target_config:
619 target_config['ip_list'] = []
620 target_config['ip_list'] += ip_addresses
621 target_config['portals'][gateway_name] = {
622 "portal_ip_addresses": ip_addresses
623 }
624
625 def delete_gateway(self, target_iqn, gateway_name):
626 target_config = self.config['targets'][target_iqn]
627 portal_config = target_config['portals'][gateway_name]
628 for ip in portal_config['portal_ip_addresses']:
629 target_config['ip_list'].remove(ip)
630 target_config['portals'].pop(gateway_name)
631
632 def create_disk(self, pool, image, backstore, wwn):
633 if wwn is None:
634 wwn = '64af6678-9694-4367-bacc-f8eb0baa' + str(len(self.config['disks']))
635 image_id = '{}/{}'.format(pool, image)
636 self.config['disks'][image_id] = {
637 "pool": pool,
638 "image": image,
639 "backstore": backstore,
640 "controls": {},
641 "wwn": wwn
642 }
643
644 def create_target_lun(self, target_iqn, image_id, lun):
645 target_config = self.config['targets'][target_iqn]
646 if lun is None:
647 lun = len(target_config['disks'])
648 target_config['disks'][image_id] = {
649 "lun_id": lun
650 }
651 self.config['disks'][image_id]['owner'] = list(target_config['portals'].keys())[0]
652
653 def reconfigure_disk(self, pool, image, controls):
654 image_id = '{}/{}'.format(pool, image)
655 settings = self.get_settings()
656 backstore = self.config['disks'][image_id]['backstore']
657 disk_default_controls = settings['disk_default_controls'][backstore]
658 new_controls = {}
659 for control_k, control_v in controls.items():
660 if control_v != disk_default_controls[control_k]:
661 new_controls[control_k] = control_v
662 self.config['disks'][image_id]['controls'] = new_controls
663
664 def create_client(self, target_iqn, client_iqn):
665 target_config = self.config['targets'][target_iqn]
666 target_config['clients'][client_iqn] = {
667 "auth": {
668 "username": "",
669 "password": "",
670 "password_encryption_enabled": False,
671 "mutual_username": "",
672 "mutual_password": "",
673 "mutual_password_encryption_enabled": False
674 },
675 "group_name": "",
676 "luns": {}
677 }
678
679 def create_client_lun(self, target_iqn, client_iqn, image_id):
680 target_config = self.config['targets'][target_iqn]
681 target_config['clients'][client_iqn]['luns'][image_id] = {}
682
683 def delete_client_lun(self, target_iqn, client_iqn, image_id):
684 target_config = self.config['targets'][target_iqn]
685 del target_config['clients'][client_iqn]['luns'][image_id]
686
687 def create_client_auth(self, target_iqn, client_iqn, user, password, m_user, m_password):
688 target_config = self.config['targets'][target_iqn]
689 target_config['clients'][client_iqn]['auth']['username'] = user
690 target_config['clients'][client_iqn]['auth']['password'] = password
691 target_config['clients'][client_iqn]['auth']['mutual_username'] = m_user
692 target_config['clients'][client_iqn]['auth']['mutual_password'] = m_password
693
694 def create_group(self, target_iqn, group_name, members, image_ids):
695 target_config = self.config['targets'][target_iqn]
696 target_config['groups'][group_name] = {
697 "disks": {},
698 "members": []
699 }
700 for image_id in image_ids:
701 target_config['groups'][group_name]['disks'][image_id] = {}
702 target_config['groups'][group_name]['members'] = members
703
704 def delete_group(self, target_iqn, group_name):
705 target_config = self.config['targets'][target_iqn]
706 del target_config['groups'][group_name]
707
708 def delete_client(self, target_iqn, client_iqn):
709 target_config = self.config['targets'][target_iqn]
710 del target_config['clients'][client_iqn]
711
712 def delete_target_lun(self, target_iqn, image_id):
713 target_config = self.config['targets'][target_iqn]
714 target_config['disks'].pop(image_id)
715 del self.config['disks'][image_id]['owner']
716
717 def delete_disk(self, pool, image):
718 image_id = '{}/{}'.format(pool, image)
719 del self.config['disks'][image_id]
720
721 def delete_target(self, target_iqn):
722 del self.config['targets'][target_iqn]
723
724 def get_ip_addresses(self):
725 ips = {
726 'node1': ['192.168.100.201'],
727 'node2': ['192.168.100.202', '10.0.2.15'],
728 'node3': ['192.168.100.203']
729 }
730 return {'data': ips[self.gateway_name]}
731
732 def get_hostname(self):
733 hostnames = {
734 'https://admin:admin@10.17.5.1:5001': 'node1',
735 'https://admin:admin@10.17.5.2:5001': 'node2',
736 'https://admin:admin@10.17.5.3:5001': 'node3'
737 }
738 if self.service_url not in hostnames:
739 raise RequestException('No route to host')
740 return {'data': hostnames[self.service_url]}
741
742 def update_discoveryauth(self, user, password, mutual_user, mutual_password):
743 self.config['discovery_auth']['username'] = user
744 self.config['discovery_auth']['password'] = password
745 self.config['discovery_auth']['mutual_username'] = mutual_user
746 self.config['discovery_auth']['mutual_password'] = mutual_password
747
748 def update_targetacl(self, target_iqn, action):
749 self.config['targets'][target_iqn]['acl_enabled'] = (action == 'enable_acl')
750
751 def update_targetauth(self, target_iqn, user, password, mutual_user, mutual_password):
752 target_config = self.config['targets'][target_iqn]
753 target_config['auth']['username'] = user
754 target_config['auth']['password'] = password
755 target_config['auth']['mutual_username'] = mutual_user
756 target_config['auth']['mutual_password'] = mutual_password
757
758 def get_targetinfo(self, target_iqn):
759 # pylint: disable=unused-argument
760 return {
761 'num_sessions': 0
762 }
763
764 def get_clientinfo(self, target_iqn, client_iqn):
765 # pylint: disable=unused-argument
766 return {
767 'alias': '',
768 'ip_address': [],
769 'state': {}
770 }