Coverage for manila/tests/share/drivers/netapp/dataontap/client/test_client_cmode_rest.py: 99%

3229 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2026-02-18 22:19 +0000

1# Copyright (c) 2023 NetApp, Inc. All rights reserved. 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); you may 

4# not use this file except in compliance with the License. You may obtain 

5# a copy of the License at 

6# 

7# http://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 

11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 

12# License for the specific language governing permissions and limitations 

13# under the License. 

14 

15import copy 

16import math 

17import time 

18from unittest import mock 

19 

20import ddt 

21from oslo_log import log 

22from oslo_utils import netutils 

23from oslo_utils import units 

24 

25from manila import exception 

26from manila.share.drivers.netapp.dataontap.client import client_cmode 

27from manila.share.drivers.netapp.dataontap.client import client_cmode_rest 

28from manila.share.drivers.netapp.dataontap.client import rest_api as netapp_api 

29from manila.share.drivers.netapp import utils as netapp_utils 

30from manila import test 

31from manila.tests.share.drivers.netapp.dataontap.client import fakes as fake 

32from manila import utils 

33 

34 

35@ddt.ddt 

36class NetAppRestCmodeClientTestCase(test.TestCase): 

37 

38 def setUp(self): 

39 super(NetAppRestCmodeClientTestCase, self).setUp() 

40 

41 # Mock loggers as themselves to allow logger arg validation 

42 mock_logger = log.getLogger('mock_logger') 

43 self.mock_object(client_cmode_rest.LOG, 

44 'error', 

45 mock.Mock(side_effect=mock_logger.error)) 

46 self.mock_object(client_cmode_rest.LOG, 

47 'warning', 

48 mock.Mock(side_effect=mock_logger.warning)) 

49 self.mock_object(client_cmode_rest.LOG, 

50 'debug', 

51 mock.Mock(side_effect=mock_logger.debug)) 

52 self.mock_object(client_cmode.NetAppCmodeClient, 

53 'get_ontapi_version', 

54 mock.Mock(return_value=(1, 20))) 

55 # store the original reference so we can call it later in 

56 # test_get_ontap_version 

57 self.original_get_ontap_version = ( 

58 client_cmode_rest.NetAppRestClient.get_ontap_version) 

59 self.mock_object(client_cmode_rest.NetAppRestClient, 

60 'get_ontap_version', 

61 mock.Mock(return_value={ 

62 'version-tuple': (9, 12, 1), 

63 'version': fake.VERSION, 

64 })) 

65 self.original_check_for_cluster_credentials = ( 

66 client_cmode_rest.NetAppRestClient._check_for_cluster_credentials) 

67 self.mock_object(client_cmode_rest.NetAppRestClient, 

68 '_check_for_cluster_credentials', 

69 mock.Mock(return_value=True)) 

70 self.mock_object(client_cmode.NetAppCmodeClient, 

71 'get_system_version', 

72 mock.Mock(return_value={ 

73 'version-tuple': (9, 10, 1), 

74 'version': fake.VERSION, 

75 })) 

76 

77 self.client = client_cmode_rest.NetAppRestClient( 

78 **fake.CONNECTION_INFO) 

79 self.client.connection = mock.MagicMock() 

80 

81 self.sleep_patcher = mock.patch.object(time, 'sleep', lambda s: None) 

82 self.sleep_patcher.start() 

83 self.addCleanup(self.sleep_patcher.stop) 

84 

85 def _mock_api_error(self, code='fake', message='fake'): 

86 return mock.Mock( 

87 side_effect=netapp_api.api.NaApiError(code=code, message=message)) 

88 

89 def test_send_request(self): 

90 expected = 'fake_response' 

91 mock_get_records = self.mock_object( 

92 self.client, 'get_records', 

93 mock.Mock(return_value=expected)) 

94 

95 res = self.client.send_request( 

96 fake.FAKE_ACTION_URL, 'get', 

97 body=fake.FAKE_HTTP_BODY, 

98 query=fake.FAKE_HTTP_QUERY, enable_tunneling=False) 

99 

100 self.assertEqual(expected, res) 

101 mock_get_records.assert_called_once_with( 

102 fake.FAKE_ACTION_URL, 

103 fake.FAKE_HTTP_QUERY, False, 10000) 

104 

105 def test_send_request_post(self): 

106 expected = (201, 'fake_response') 

107 mock_invoke = self.mock_object( 

108 self.client.connection, 'invoke_successfully', 

109 mock.Mock(return_value=expected)) 

110 

111 res = self.client.send_request( 

112 fake.FAKE_ACTION_URL, 'post', 

113 body=fake.FAKE_HTTP_BODY, 

114 query=fake.FAKE_HTTP_QUERY, enable_tunneling=False) 

115 

116 self.assertEqual(expected[1], res) 

117 mock_invoke.assert_called_once_with( 

118 fake.FAKE_ACTION_URL, 'post', 

119 body=fake.FAKE_HTTP_BODY, 

120 query=fake.FAKE_HTTP_QUERY, enable_tunneling=False) 

121 

122 def test_send_request_wait(self): 

123 expected = (202, fake.JOB_RESPONSE_REST) 

124 mock_invoke = self.mock_object( 

125 self.client.connection, 'invoke_successfully', 

126 mock.Mock(return_value=expected)) 

127 

128 mock_wait = self.mock_object( 

129 self.client, '_wait_job_result', 

130 mock.Mock(return_value=expected[1])) 

131 

132 res = self.client.send_request( 

133 fake.FAKE_ACTION_URL, 'post', 

134 body=fake.FAKE_HTTP_BODY, 

135 query=fake.FAKE_HTTP_QUERY, enable_tunneling=False) 

136 

137 self.assertEqual(expected[1], res) 

138 mock_invoke.assert_called_once_with( 

139 fake.FAKE_ACTION_URL, 'post', 

140 body=fake.FAKE_HTTP_BODY, 

141 query=fake.FAKE_HTTP_QUERY, enable_tunneling=False) 

142 mock_wait.assert_called_once_with( 

143 expected[1]['job']['_links']['self']['href'][4:]) 

144 

145 @ddt.data(True, False) 

146 def test_get_records(self, enable_tunneling): 

147 api_responses = [ 

148 (200, fake.VOLUME_GET_ITER_RESPONSE_REST_PAGE), 

149 (200, fake.VOLUME_GET_ITER_RESPONSE_REST_PAGE), 

150 (200, fake.VOLUME_GET_ITER_RESPONSE_REST_LAST_PAGE), 

151 ] 

152 

153 mock_invoke = self.mock_object( 

154 self.client.connection, 'invoke_successfully', 

155 mock.Mock(side_effect=copy.deepcopy(api_responses))) 

156 

157 query = { 

158 'fields': 'name' 

159 } 

160 

161 result = self.client.get_records( 

162 '/storage/volumes/', query=query, 

163 enable_tunneling=enable_tunneling, 

164 max_page_length=10) 

165 

166 num_records = result['num_records'] 

167 self.assertEqual(28, num_records) 

168 self.assertEqual(28, len(result['records'])) 

169 

170 expected_records = [] 

171 expected_records.extend(api_responses[0][1]['records']) 

172 expected_records.extend(api_responses[1][1]['records']) 

173 expected_records.extend(api_responses[2][1]['records']) 

174 

175 self.assertEqual(expected_records, result['records']) 

176 

177 next_tag = result.get('next') 

178 self.assertIsNone(next_tag) 

179 

180 expected_query = copy.deepcopy(query) 

181 expected_query['max_records'] = 10 

182 

183 next_url_1 = api_responses[0][1]['_links']['next']['href'][4:] 

184 next_url_2 = api_responses[1][1]['_links']['next']['href'][4:] 

185 

186 mock_invoke.assert_has_calls([ 

187 mock.call('/storage/volumes/', 'get', query=expected_query, 

188 enable_tunneling=enable_tunneling), 

189 mock.call(next_url_1, 'get', query=None, 

190 enable_tunneling=enable_tunneling), 

191 mock.call(next_url_2, 'get', query=None, 

192 enable_tunneling=enable_tunneling), 

193 ]) 

194 

195 def test_get_records_single_page(self): 

196 

197 api_response = ( 

198 200, fake.VOLUME_GET_ITER_RESPONSE_REST_LAST_PAGE) 

199 mock_invoke = self.mock_object(self.client.connection, 

200 'invoke_successfully', 

201 mock.Mock(return_value=api_response)) 

202 

203 query = { 

204 'fields': 'name' 

205 } 

206 

207 result = self.client.get_records( 

208 '/storage/volumes/', query=query, max_page_length=10) 

209 

210 num_records = result['num_records'] 

211 self.assertEqual(8, num_records) 

212 self.assertEqual(8, len(result['records'])) 

213 

214 next_tag = result.get('next') 

215 self.assertIsNone(next_tag) 

216 

217 args = copy.deepcopy(query) 

218 args['max_records'] = 10 

219 

220 mock_invoke.assert_has_calls([ 

221 mock.call('/storage/volumes/', 'get', query=args, 

222 enable_tunneling=True), 

223 ]) 

224 

225 def test_get_records_not_found(self): 

226 

227 api_response = (200, fake.NO_RECORDS_RESPONSE_REST) 

228 mock_invoke = self.mock_object(self.client.connection, 

229 'invoke_successfully', 

230 mock.Mock(return_value=api_response)) 

231 

232 result = self.client.get_records('/storage/volumes/') 

233 

234 num_records = result['num_records'] 

235 self.assertEqual(0, num_records) 

236 self.assertEqual(0, len(result['records'])) 

237 

238 args = { 

239 'max_records': client_cmode_rest.DEFAULT_MAX_PAGE_LENGTH 

240 } 

241 

242 mock_invoke.assert_has_calls([ 

243 mock.call('/storage/volumes/', 'get', query=args, 

244 enable_tunneling=True), 

245 ]) 

246 

247 def test_get_records_timeout(self): 

248 # To simulate timeout, max_records is 30, but the API returns less 

249 # records and fill the 'next url' pointing to the next page. 

250 max_records = 30 

251 api_responses = [ 

252 (200, fake.VOLUME_GET_ITER_RESPONSE_REST_PAGE), 

253 (200, fake.VOLUME_GET_ITER_RESPONSE_REST_PAGE), 

254 (200, fake.VOLUME_GET_ITER_RESPONSE_REST_LAST_PAGE), 

255 ] 

256 

257 mock_invoke = self.mock_object( 

258 self.client.connection, 'invoke_successfully', 

259 mock.Mock(side_effect=copy.deepcopy(api_responses))) 

260 

261 query = { 

262 'fields': 'name' 

263 } 

264 

265 result = self.client.get_records( 

266 '/storage/volumes/', query=query, max_page_length=max_records) 

267 

268 num_records = result['num_records'] 

269 self.assertEqual(28, num_records) 

270 self.assertEqual(28, len(result['records'])) 

271 

272 expected_records = [] 

273 expected_records.extend(api_responses[0][1]['records']) 

274 expected_records.extend(api_responses[1][1]['records']) 

275 expected_records.extend(api_responses[2][1]['records']) 

276 

277 self.assertEqual(expected_records, result['records']) 

278 

279 next_tag = result.get('next', None) 

280 self.assertIsNone(next_tag) 

281 

282 args1 = copy.deepcopy(query) 

283 args1['max_records'] = max_records 

284 

285 next_url_1 = api_responses[0][1]['_links']['next']['href'][4:] 

286 next_url_2 = api_responses[1][1]['_links']['next']['href'][4:] 

287 

288 mock_invoke.assert_has_calls([ 

289 mock.call('/storage/volumes/', 'get', query=args1, 

290 enable_tunneling=True), 

291 mock.call(next_url_1, 'get', query=None, enable_tunneling=True), 

292 mock.call(next_url_2, 'get', query=None, enable_tunneling=True), 

293 ]) 

294 

295 def test__getattr__(self): 

296 # NOTE(nahimsouza): get_ontapi_version is implemented only in ZAPI 

297 # client, therefore, it will call __getattr__ 

298 self.client.get_ontapi_version() 

299 

300 @ddt.data(True, False) 

301 def test_get_ontap_version(self, cached): 

302 self.client.get_ontap_version = self.original_get_ontap_version 

303 api_response = { 

304 'records': [ 

305 { 

306 'version': { 

307 'generation': 9, 

308 'major': 11, 

309 'minor': 1, 

310 'full': 'NetApp Release 9.11.1' 

311 } 

312 }] 

313 

314 } 

315 return_mock = { 

316 'version': 'NetApp Release 9.11.1', 

317 'version-tuple': (9, 11, 1) 

318 } 

319 mock_connect = self.mock_object(self.client.connection, 

320 'get_ontap_version', 

321 mock.Mock(return_value=return_mock)) 

322 mock_send_request = self.mock_object( 

323 self.client, 

324 'send_request', 

325 mock.Mock(return_value=api_response)) 

326 

327 result = self.client.get_ontap_version(self=self.client, cached=cached) 

328 

329 if cached: 

330 mock_connect.assert_called_once() 

331 else: 

332 mock_send_request.assert_called_once_with( 

333 '/cluster/nodes', 'get', query={'fields': 'version'}, 

334 enable_tunneling=False) 

335 

336 self.assertEqual(return_mock, result) 

337 

338 def test__wait_job_result(self): 

339 response = fake.JOB_SUCCESSFUL_REST 

340 self.mock_object(self.client, 

341 'send_request', 

342 mock.Mock(return_value=response)) 

343 result = self.client._wait_job_result( 

344 f'/cluster/jobs/{fake.FAKE_UUID}') 

345 self.assertEqual(response, result) 

346 

347 def test__wait_job_result_failure(self): 

348 response = fake.JOB_ERROR_REST 

349 self.mock_object(self.client, 

350 'send_request', 

351 mock.Mock(return_value=response)) 

352 self.assertRaises(netapp_utils.NetAppDriverException, 

353 self.client._wait_job_result, 

354 f'/cluster/jobs/{fake.FAKE_UUID}') 

355 

356 def test__wait_job_result_timeout(self): 

357 response = fake.JOB_RUNNING_REST 

358 self.client.async_rest_timeout = 2 

359 self.mock_object(self.client, 

360 'send_request', 

361 mock.Mock(return_value=response)) 

362 self.assertRaises(netapp_utils.NetAppDriverException, 

363 self.client._wait_job_result, 

364 f'/cluster/jobs/{fake.FAKE_UUID}') 

365 

366 def test_list_cluster_nodes(self): 

367 """Get all available cluster nodes.""" 

368 

369 return_value = fake.FAKE_GET_CLUSTER_NODE_VERSION_REST 

370 

371 self.mock_object(self.client, 'send_request', 

372 mock.Mock(return_value=return_value)) 

373 test_result = self.client.list_cluster_nodes() 

374 

375 self.client.send_request.assert_called_once_with( 

376 '/cluster/nodes', 'get' 

377 ) 

378 

379 nodes = return_value.get('records', []) 

380 

381 expected_result = [node['name'] for node in nodes] 

382 

383 self.assertEqual(expected_result, test_result) 

384 

385 @ddt.data(True, False) 

386 def test_check_for_cluster_credentials(self, cluster_creds): 

387 self.client._have_cluster_creds = cluster_creds 

388 

389 result = self.client.check_for_cluster_credentials() 

390 

391 self.assertEqual(cluster_creds, result) 

392 

393 def test__check_for_cluster_credentials(self): 

394 self.client._check_for_cluster_credentials = ( 

395 self.original_check_for_cluster_credentials) 

396 api_response = fake.FAKE_GET_CLUSTER_NODE_VERSION_REST 

397 self.mock_object(self.client, 

398 'list_cluster_nodes', 

399 mock.Mock(return_value=api_response)) 

400 

401 result = self.client._check_for_cluster_credentials(self=self.client) 

402 

403 self.assertTrue(result) 

404 

405 def test__check_for_cluster_credentials_not_cluster(self): 

406 self.client._check_for_cluster_credentials = ( 

407 self.original_check_for_cluster_credentials) 

408 self.mock_object(self.client, 'list_cluster_nodes', 

409 self._mock_api_error( 

410 netapp_api.EREST_NOT_AUTHORIZED)) 

411 

412 result = self.client._check_for_cluster_credentials(self=self.client) 

413 

414 self.assertFalse(result) 

415 

416 def test__check_for_cluster_credentials_api_error(self): 

417 self.client._check_for_cluster_credentials = ( 

418 self.original_check_for_cluster_credentials) 

419 self.mock_object(self.client, 'list_cluster_nodes', 

420 self._mock_api_error()) 

421 

422 self.assertRaises(netapp_api.api.NaApiError, 

423 self.client._check_for_cluster_credentials, 

424 self.client) 

425 

426 def test_get_licenses(self): 

427 return_value = fake.FAKE_GET_LICENSES_REST 

428 

429 self.mock_object(self.client, 'send_request', 

430 mock.Mock(return_value=return_value)) 

431 

432 test_result = self.client.get_licenses() 

433 

434 expected_result = sorted( 

435 [license['name'] for license in return_value.get('records', [])]) 

436 

437 self.assertEqual(test_result, expected_result) 

438 

439 @ddt.data(((9, 1, 0), fake.VERSION_NO_DARE), ((8, 3, 2), fake.VERSION)) 

440 @ddt.unpack 

441 def test_is_nve_supported_unsupported_release_or_platform(self, gen, ver): 

442 system_version = {'version-tuple': gen, 'version': ver} 

443 self.mock_object(self.client, 

444 'get_ontap_version', 

445 mock.Mock(return_value=system_version)) 

446 self.mock_object(self.client, 

447 '_get_security_key_manager_nve_support', 

448 mock.Mock(return_value=False)) 

449 self.mock_object(self.client, 

450 'list_cluster_nodes', 

451 mock.Mock(return_value=fake.NODE_NAMES)) 

452 

453 result = self.client.is_nve_supported() 

454 

455 self.assertFalse(result) 

456 

457 def test_is_nve_supported_valid_platform_and_supported_release(self): 

458 

459 system_version = { 

460 'version-tuple': (9, 1, 0), 

461 'version': fake.VERSION, 

462 } 

463 self.mock_object(self.client, 

464 'get_ontap_version', 

465 mock.Mock(return_value=system_version)) 

466 self.mock_object(self.client, 

467 '_get_security_key_manager_nve_support', 

468 mock.Mock(return_value=True)) 

469 self.mock_object(self.client, 

470 'list_cluster_nodes', 

471 mock.Mock(return_value=fake.NODE_NAMES)) 

472 

473 result = self.client.is_nve_supported() 

474 self.assertTrue(result) 

475 

476 def test_is_nve_supported_key_manager_not_enabled(self): 

477 

478 system_version = { 

479 'version-tuple': (9, 1, 0), 

480 'version': fake.VERSION, 

481 } 

482 self.mock_object(self.client, 

483 'get_ontap_version', 

484 mock.Mock(return_value=system_version)) 

485 self.mock_object(self.client, 

486 '_get_security_key_manager_nve_support', 

487 mock.Mock(return_value=False)) 

488 self.mock_object(self.client, 

489 'list_cluster_nodes', 

490 mock.Mock(return_value=fake.NODE_NAMES)) 

491 

492 result = self.client.is_nve_supported() 

493 

494 self.assertFalse(result) 

495 

496 def test__get_volume_by_args(self): 

497 response = fake.VOLUME_LIST_SIMPLE_RESPONSE_REST 

498 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

499 

500 self.mock_object(self.client, 'send_request', 

501 mock.Mock(return_value=response)) 

502 

503 result = self.client._get_volume_by_args( 

504 vol_name=fake.VOLUME_NAMES[0], 

505 aggregate_name=fake.SHARE_AGGREGATE_NAME, 

506 vol_path=fake.VOLUME_JUNCTION_PATH, 

507 vserver=fake.VSERVER_NAME, 

508 fields='name,style,svm.name,svm.uuid') 

509 

510 query = { 

511 'name': fake.VOLUME_NAMES[0], 

512 'aggregates.name': fake.SHARE_AGGREGATE_NAME, 

513 'nas.path': fake.VOLUME_JUNCTION_PATH, 

514 'svm.name': fake.VSERVER_NAME, 

515 'style': 'flex*', # Match both 'flexvol' and 'flexgroup' 

516 'error_state.is_inconsistent': 'false', 

517 'fields': 'name,style,svm.name,svm.uuid' 

518 } 

519 self.client.send_request.assert_called_once_with( 

520 '/storage/volumes/', 'get', query=query) 

521 

522 self.assertEqual(volume, result) 

523 

524 def test_restore_snapshot(self): 

525 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

526 uuid = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST["uuid"] 

527 body = { 

528 'restore_to.snapshot.name': fake.SNAPSHOT_NAME 

529 } 

530 

531 self.mock_object(self.client, '_get_volume_by_args', 

532 mock.Mock(return_value=volume)) 

533 self.mock_object(self.client, 'send_request') 

534 

535 self.client.restore_snapshot(fake.VOLUME_NAMES[0], fake.SNAPSHOT_NAME) 

536 

537 self.client._get_volume_by_args.assert_called_once_with( 

538 vol_name=fake.VOLUME_NAMES[0]) 

539 self.client.send_request.assert_called_once_with( 

540 f'/storage/volumes/{uuid}', 'patch', body=body) 

541 

542 @ddt.data(0, 10) 

543 def test__has_records(self, num_records): 

544 result = self.client._has_records({'num_records': num_records}) 

545 

546 if not num_records or num_records == 0: 

547 self.assertFalse(result) 

548 else: 

549 self.assertTrue(result) 

550 

551 def test_vserver_exists(self): 

552 query = { 

553 'name': fake.VSERVER_NAME 

554 } 

555 return_value = fake.SVMS_LIST_SIMPLE_RESPONSE_REST 

556 

557 self.mock_object(self.client, 'send_request', 

558 mock.Mock(return_value=return_value)) 

559 

560 self.mock_object(self.client, '_has_records', 

561 mock.Mock(return_value=True)) 

562 

563 result = self.client.vserver_exists(fake.VSERVER_NAME) 

564 

565 self.client.send_request.assert_called_once_with( 

566 '/svm/svms', 'get', query=query, enable_tunneling=False) 

567 self.client._has_records.assert_called_once_with( 

568 fake.SVMS_LIST_SIMPLE_RESPONSE_REST) 

569 

570 self.assertEqual(result, True) 

571 

572 def test_get_aggregate(self): 

573 

574 response = fake.AGGR_GET_ITER_RESPONSE_REST['records'] 

575 self.mock_object(self.client, 

576 '_get_aggregates', 

577 mock.Mock(return_value=response)) 

578 

579 result = self.client.get_aggregate(fake.SHARE_AGGREGATE_NAME) 

580 

581 fields = ('name,block_storage.primary.raid_type,' 

582 'block_storage.storage_type,snaplock_type') 

583 

584 self.client._get_aggregates.assert_has_calls([ 

585 mock.call( 

586 aggregate_names=[fake.SHARE_AGGREGATE_NAME], 

587 fields=fields)]) 

588 

589 expected = { 

590 'name': fake.SHARE_AGGREGATE_NAME, 

591 'raid-type': response[0]['block_storage']['primary']['raid_type'], 

592 'is-hybrid': 

593 response[0]['block_storage']['storage_type'] == 'hybrid', 

594 'snaplock-type': response[0]['snaplock_type'], 

595 'is-snaplock': response[0]['is_snaplock'] 

596 } 

597 

598 self.assertEqual(expected, result) 

599 

600 def test_get_cluster_aggregate_capacities(self): 

601 

602 response = fake.AGGR_GET_ITER_RESPONSE_REST['records'] 

603 self.mock_object(self.client, 

604 '_get_aggregates', 

605 mock.Mock(return_value=response)) 

606 

607 result = self.client.get_cluster_aggregate_capacities( 

608 response) 

609 

610 fields = 'name,space' 

611 self.client._get_aggregates.assert_has_calls([ 

612 mock.call( 

613 aggregate_names=response, 

614 fields=fields)]) 

615 expected = { 

616 response[0]['name']: { 

617 'available': 568692293632, 

618 'total': 1271819509760, 

619 'used': 703127216128, 

620 }, 

621 response[1]['name']: { 

622 'available': 727211110400, 

623 'total': 1426876227584, 

624 'used': 699665117184, 

625 } 

626 } 

627 

628 self.assertDictEqual(expected, result) 

629 

630 def test_list_non_root_aggregates(self): 

631 return_value = fake.FAKE_AGGR_LIST 

632 self.mock_object(self.client, 'send_request', 

633 mock.Mock(return_value=return_value)) 

634 

635 result = self.client.list_non_root_aggregates() 

636 

637 expected = [fake.SHARE_AGGREGATE_NAMES_LIST[0]] 

638 self.assertEqual(expected, result) 

639 

640 def test__get_aggregates(self): 

641 

642 api_response = fake.AGGR_GET_ITER_RESPONSE_REST 

643 self.mock_object(self.client, 'send_request', 

644 mock.Mock(return_value=api_response)) 

645 result = self.client._get_aggregates( 

646 aggregate_names=fake.SHARE_AGGREGATE_NAMES) 

647 expected = fake.AGGR_GET_ITER_RESPONSE_REST['records'] 

648 self.assertEqual(expected, result) 

649 

650 def test_get_node_for_aggregate(self): 

651 

652 response = fake.AGGR_GET_ITER_RESPONSE_REST['records'] 

653 self.mock_object(self.client, 

654 '_get_aggregates', 

655 mock.Mock(return_value=response)) 

656 result = self.client.get_node_for_aggregate(fake.SHARE_AGGREGATE_NAME) 

657 expected = 'fake_home_node_name' 

658 self.assertEqual(expected, result) 

659 

660 @ddt.data({'types': {'FCAL'}, 'expected': ['FCAL']}, 

661 {'types': {'SATA', 'SSD'}, 'expected': ['SATA', 'SSD']}, ) 

662 @ddt.unpack 

663 def test_get_aggregate_disk_types(self, types, expected): 

664 

665 mock_get_aggregate_disk_types = self.mock_object( 

666 self.client, '_get_aggregate_disk_types', 

667 mock.Mock(return_value=types)) 

668 

669 result = self.client.get_aggregate_disk_types( 

670 fake.SHARE_AGGREGATE_NAME) 

671 

672 self.assertEqual(sorted(expected), sorted(result)) 

673 mock_get_aggregate_disk_types.assert_called_once_with( 

674 fake.SHARE_AGGREGATE_NAME) 

675 

676 def test_volume_exists(self): 

677 query = { 

678 'name': fake.VOLUME_NAMES[0] 

679 } 

680 return_value = fake.VOLUME_LIST_SIMPLE_RESPONSE_REST 

681 

682 self.mock_object(self.client, 'send_request', 

683 mock.Mock(return_value=return_value)) 

684 

685 self.mock_object(self.client, '_has_records', 

686 mock.Mock(return_value=True)) 

687 

688 result = self.client.volume_exists(fake.VOLUME_NAMES[0]) 

689 

690 self.client.send_request.assert_called_once_with( 

691 '/storage/volumes', 'get', query=query) 

692 self.client._has_records.assert_called_once_with( 

693 fake.VOLUME_LIST_SIMPLE_RESPONSE_REST) 

694 self.assertEqual(result, True) 

695 

696 def test_list_vserver_aggregates(self): 

697 

698 self.mock_object(self.client, 

699 'get_vserver_aggregate_capacities', 

700 mock.Mock(return_value=fake.VSERVER_AGGREGATES)) 

701 

702 result = self.client.list_vserver_aggregates() 

703 

704 self.assertListEqual(list(fake.VSERVER_AGGREGATES.keys()), result) 

705 

706 def test_list_vserver_aggregates_none_found(self): 

707 

708 self.mock_object(self.client, 

709 'get_vserver_aggregate_capacities', 

710 mock.Mock(return_value={})) 

711 

712 result = self.client.list_vserver_aggregates() 

713 

714 self.assertListEqual([], result) 

715 

716 def test_get_vserver_aggregate_capacities(self): 

717 

718 response = fake.FAKE_SVM_AGGREGATES 

719 self.mock_object(self.client, 

720 'send_request', 

721 mock.Mock(return_value=response)) 

722 

723 result = self.client.get_vserver_aggregate_capacities( 

724 fake.SHARE_AGGREGATE_NAMES_LIST) 

725 

726 query = { 

727 'fields': 'name,aggregates.name,aggregates.available_size' 

728 } 

729 

730 self.client.send_request.assert_has_calls([ 

731 mock.call('/svm/svms', 'get', query=query)]) 

732 

733 expected = { 

734 response['records'][0].get('aggregates')[0].get('name'): { 

735 'available': 568692293632, 

736 }, 

737 response['records'][0].get('aggregates')[1].get('name'): { 

738 'available': 727211110400, 

739 } 

740 } 

741 

742 self.assertDictEqual(expected, result) 

743 

744 def test_get_vserver_aggregate_capacities_partial_request(self): 

745 response = fake.FAKE_SVM_AGGREGATES 

746 size = response['records'][0].get('aggregates')[0].get( 

747 'available_size') 

748 self.mock_object(self.client, 

749 'send_request', 

750 mock.Mock(return_value=response)) 

751 

752 result = self.client.get_vserver_aggregate_capacities( 

753 [fake.SHARE_AGGREGATE_NAMES[0]]) 

754 

755 expected = { 

756 fake.SHARE_AGGREGATE_NAMES[0]: { 

757 'available': size 

758 } 

759 } 

760 self.assertDictEqual(expected, result) 

761 

762 def test_get_vserver_aggregate_capacities_aggregate_not_found(self): 

763 self.mock_object(self.client, 

764 'send_request', 

765 mock.Mock(return_value=fake.FAKE_SVM_AGGR_EMPTY)) 

766 

767 result = self.client.get_vserver_aggregate_capacities( 

768 ['other-aggr']) 

769 

770 self.assertDictEqual({}, result) 

771 self.assertEqual(1, client_cmode_rest.LOG.warning.call_count) 

772 

773 def test_get_vserver_aggregate_capacities_none_requested(self): 

774 result = self.client.get_vserver_aggregate_capacities([]) 

775 self.assertEqual({}, result) 

776 

777 @ddt.data((None, None), 

778 (fake.QOS_MAX_THROUGHPUT, None), 

779 (fake.QOS_MAX_THROUGHPUT_IOPS, None), 

780 (None, None), 

781 (None, fake.QOS_MIN_THROUGHPUT), 

782 (None, fake.QOS_MIN_THROUGHPUT_IOPS), 

783 (fake.QOS_MAX_THROUGHPUT_IOPS, fake.QOS_MIN_THROUGHPUT_IOPS)) 

784 @ddt.unpack 

785 def test_qos_policy_group_create(self, max_throughput, min_throughput): 

786 return_value = fake.GENERIC_JOB_POST_RESPONSE 

787 body = { 

788 'name': fake.QOS_POLICY_GROUP_NAME, 

789 'svm.name': fake.VSERVER_NAME, 

790 } 

791 if max_throughput: 

792 if 'iops' in max_throughput: 

793 qos = fake.QOS_MAX_THROUGHPUT_IOPS_NO_UNIT 

794 body['fixed.max_throughput_iops'] = qos 

795 else: 

796 qos = math.ceil(fake.QOS_MAX_THROUGHPUT_NO_UNIT / units.Mi) 

797 body['fixed.max_throughput_mbps'] = qos 

798 

799 if min_throughput: 

800 if 'iops' in min_throughput: 

801 qos = fake.QOS_MIN_THROUGHPUT_IOPS_NO_UNIT 

802 body['fixed.min_throughput_iops'] = qos 

803 else: 

804 qos = math.ceil(fake.QOS_MIN_THROUGHPUT_NO_UNIT / units.Mi) 

805 body['fixed.min_throughput_mbps'] = qos 

806 

807 self.mock_object(self.client, 'send_request', 

808 mock.Mock(return_value=return_value)) 

809 

810 result = self.client.qos_policy_group_create( 

811 fake.QOS_POLICY_GROUP_NAME, fake.VSERVER_NAME, 

812 max_throughput, min_throughput) 

813 

814 self.client.send_request.assert_called_once_with( 

815 '/storage/qos/policies', 'post', body=body) 

816 self.assertEqual(result, return_value) 

817 

818 @ddt.data(None, ['CIFS', 'NFS']) 

819 def test_get_network_interfaces(self, protocols): 

820 return_value = fake.GENERIC_NETWORK_INTERFACES_GET_REPONSE 

821 

822 lif_info = return_value.get('records', [])[0] 

823 

824 fake_lif = [{ 

825 'uuid': lif_info['uuid'], 

826 'administrative-status': 'up' if lif_info['enabled'] else 'down', 

827 'address': lif_info['ip']['address'], 

828 'home-node': lif_info['location']['home_node']['name'], 

829 'home-port': lif_info['location']['home_port']['name'], 

830 'interface-name': lif_info['name'], 

831 'netmask': lif_info['ip']['netmask'], 

832 'role': lif_info['services'], 

833 'vserver': lif_info['svm']['name'], 

834 }] 

835 

836 if protocols: 

837 query = { 

838 'services': 'data_cifs,data_nfs', 

839 'fields': 'ip.address,location.home_node.name,' 

840 'location.home_port.name,ip.netmask,' 

841 'services,svm.name,enabled' 

842 } 

843 else: 

844 query = { 

845 'fields': 'ip.address,location.home_node.name,' 

846 'location.home_port.name,ip.netmask,' 

847 'services,svm.name,enabled' 

848 } 

849 

850 self.mock_object(self.client, 'send_request', 

851 mock.Mock(return_value=return_value)) 

852 

853 result = self.client.get_network_interfaces(protocols) 

854 

855 self.client.send_request.assert_called_once_with( 

856 '/network/ip/interfaces', 'get', query=query) 

857 

858 self.assertEqual(result, fake_lif) 

859 

860 def test_clear_nfs_export_policy_for_volume(self): 

861 

862 mock_set_nfs_export_policy_for_volume = self.mock_object( 

863 self.client, 'set_nfs_export_policy_for_volume') 

864 

865 self.client.clear_nfs_export_policy_for_volume(fake.SHARE_NAME) 

866 

867 mock_set_nfs_export_policy_for_volume.assert_called_once_with( 

868 fake.SHARE_NAME, 'default') 

869 

870 def test_set_nfs_export_policy_for_volume(self): 

871 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

872 query = {'name': volume['name']} 

873 

874 body = { 

875 'nas.export_policy.name': fake.EXPORT_POLICY_NAME 

876 } 

877 

878 self.mock_object(self.client, 'send_request') 

879 

880 self.client.set_nfs_export_policy_for_volume( 

881 fake.VOLUME_NAMES[0], fake.EXPORT_POLICY_NAME) 

882 

883 self.client.send_request.assert_called_once_with( 

884 '/storage/volumes/', 'patch', 

885 query=query, body=body) 

886 

887 def test_create_nfs_export_policy(self): 

888 

889 body = {'name': fake.EXPORT_POLICY_NAME} 

890 

891 self.mock_object(self.client, 'send_request') 

892 

893 self.client.create_nfs_export_policy(fake.EXPORT_POLICY_NAME) 

894 

895 self.client.send_request.assert_called_once_with( 

896 '/protocols/nfs/export-policies', 'post', body=body) 

897 

898 def test_soft_delete_nfs_export_policy(self): 

899 self.mock_object(self.client, 'delete_nfs_export_policy', 

900 mock.Mock(side_effect=self._mock_api_error())) 

901 self.mock_object(self.client, 'rename_nfs_export_policy') 

902 

903 self.client.soft_delete_nfs_export_policy(fake.EXPORT_POLICY_NAME) 

904 

905 self.client.rename_nfs_export_policy.assert_has_calls([ 

906 mock.call( 

907 fake.EXPORT_POLICY_NAME, 

908 'deleted_manila_' + fake.EXPORT_POLICY_NAME)]) 

909 

910 def test_rename_nfs_export_policy(self): 

911 return_uuid = fake.GENERIC_EXPORT_POLICY_RESPONSE_AND_VOLUMES 

912 uuid = "fake-policy-uuid" 

913 

914 self.mock_object(self.client, 'send_request', 

915 mock.Mock(return_value=return_uuid)) 

916 self.mock_object(self.client, '_has_records', 

917 mock.Mock(return_value=True)) 

918 

919 body = { 

920 'name': 'fake_new_policy_name' 

921 } 

922 

923 self.client.rename_nfs_export_policy(fake.EXPORT_POLICY_NAME, 

924 'fake_new_policy_name') 

925 

926 self.client._has_records.assert_called_once_with(return_uuid) 

927 

928 self.client.send_request.assert_has_calls([ 

929 mock.call('/protocols/nfs/export-policies', 'get', 

930 query={'name': fake.EXPORT_POLICY_NAME}), 

931 mock.call(f'/protocols/nfs/export-policies/{uuid}', 'patch', 

932 body=body)]) 

933 

934 def test_get_volume_junction_path(self): 

935 return_value = fake.GENERIC_EXPORT_POLICY_RESPONSE_AND_VOLUMES 

936 

937 query = { 

938 'name': fake.SHARE_NAME, 

939 'fields': 'nas.path' 

940 } 

941 

942 self.mock_object(self.client, 'send_request', 

943 mock.Mock(return_value=return_value)) 

944 

945 result = self.client.get_volume_junction_path(fake.SHARE_NAME) 

946 

947 expected = fake.VOLUME_JUNCTION_PATH 

948 

949 self.client.send_request.assert_called_once_with('/storage/volumes/', 

950 'get', query=query) 

951 

952 self.assertEqual(result, expected) 

953 

954 def test_get_volume_snapshot_attributes(self): 

955 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

956 return_value = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

957 

958 self.mock_object(self.client, '_get_volume_by_args', 

959 mock.Mock(return_value=volume)) 

960 self.mock_object(self.client, 'send_request', 

961 mock.Mock(return_value=return_value)) 

962 

963 expected = { 

964 'snapdir-access-enabled': 'false', 

965 'snapshot-policy': 'daily', 

966 } 

967 

968 result = self.client.get_volume_snapshot_attributes(fake.SHARE_NAME) 

969 self.assertEqual(result, expected) 

970 

971 def test_get_volume(self): 

972 return_value = fake.GENERIC_EXPORT_POLICY_RESPONSE_AND_VOLUMES 

973 

974 fake_volume = return_value.get('records', [])[0] 

975 

976 expected = { 

977 'aggregate': fake.SHARE_AGGREGATE_NAME, 

978 'aggr-list': [fake.SHARE_AGGREGATE_NAME], 

979 'junction-path': fake_volume.get('nas', {}).get('path', ''), 

980 'name': fake_volume.get('name', ''), 

981 'owning-vserver-name': fake_volume.get('svm', {}).get('name', ''), 

982 'type': fake_volume.get('type', ''), 

983 'style': fake_volume.get('style', ''), 

984 'size': fake_volume.get('space', {}).get('size', ''), 

985 'size-used': fake_volume.get('space', {}).get('used', ''), 

986 'qos-policy-group-name': fake_volume.get('qos', {}) 

987 .get('policy', {}) 

988 .get('name'), 

989 'style-extended': fake_volume.get('style', ''), 

990 'snaplock-type': fake_volume.get('snaplock', {}).get('type', '') 

991 } 

992 

993 self.mock_object(self.client, 'send_request', 

994 mock.Mock(return_value=return_value)) 

995 self.mock_object(self.client, '_has_records', 

996 mock.Mock(return_value=True)) 

997 

998 result = self.client.get_volume(fake.SHARE_NAME) 

999 

1000 self.client._has_records.assert_called_once_with(return_value) 

1001 self.assertEqual(result, expected) 

1002 

1003 def test_cifs_share_exists(self): 

1004 return_value = fake.VOLUME_LIST_SIMPLE_RESPONSE_REST 

1005 self.mock_object(self.client, 'send_request', 

1006 mock.Mock(return_value=return_value)) 

1007 self.mock_object(self.client, '_has_records', 

1008 mock.Mock(return_value=True)) 

1009 

1010 result = self.client.cifs_share_exists(fake.SHARE_NAME) 

1011 

1012 query = { 

1013 'name': fake.SHARE_NAME, 

1014 'path': fake.VOLUME_JUNCTION_PATH 

1015 } 

1016 self.client._has_records.assert_called_once_with(return_value) 

1017 self.client.send_request.assert_called_once_with( 

1018 '/protocols/cifs/shares', 'get', query=query) 

1019 self.assertTrue(result) 

1020 

1021 def test_create_cifs_share(self): 

1022 

1023 body = { 

1024 'name': fake.SHARE_NAME, 

1025 'path': fake.VOLUME_JUNCTION_PATH, 

1026 'svm.name': self.client.vserver, 

1027 } 

1028 

1029 self.mock_object(self.client, 'send_request') 

1030 

1031 self.client.create_cifs_share(fake.SHARE_NAME, f'/{fake.SHARE_NAME}') 

1032 

1033 self.client.send_request.assert_called_once_with( 

1034 '/protocols/cifs/shares', 'post', body=body) 

1035 

1036 @ddt.data(None, 'fake_security_style') 

1037 def test_set_volume_security_style(self, security_style): 

1038 

1039 self.mock_object(self.client, 'send_request') 

1040 

1041 if security_style: 

1042 self.client.set_volume_security_style(fake.VOLUME_NAMES[0], 

1043 security_style) 

1044 else: 

1045 self.client.set_volume_security_style(fake.VOLUME_NAMES[0]) 

1046 

1047 query = { 

1048 'name': fake.VOLUME_NAMES[0], 

1049 } 

1050 body = { 

1051 'nas.security_style': security_style if security_style else 'unix' 

1052 } 

1053 self.client.send_request.assert_called_once_with( 

1054 '/storage/volumes', 'patch', body=body, query=query) 

1055 

1056 def test_remove_cifs_share_access(self): 

1057 return_uuid = fake.GENERIC_EXPORT_POLICY_RESPONSE_AND_VOLUMES 

1058 self.mock_object(self.client, 'send_request', 

1059 mock.Mock(return_value=return_uuid)) 

1060 

1061 self.client.remove_cifs_share_access(fake.SHARE_NAME, fake.USER_NAME) 

1062 

1063 fake_uuid = "fake_uuid" 

1064 self.client.send_request.assert_has_calls([ 

1065 mock.call('/protocols/cifs/shares', 'get', 

1066 query={'name': fake.SHARE_NAME, 'fields': 'svm.uuid'}), 

1067 mock.call(f'/protocols/cifs/shares/{fake_uuid}/{fake.SHARE_NAME}/' 

1068 f'acls/{fake.USER_NAME}/windows', 'delete')]) 

1069 

1070 def test_create_volume(self): 

1071 

1072 mock_create_volume_async = self.mock_object(self.client, 

1073 'create_volume_async') 

1074 mock_update = self.mock_object( 

1075 self.client, 'update_volume_efficiency_attributes') 

1076 mock_max_files = self.mock_object(self.client, 'set_volume_max_files') 

1077 options = {'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME} 

1078 self.client.create_volume(fake.SHARE_AGGREGATE_NAME, 

1079 fake.VOLUME_NAMES[0], fake.SHARE_SIZE, 

1080 max_files=1, snaplock_type="enterprise", 

1081 **options) 

1082 mock_create_volume_async.assert_called_once_with( 

1083 [fake.SHARE_AGGREGATE_NAME], fake.VOLUME_NAMES[0], fake.SHARE_SIZE, 

1084 is_flexgroup=False, thin_provisioned=False, snapshot_policy=None, 

1085 language=None, max_files=1, snapshot_reserve=None, 

1086 volume_type='rw', qos_policy_group=None, encrypt=False, 

1087 adaptive_qos_policy_group=None, mount_point_name=None, 

1088 efficiency_policy=fake.VOLUME_EFFICIENCY_POLICY_NAME, 

1089 snaplock_type="enterprise", 

1090 ) 

1091 mock_update.assert_called_once_with( 

1092 fake.VOLUME_NAMES[0], False, False, 

1093 efficiency_policy=fake.VOLUME_EFFICIENCY_POLICY_NAME) 

1094 mock_max_files.assert_called_once_with(fake.VOLUME_NAMES[0], 1) 

1095 

1096 def test_create_volume_async(self): 

1097 body = { 

1098 'size': 1073741824, 

1099 'name': fake.VOLUME_NAMES[0], 

1100 'style': 'flexvol', 

1101 'aggregates': [{'name': fake.SHARE_AGGREGATE_NAME}] 

1102 } 

1103 

1104 return_value = fake.GENERIC_JOB_POST_RESPONSE 

1105 

1106 expected_result = { 

1107 'jobid': fake.GENERIC_JOB_POST_RESPONSE['job']['uuid'], 

1108 'error-code': '', 

1109 'error-message': '', 

1110 } 

1111 

1112 self.mock_object(self.client, '_get_create_volume_body', 

1113 mock.Mock(return_value={})) 

1114 self.mock_object(self.client, 'send_request', 

1115 mock.Mock(return_value=return_value)) 

1116 

1117 result = self.client.create_volume_async([ 

1118 fake.SHARE_AGGREGATE_NAME], fake.VOLUME_NAMES[0], 1, 

1119 is_flexgroup=False) 

1120 

1121 self.client._get_create_volume_body.assert_called_once_with( 

1122 fake.VOLUME_NAMES[0], False, None, None, None, 'rw', None, False, 

1123 None, None, None) 

1124 self.client.send_request.assert_called_once_with( 

1125 '/storage/volumes', 'post', body=body, wait_on_accepted=True) 

1126 self.assertEqual(expected_result, result) 

1127 

1128 def test_get_volume_efficiency_status(self): 

1129 return_value = fake.VOLUME_LIST_SIMPLE_RESPONSE_REST 

1130 

1131 query = { 

1132 'efficiency.volume_path': '/vol/%s' % fake.VOLUME_NAMES[0], 

1133 'fields': 'efficiency.state,efficiency.compression' 

1134 } 

1135 

1136 expected_result = { 

1137 'dedupe': True, 

1138 'compression': True 

1139 } 

1140 

1141 self.mock_object(self.client, 'send_request', 

1142 mock.Mock(return_value=return_value)) 

1143 

1144 result = self.client.get_volume_efficiency_status(fake.VOLUME_NAMES[0]) 

1145 

1146 self.client.send_request.assert_called_once_with( 

1147 '/storage/volumes', 'get', query=query) 

1148 self.assertEqual(expected_result, result) 

1149 

1150 def test_enable_dedupe_async(self): 

1151 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1152 uuid = volume["uuid"] 

1153 return_value = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1154 

1155 self.mock_object(self.client, '_get_volume_by_args', 

1156 mock.Mock(return_value=volume)) 

1157 self.mock_object(self.client, 'send_request', 

1158 mock.Mock(return_value=return_value)) 

1159 

1160 body = { 

1161 'efficiency': {'dedupe': 'background'} 

1162 } 

1163 

1164 self.client.enable_dedupe_async(fake.VOLUME_NAMES[0]) 

1165 

1166 self.client.send_request.assert_called_once_with( 

1167 f'/storage/volumes/{uuid}', 'patch', body=body) 

1168 self.client._get_volume_by_args.assert_called_once_with( 

1169 vol_name=fake.VOLUME_NAMES[0]) 

1170 

1171 def test_disable_dedupe_async(self): 

1172 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1173 uuid = volume["uuid"] 

1174 return_value = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1175 

1176 self.mock_object(self.client, '_get_volume_by_args', 

1177 mock.Mock(return_value=volume)) 

1178 self.mock_object(self.client, 'send_request', 

1179 mock.Mock(return_value=return_value)) 

1180 

1181 body = { 

1182 'efficiency': {'dedupe': 'none'} 

1183 } 

1184 

1185 self.client.disable_dedupe_async(fake.VOLUME_NAMES[0]) 

1186 

1187 self.client.send_request.assert_called_once_with( 

1188 f'/storage/volumes/{uuid}', 'patch', body=body) 

1189 self.client._get_volume_by_args.assert_called_once_with( 

1190 vol_name=fake.VOLUME_NAMES[0]) 

1191 

1192 def test_enable_compression_async(self): 

1193 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1194 uuid = volume["uuid"] 

1195 return_value = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1196 

1197 self.mock_object(self.client, '_get_volume_by_args', 

1198 mock.Mock(return_value=volume)) 

1199 self.mock_object(self.client, 'send_request', 

1200 mock.Mock(return_value=return_value)) 

1201 

1202 body = { 

1203 'efficiency': {'compression': 'background'} 

1204 } 

1205 

1206 self.client.enable_compression_async(fake.VOLUME_NAMES[0]) 

1207 

1208 self.client.send_request.assert_called_once_with( 

1209 f'/storage/volumes/{uuid}', 'patch', body=body) 

1210 self.client._get_volume_by_args.assert_called_once_with( 

1211 vol_name=fake.VOLUME_NAMES[0]) 

1212 

1213 def test_disable_compression_async(self): 

1214 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1215 uuid = volume["uuid"] 

1216 return_value = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1217 

1218 self.mock_object(self.client, '_get_volume_by_args', 

1219 mock.Mock(return_value=volume)) 

1220 self.mock_object(self.client, 'send_request', 

1221 mock.Mock(return_value=return_value)) 

1222 

1223 body = { 

1224 'efficiency': {'compression': 'none'} 

1225 } 

1226 

1227 self.client.disable_compression_async(fake.VOLUME_NAMES[0]) 

1228 

1229 self.client.send_request.assert_called_once_with( 

1230 f'/storage/volumes/{uuid}', 'patch', body=body) 

1231 self.client._get_volume_by_args.assert_called_once_with( 

1232 vol_name=fake.VOLUME_NAMES[0]) 

1233 

1234 def test_apply_volume_efficiency_policy(self): 

1235 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1236 uuid = volume["uuid"] 

1237 return_value = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1238 

1239 self.mock_object(self.client, '_get_volume_by_args', 

1240 mock.Mock(return_value=volume)) 

1241 self.mock_object(self.client, 'send_request', 

1242 mock.Mock(return_value=return_value)) 

1243 

1244 body = { 

1245 'efficiency': {'policy': fake.VOLUME_EFFICIENCY_POLICY_NAME} 

1246 } 

1247 

1248 self.client.apply_volume_efficiency_policy( 

1249 fake.VOLUME_NAMES[0], 

1250 efficiency_policy=fake.VOLUME_EFFICIENCY_POLICY_NAME 

1251 ) 

1252 

1253 self.client.send_request.assert_called_once_with( 

1254 f'/storage/volumes/{uuid}', 'patch', body=body) 

1255 self.client._get_volume_by_args.assert_called_once_with( 

1256 vol_name=fake.VOLUME_NAMES[0]) 

1257 

1258 def test_apply_volume_efficiency_none_policy(self): 

1259 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1260 return_value = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1261 

1262 self.mock_object(self.client, '_get_volume_by_args', 

1263 mock.Mock(return_value=volume)) 

1264 self.mock_object(self.client, 'send_request', 

1265 mock.Mock(return_value=return_value)) 

1266 

1267 self.client.apply_volume_efficiency_policy( 

1268 fake.VOLUME_NAMES[0], 

1269 efficiency_policy=None 

1270 ) 

1271 

1272 self.client._get_volume_by_args.assert_not_called() 

1273 

1274 def test_set_volume_max_files(self): 

1275 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1276 uuid = volume["uuid"] 

1277 return_value = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1278 fake_max_files = '40000' 

1279 

1280 self.mock_object(self.client, '_get_volume_by_args', 

1281 mock.Mock(return_value=volume)) 

1282 self.mock_object(self.client, 'send_request', 

1283 mock.Mock(return_value=return_value)) 

1284 

1285 body = { 

1286 'files.maximum': int(fake_max_files) 

1287 } 

1288 

1289 self.client.set_volume_max_files(fake.VOLUME_NAMES[0], fake_max_files) 

1290 

1291 self.client.send_request.assert_called_once_with( 

1292 f'/storage/volumes/{uuid}', 'patch', body=body) 

1293 self.client._get_volume_by_args.assert_called_once_with( 

1294 vol_name=fake.VOLUME_NAMES[0]) 

1295 

1296 def test_set_volume_max_files_retry_allocated(self): 

1297 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1298 uuid = volume["uuid"] 

1299 fake_max_files = '40000' 

1300 fake_used_files = '30000' 

1301 alloc_files = {'maximum': fake_max_files, 'used': fake_used_files} 

1302 side_effect = [ 

1303 netapp_api.api.NaApiError( 

1304 code=netapp_api.EREST_CANNOT_MODITY_SPECIFIED_FIELD), None] 

1305 

1306 self.mock_object(self.client, '_get_volume_by_args', 

1307 mock.Mock(return_value=volume)) 

1308 mock_sr = self.mock_object(self.client, 'send_request', 

1309 mock.Mock(side_effect=side_effect)) 

1310 self.mock_object(self.client, 'get_volume_allocated_files', 

1311 mock.Mock(return_value=alloc_files)) 

1312 

1313 body_before = { 

1314 'files.maximum': int(fake_max_files) 

1315 } 

1316 body_retry = { 

1317 'files.maximum': int(fake_used_files) 

1318 } 

1319 

1320 self.client.set_volume_max_files( 

1321 fake.VOLUME_NAMES[0], fake_max_files, retry_allocated=True) 

1322 

1323 mock_sr.assert_has_calls([ 

1324 mock.call(f'/storage/volumes/{uuid}', 'patch', body=body_before), 

1325 mock.call(f'/storage/volumes/{uuid}', 'patch', body=body_retry), 

1326 ]) 

1327 self.client._get_volume_by_args.assert_called() 

1328 

1329 def test_set_volume_snapdir_access(self): 

1330 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1331 uuid = volume["uuid"] 

1332 return_value = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1333 fake_hide_snapdir = 'fake-snapdir' 

1334 

1335 self.mock_object(self.client, '_get_volume_by_args', 

1336 mock.Mock(return_value=volume)) 

1337 self.mock_object(self.client, 'send_request', 

1338 mock.Mock(return_value=return_value)) 

1339 

1340 body = { 

1341 'snapshot_directory_access_enabled': str( 

1342 not fake_hide_snapdir).lower() 

1343 } 

1344 

1345 self.client.set_volume_snapdir_access(fake.VOLUME_NAMES[0], 

1346 fake_hide_snapdir) 

1347 

1348 self.client.send_request.assert_called_once_with( 

1349 f'/storage/volumes/{uuid}', 'patch', body=body) 

1350 self.client._get_volume_by_args.assert_called_once_with( 

1351 vol_name=fake.VOLUME_NAMES[0]) 

1352 

1353 def test_get_fpolicy_scopes(self): 

1354 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1355 uuid = volume["uuid"] 

1356 return_value = fake.GENERIC_FPOLICY_RESPONSE 

1357 

1358 query = { 

1359 'name': fake.FPOLICY_POLICY_NAME, 

1360 'scope.include_shares': fake.VOLUME_NAMES[0], 

1361 'scope.include_extension': fake.FPOLICY_EXT_TO_INCLUDE, 

1362 'scope.exclude_extension': fake.FPOLICY_EXT_TO_EXCLUDE 

1363 } 

1364 

1365 expected_result = [ 

1366 { 

1367 'policy-name': fake.FPOLICY_POLICY_NAME, 

1368 'file-extensions-to-include': fake.FPOLICY_EXT_TO_INCLUDE_LIST, 

1369 'file-extensions-to-exclude': fake.FPOLICY_EXT_TO_EXCLUDE_LIST, 

1370 'shares-to-include': [fake.VOLUME_NAMES[0]], 

1371 } 

1372 ] 

1373 

1374 self.mock_object(self.client, '_get_volume_by_args', 

1375 mock.Mock(return_value=volume)) 

1376 self.mock_object(self.client, '_has_records', 

1377 mock.Mock(return_value=True)) 

1378 self.mock_object(self.client, 'send_request', 

1379 mock.Mock(return_value=return_value)) 

1380 

1381 result = self.client.get_fpolicy_scopes( 

1382 fake.VOLUME_NAMES[0], fake.FPOLICY_POLICY_NAME, 

1383 fake.FPOLICY_EXT_TO_INCLUDE_LIST, fake.FPOLICY_EXT_TO_EXCLUDE_LIST, 

1384 [fake.VOLUME_NAMES[0]]) 

1385 

1386 self.client._get_volume_by_args.assert_called_once_with( 

1387 vol_name=fake.VOLUME_NAMES[0]) 

1388 self.client.send_request.assert_called_once_with( 

1389 f'/protocols/fpolicy/{uuid}/policies', 'get', query=query) 

1390 

1391 self.assertEqual(expected_result, result) 

1392 

1393 def test_get_fpolicy_policies_status(self): 

1394 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1395 uuid = volume["uuid"] 

1396 return_value = fake.GENERIC_FPOLICY_RESPONSE 

1397 

1398 query = { 

1399 'name': fake.FPOLICY_POLICY_NAME, 

1400 'enabled': 'true' 

1401 } 

1402 

1403 expected_result = [ 

1404 { 

1405 'policy-name': fake.FPOLICY_POLICY_NAME, 

1406 'status': True, 

1407 'sequence-number': 1 

1408 } 

1409 ] 

1410 

1411 self.mock_object(self.client, '_get_volume_by_args', 

1412 mock.Mock(return_value=volume)) 

1413 self.mock_object(self.client, '_has_records', 

1414 mock.Mock(return_value=True)) 

1415 self.mock_object(self.client, 'send_request', 

1416 mock.Mock(return_value=return_value)) 

1417 

1418 result = self.client.get_fpolicy_policies_status( 

1419 fake.VOLUME_NAMES[0], fake.FPOLICY_POLICY_NAME, 'true') 

1420 

1421 self.client._get_volume_by_args.assert_called_once_with( 

1422 vol_name=fake.VOLUME_NAMES[0]) 

1423 self.client.send_request.assert_called_once_with( 

1424 f'/protocols/fpolicy/{uuid}/policies', 'get', query=query) 

1425 

1426 self.assertEqual(expected_result, result) 

1427 

1428 def test_get_fpolicy_policies(self): 

1429 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1430 uuid = volume["uuid"] 

1431 return_value = fake.GENERIC_FPOLICY_RESPONSE 

1432 

1433 query = { 

1434 'name': fake.FPOLICY_POLICY_NAME, 

1435 'engine.name': 'native', 

1436 'events': fake.FPOLICY_EVENT_NAME 

1437 } 

1438 

1439 expected_result = [ 

1440 { 

1441 'policy-name': fake.FPOLICY_POLICY_NAME, 

1442 'engine-name': 'native', 

1443 'events': [fake.FPOLICY_EVENT_NAME] 

1444 } 

1445 ] 

1446 

1447 self.mock_object(self.client, '_get_volume_by_args', 

1448 mock.Mock(return_value=volume)) 

1449 self.mock_object(self.client, '_has_records', 

1450 mock.Mock(return_value=True)) 

1451 self.mock_object(self.client, 'send_request', 

1452 mock.Mock(return_value=return_value)) 

1453 

1454 result = self.client.get_fpolicy_policies( 

1455 fake.VOLUME_NAMES[0], fake.FPOLICY_POLICY_NAME, 'native', 

1456 [fake.FPOLICY_EVENT_NAME]) 

1457 

1458 self.client._get_volume_by_args.assert_called_once_with( 

1459 vol_name=fake.VOLUME_NAMES[0]) 

1460 self.client.send_request.assert_called_once_with( 

1461 f'/protocols/fpolicy/{uuid}/policies', 'get', query=query) 

1462 

1463 self.assertEqual(expected_result, result) 

1464 

1465 def test_get_fpolicy_events(self): 

1466 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1467 uuid = volume["uuid"] 

1468 return_value = fake.GENERIC_FPOLICY_EVENTS_RESPONSE 

1469 

1470 query = { 

1471 'name': fake.FPOLICY_EVENT_NAME, 

1472 'protocol': fake.FPOLICY_PROTOCOL, 

1473 'fields': 'file_operations.create,file_operations.write,' 

1474 'file_operations.rename' 

1475 } 

1476 

1477 expected_result = [ 

1478 { 

1479 'event-name': fake.FPOLICY_EVENT_NAME, 

1480 'protocol': fake.FPOLICY_PROTOCOL, 

1481 'file-operations': fake.FPOLICY_FILE_OPERATIONS_LIST 

1482 } 

1483 ] 

1484 

1485 self.mock_object(self.client, '_get_volume_by_args', 

1486 mock.Mock(return_value=volume)) 

1487 self.mock_object(self.client, '_has_records', 

1488 mock.Mock(return_value=True)) 

1489 self.mock_object(self.client, 'send_request', 

1490 mock.Mock(return_value=return_value)) 

1491 

1492 result = self.client.get_fpolicy_events( 

1493 fake.VOLUME_NAMES[0], fake.FPOLICY_EVENT_NAME, 

1494 fake.FPOLICY_PROTOCOL, fake.FPOLICY_FILE_OPERATIONS_LIST) 

1495 

1496 self.client._get_volume_by_args.assert_called_once_with( 

1497 vol_name=fake.VOLUME_NAMES[0]) 

1498 self.client.send_request.assert_called_once_with( 

1499 f'/protocols/fpolicy/{uuid}/events', 'get', query=query) 

1500 

1501 self.assertEqual(expected_result, result) 

1502 

1503 def test_create_fpolicy_event(self): 

1504 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1505 uuid = volume["uuid"] 

1506 

1507 body = { 

1508 'name': fake.FPOLICY_EVENT_NAME, 

1509 'protocol': fake.FPOLICY_PROTOCOL, 

1510 'file_operations.create': 'true', 

1511 'file_operations.write': 'true', 

1512 'file_operations.rename': 'true' 

1513 } 

1514 

1515 self.mock_object(self.client, '_get_volume_by_args', 

1516 mock.Mock(return_value=volume)) 

1517 self.mock_object(self.client, 'send_request') 

1518 

1519 self.client.create_fpolicy_event( 

1520 fake.VOLUME_NAMES[0], fake.FPOLICY_EVENT_NAME, 

1521 fake.FPOLICY_PROTOCOL, fake.FPOLICY_FILE_OPERATIONS_LIST) 

1522 

1523 self.client._get_volume_by_args.assert_called_once_with( 

1524 vol_name=fake.VOLUME_NAMES[0]) 

1525 self.client.send_request.assert_called_once_with( 

1526 f'/protocols/fpolicy/{uuid}/events', 'post', body=body) 

1527 

1528 def test_delete_fpolicy_policy(self): 

1529 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1530 uuid = volume["uuid"] 

1531 

1532 self.mock_object(self.client, '_get_volume_by_args', 

1533 mock.Mock(return_value=volume)) 

1534 self.mock_object(self.client, 'send_request') 

1535 

1536 self.client.delete_fpolicy_policy( 

1537 fake.VOLUME_NAMES[0], fake.FPOLICY_POLICY_NAME) 

1538 

1539 self.client._get_volume_by_args.assert_called_once_with( 

1540 vol_name=fake.VOLUME_NAMES[0]) 

1541 self.client.send_request.assert_called_once_with( 

1542 f'/protocols/fpolicy/{uuid}/policies/{fake.FPOLICY_POLICY_NAME}', 

1543 'delete') 

1544 

1545 def test_delete_fpolicy_event(self): 

1546 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1547 uuid = volume["uuid"] 

1548 

1549 self.mock_object(self.client, '_get_volume_by_args', 

1550 mock.Mock(return_value=volume)) 

1551 self.mock_object(self.client, 'send_request') 

1552 

1553 self.client.delete_fpolicy_event( 

1554 fake.VOLUME_NAMES[0], fake.FPOLICY_EVENT_NAME) 

1555 

1556 self.client._get_volume_by_args.assert_called_once_with( 

1557 vol_name=fake.VOLUME_NAMES[0]) 

1558 self.client.send_request.assert_called_once_with( 

1559 f'/protocols/fpolicy/{uuid}/events/{fake.FPOLICY_EVENT_NAME}', 

1560 'delete') 

1561 

1562 def test_enable_fpolicy_policy(self): 

1563 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1564 uuid = volume["uuid"] 

1565 

1566 body = { 

1567 'priority': 1, 

1568 } 

1569 

1570 self.mock_object(self.client, '_get_volume_by_args', 

1571 mock.Mock(return_value=volume)) 

1572 self.mock_object(self.client, 'send_request') 

1573 

1574 self.client.enable_fpolicy_policy( 

1575 fake.VOLUME_NAMES[0], fake.FPOLICY_POLICY_NAME, 1) 

1576 

1577 self.client._get_volume_by_args.assert_called_once_with( 

1578 vol_name=fake.VOLUME_NAMES[0]) 

1579 self.client.send_request.assert_called_once_with( 

1580 f'/protocols/fpolicy/{uuid}/policies/{fake.FPOLICY_POLICY_NAME}', 

1581 'patch', body=body) 

1582 

1583 def test_create_fpolicy_policy_with_scope(self): 

1584 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1585 uuid = volume["uuid"] 

1586 

1587 body = { 

1588 'name': fake.FPOLICY_POLICY_NAME, 

1589 'events.name': fake.FPOLICY_EVENT_NAME, 

1590 'engine.name': fake.FPOLICY_ENGINE, 

1591 'scope.include_shares': [fake.VOLUME_NAMES[0]], 

1592 'scope.include_extension': fake.FPOLICY_EXT_TO_INCLUDE_LIST, 

1593 'scope.exclude_extension': fake.FPOLICY_EXT_TO_EXCLUDE_LIST 

1594 } 

1595 

1596 self.mock_object(self.client, '_get_volume_by_args', 

1597 mock.Mock(return_value=volume)) 

1598 self.mock_object(self.client, 'send_request') 

1599 

1600 self.client.create_fpolicy_policy_with_scope( 

1601 fake.FPOLICY_POLICY_NAME, fake.VOLUME_NAMES[0], 

1602 fake.FPOLICY_EVENT_NAME, fake.FPOLICY_ENGINE, 

1603 extensions_to_include=fake.FPOLICY_EXT_TO_INCLUDE, 

1604 extensions_to_exclude=fake.FPOLICY_EXT_TO_EXCLUDE) 

1605 

1606 self.client._get_volume_by_args.assert_called_once_with( 

1607 vol_name=fake.VOLUME_NAMES[0]) 

1608 self.client.send_request.assert_called_once_with( 

1609 f'/protocols/fpolicy/{uuid}/policies', 'post', body=body) 

1610 

1611 def test_delete_nfs_export_policy(self): 

1612 policy_name = 'fake_policy_name' 

1613 

1614 query = { 

1615 'name': policy_name, 

1616 } 

1617 

1618 api_response = fake.EXPORT_POLICY_REST 

1619 

1620 mock_sr = self.mock_object(self.client, 'send_request', mock.Mock( 

1621 return_value=api_response)) 

1622 

1623 if not api_response.get('records'): 1623 ↛ 1624line 1623 didn't jump to line 1624 because the condition on line 1623 was never true

1624 return 

1625 id = api_response.get('records')[0]['id'] 

1626 

1627 self.client.delete_nfs_export_policy(policy_name) 

1628 

1629 mock_sr.assert_has_calls([ 

1630 mock.call('/protocols/nfs/export-policies', 'get', 

1631 query=query), 

1632 mock.call(f'/protocols/nfs/export-policies/{id}', 'delete'), 

1633 ]) 

1634 

1635 def test_delete_volume(self): 

1636 """Deletes a volume.""" 

1637 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1638 

1639 self.mock_object(self.client, '_get_volume_by_args', 

1640 mock.Mock(return_value=volume)) 

1641 

1642 mock_sr = self.mock_object(self.client, 'send_request') 

1643 # Get volume UUID. 

1644 uuid = volume['uuid'] 

1645 

1646 self.client.delete_volume('fake_volume_name') 

1647 

1648 mock_sr.assert_called_once_with(f'/storage/volumes/{uuid}', 'delete') 

1649 

1650 def test_soft_delete_volume_error(self): 

1651 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1652 

1653 self.mock_object(self.client, '_get_volume_by_args', 

1654 mock.Mock(return_value=volume)) 

1655 self.mock_object( 

1656 self.client, 'send_request', 

1657 self._mock_api_error( 

1658 code=netapp_api.EREST_VOLDEL_NOT_ALLOW_BY_CLONE)) 

1659 mock_rename = self.mock_object(self.client, 'rename_volume') 

1660 

1661 # Get volume UUID. 

1662 uuid = volume['uuid'] 

1663 

1664 self.client.soft_delete_volume('fake_volume_name') 

1665 

1666 self.client.send_request.assert_called_once_with( 

1667 f'/storage/volumes/{uuid}', 'delete') 

1668 mock_rename.assert_called_once_with( 

1669 'fake_volume_name', 

1670 client_cmode_rest.DELETED_PREFIX + 'fake_volume_name') 

1671 

1672 def test_soft_delete_volume_error_return_errors(self): 

1673 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1674 

1675 self.mock_object(self.client, '_get_volume_by_args', 

1676 mock.Mock(return_value=volume)) 

1677 self.mock_object( 

1678 self.client, 'send_request', 

1679 self._mock_api_error( 

1680 code=netapp_api.EREST_VOLDEL_NOT_ALLOW_BY_CLONE)) 

1681 

1682 ret = self.client.soft_delete_volume('fake_volume_name', 

1683 return_errors=True) 

1684 self.assertEqual('del_not_allow_by_clone', ret) 

1685 

1686 def test_prune_deleted_volumes_no_clones_online(self): 

1687 api_response = [fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST] 

1688 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1689 self.mock_object(self.client, 'get_deleted_volumes_to_prune', 

1690 mock.Mock(return_value=api_response)) 

1691 self.mock_object(self.client, '_get_volume_by_args', 

1692 mock.Mock(return_value=volume)) 

1693 self.mock_object(self.client, 'send_request') 

1694 

1695 self.mock_object( 

1696 copy, 'deepcopy', mock.Mock(return_value=self.client)) 

1697 mock_get_clones = self.mock_object( 

1698 self.client, 'get_clones_of_parent_volume', 

1699 mock.Mock(return_value=[])) 

1700 

1701 self.client.prune_deleted_volumes() 

1702 

1703 mock_get_clones.assert_called_once_with( 

1704 api_response[0]['svm']['name'], api_response[0]['name']) 

1705 

1706 def test_prune_deleted_volumes_no_clones_offline(self): 

1707 response = [fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST] 

1708 api_response = copy.deepcopy(response) 

1709 api_response[0]['state'] = 'offline' 

1710 

1711 self.mock_object(self.client, 'get_deleted_volumes_to_prune', 

1712 mock.Mock(return_value=api_response)) 

1713 self.mock_object( 

1714 copy, 'deepcopy', mock.Mock(return_value=self.client)) 

1715 mock_get_clones = self.mock_object( 

1716 self.client, 'get_clones_of_parent_volume', 

1717 mock.Mock(return_value=[])) 

1718 mock_delete = self.mock_object( 

1719 self.client, 'delete_volume', 

1720 mock.Mock(return_value='success')) 

1721 

1722 self.client.prune_deleted_volumes() 

1723 

1724 mock_get_clones.assert_called_once_with( 

1725 api_response[0]['svm']['name'], api_response[0]['name']) 

1726 mock_delete.assert_called() 

1727 

1728 def test_prune_deleted_volumes_clones_online(self): 

1729 api_response = [fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST] 

1730 self.mock_object(self.client, 'get_deleted_volumes_to_prune', 

1731 mock.Mock(return_value=api_response)) 

1732 self.mock_object( 

1733 copy, 'deepcopy', mock.Mock(return_value=self.client)) 

1734 mock_get_clones = self.mock_object( 

1735 self.client, 'get_clones_of_parent_volume', 

1736 mock.Mock(return_value=['fake_clone'])) 

1737 mock_status = self.mock_object( 

1738 self.client, 'volume_clone_split_status', 

1739 mock.Mock(return_value='unknown')) 

1740 mock_start = self.mock_object( 

1741 self.client, 'volume_clone_split_start') 

1742 

1743 self.client.prune_deleted_volumes() 

1744 

1745 mock_get_clones.assert_called_once_with( 

1746 api_response[0]['svm']['name'], api_response[0]['name']) 

1747 mock_status.assert_called_once_with('fake_clone') 

1748 mock_start.assert_called_once_with('fake_clone') 

1749 

1750 def test_prune_deleted_volumes_clones_offline(self): 

1751 response = [fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST] 

1752 api_response = copy.deepcopy(response) 

1753 api_response[0]['state'] = 'offline' 

1754 

1755 self.mock_object(self.client, 'get_deleted_volumes_to_prune', 

1756 mock.Mock(return_value=api_response)) 

1757 self.mock_object( 

1758 copy, 'deepcopy', mock.Mock(return_value=self.client)) 

1759 mock_get_clones = self.mock_object( 

1760 self.client, 'get_clones_of_parent_volume', 

1761 mock.Mock(return_value=['fake_clone'])) 

1762 mock_online = self.mock_object(self.client, 'online_volume') 

1763 

1764 self.client.prune_deleted_volumes() 

1765 

1766 mock_get_clones.assert_called_once_with( 

1767 api_response[0]['svm']['name'], api_response[0]['name']) 

1768 mock_online.assert_has_calls([ 

1769 mock.call(api_response[0]['name']), 

1770 mock.call('fake_clone'), 

1771 ]) 

1772 

1773 def test__unmount_volume(self): 

1774 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1775 

1776 self.mock_object(self.client, '_get_volume_by_args', 

1777 mock.Mock(return_value=volume)) 

1778 mock_send_request = self.mock_object(self.client, 'send_request') 

1779 uuid = volume['uuid'] 

1780 

1781 # Unmount volume async operation. 

1782 body = {"nas": {"path": ""}} 

1783 

1784 self.client._unmount_volume('fake_volume_name') 

1785 mock_send_request.assert_called_once_with( 

1786 f'/storage/volumes/{uuid}', 'patch', body=body) 

1787 

1788 def test_online_volume(self): 

1789 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1790 

1791 self.mock_object(self.client, '_get_volume_by_args', 

1792 mock.Mock(return_value=volume)) 

1793 mock_send_request = self.mock_object(self.client, 'send_request') 

1794 uuid = volume['uuid'] 

1795 

1796 body = {'state': 'online'} 

1797 self.client.online_volume('fake_volume_name') 

1798 mock_send_request.assert_called_once_with(f'/storage/volumes/{uuid}', 

1799 'patch', body=body) 

1800 

1801 def test_offline_volume(self): 

1802 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

1803 

1804 self.mock_object(self.client, '_get_volume_by_args', 

1805 mock.Mock(return_value=volume)) 

1806 mock_send_request = self.mock_object(self.client, 'send_request') 

1807 uuid = volume['uuid'] 

1808 

1809 body = {'state': 'offline'} 

1810 self.client.offline_volume('fake_volume_name') 

1811 mock_send_request.assert_called_once_with(f'/storage/volumes/{uuid}', 

1812 'patch', body=body) 

1813 

1814 def test_qos_policy_group_rename(self): 

1815 """Renames a QoS policy group.""" 

1816 

1817 qos_policy_group_name = 'extreme' 

1818 new_name = 'new_name' 

1819 res = fake.QOS_POLICY_GROUP_REST 

1820 mock_send_request = self.mock_object(self.client, 'send_request', 

1821 mock.Mock(return_value=res)) 

1822 query = { 

1823 'name': qos_policy_group_name, 

1824 'fields': 'uuid', 

1825 } 

1826 uuid = res.get('records')[0]['uuid'] 

1827 body = {"name": new_name} 

1828 

1829 self.client.qos_policy_group_rename(qos_policy_group_name, new_name) 

1830 

1831 mock_send_request.assert_has_calls([ 

1832 mock.call('/storage/qos/policies', 'get', query=query), 

1833 mock.call(f'/storage/qos/policies/{uuid}', 'patch', 

1834 body=body), 

1835 ]) 

1836 

1837 def test_qos_policy_group_get(self): 

1838 qos_policy_group_name = 'extreme' 

1839 qos_policy_group = fake.QOS_POLICY_GROUP_REST 

1840 qos_policy = qos_policy_group.get('records')[0] 

1841 max_throughput = qos_policy.get('fixed', 

1842 {}).get('max_throughput_iops') 

1843 min_throughput = qos_policy.get('fixed', 

1844 {}).get('min_throughput_iops') 

1845 

1846 expected = { 

1847 'policy-group': qos_policy.get('name'), 

1848 'vserver': qos_policy.get('svm', {}).get('name'), 

1849 'max-throughput': max_throughput if max_throughput else None, 

1850 'min-throughput': min_throughput if min_throughput else None, 

1851 'num-workloads': int(qos_policy.get('object_count')), 

1852 } 

1853 

1854 query = { 

1855 'name': qos_policy_group_name, 

1856 'fields': 'name,object_count,fixed.max_throughput_iops,' + 

1857 'fixed.max_throughput_mbps,svm.name,' + 

1858 'fixed.min_throughput_iops,fixed.min_throughput_mbps' 

1859 } 

1860 

1861 mock_sr = self.mock_object(self.client, 'send_request', 

1862 mock.Mock(return_value=qos_policy_group)) 

1863 

1864 result = self.client.qos_policy_group_get(qos_policy_group_name) 

1865 mock_sr.assert_called_once_with('/storage/qos/policies', 'get', 

1866 query=query) 

1867 self.assertEqual(expected, result) 

1868 

1869 def test_remove_unused_qos_policy_groups(self): 

1870 

1871 result = fake.QOS_POLICY_GROUP_REST 

1872 

1873 query = { 

1874 'name': '%s*' % client_cmode_rest.DELETED_PREFIX, 

1875 'fields': 'uuid,name', 

1876 } 

1877 

1878 mock_send_request = self.mock_object(self.client, 'send_request', 

1879 mock.Mock(return_value=result)) 

1880 

1881 res = result.get('records') 

1882 for record in res: 

1883 uuid = record['uuid'] 

1884 

1885 self.client.remove_unused_qos_policy_groups() 

1886 

1887 mock_send_request.assert_has_calls([ 

1888 mock.call('/storage/qos/policies', 'get', query=query), 

1889 mock.call(f'/storage/qos/policies/{uuid}', 'delete')]) 

1890 

1891 def test_unmount_volume(self): 

1892 

1893 self.mock_object(self.client, '_unmount_volume') 

1894 

1895 self.client.unmount_volume(fake.SHARE_NAME) 

1896 

1897 self.client._unmount_volume.assert_called_once_with(fake.SHARE_NAME) 

1898 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count) 

1899 self.assertEqual(0, client_cmode_rest.LOG.warning.call_count) 

1900 

1901 def test_unmount_volume_api_error(self): 

1902 

1903 self.mock_object(self.client, 

1904 '_unmount_volume', 

1905 self._mock_api_error()) 

1906 

1907 self.assertRaises(netapp_api.api.NaApiError, 

1908 self.client.unmount_volume, 

1909 fake.SHARE_NAME) 

1910 

1911 self.assertEqual(1, self.client._unmount_volume.call_count) 

1912 self.assertEqual(0, client_cmode_rest.LOG.debug.call_count) 

1913 self.assertEqual(0, client_cmode_rest.LOG.warning.call_count) 

1914 

1915 def test_unmount_volume_with_retries(self): 

1916 return_code = netapp_api.EREST_UNMOUNT_FAILED_LOCK 

1917 side_effect = [netapp_api.api.NaApiError(code=return_code, 

1918 message='...job ID...')] * 5 

1919 side_effect.append(None) 

1920 self.mock_object(self.client, 

1921 '_unmount_volume', 

1922 mock.Mock(side_effect=side_effect)) 

1923 self.mock_object(time, 'sleep') 

1924 

1925 self.client.unmount_volume(fake.SHARE_NAME) 

1926 

1927 self.assertEqual(6, self.client._unmount_volume.call_count) 

1928 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count) 

1929 self.assertEqual(5, client_cmode_rest.LOG.warning.call_count) 

1930 

1931 def test_unmount_volume_with_max_retries(self): 

1932 return_code = netapp_api.EREST_UNMOUNT_FAILED_LOCK 

1933 side_effect = [netapp_api.api.NaApiError(code=return_code, 

1934 message='...job ID...')] * 30 

1935 self.mock_object(self.client, 

1936 '_unmount_volume', 

1937 mock.Mock(side_effect=side_effect)) 

1938 self.mock_object(time, 'sleep') 

1939 

1940 self.assertRaises(exception.NetAppException, 

1941 self.client.unmount_volume, 

1942 fake.SHARE_NAME) 

1943 

1944 self.assertEqual(10, self.client._unmount_volume.call_count) 

1945 self.assertEqual(0, client_cmode_rest.LOG.debug.call_count) 

1946 self.assertEqual(10, client_cmode_rest.LOG.warning.call_count) 

1947 

1948 def test_qos_policy_group_exists(self): 

1949 mock = self.mock_object(self.client, 'qos_policy_group_get') 

1950 response = self.client.qos_policy_group_exists('extreme') 

1951 mock.assert_called_once_with('extreme') 

1952 self.assertTrue(response) 

1953 

1954 def test_mark_qos_policy_group_for_deletion_rename_failure(self): 

1955 self.mock_object(self.client, 'qos_policy_group_exists', 

1956 mock.Mock(return_value=True)) 

1957 self.mock_object(self.client, 'qos_policy_group_rename', 

1958 mock.Mock(side_effect=netapp_api.api.NaApiError)) 

1959 self.mock_object(client_cmode_rest.LOG, 'warning') 

1960 self.mock_object(self.client, 'remove_unused_qos_policy_groups') 

1961 

1962 retval = self.client.mark_qos_policy_group_for_deletion( 

1963 fake.QOS_POLICY_GROUP_NAME) 

1964 

1965 self.assertIsNone(retval) 

1966 client_cmode_rest.LOG.warning.assert_called_once() 

1967 self.client.qos_policy_group_exists.assert_called_once_with( 

1968 fake.QOS_POLICY_GROUP_NAME) 

1969 self.client.qos_policy_group_rename.assert_called_once_with( 

1970 fake.QOS_POLICY_GROUP_NAME, 

1971 client_cmode_rest.DELETED_PREFIX + fake.QOS_POLICY_GROUP_NAME) 

1972 self.client.remove_unused_qos_policy_groups.assert_called_once_with() 

1973 

1974 @ddt.data(True, False) 

1975 def test_mark_qos_policy_group_for_deletion_policy_exists(self, exists): 

1976 self.mock_object(self.client, 'qos_policy_group_exists', 

1977 mock.Mock(return_value=exists)) 

1978 self.mock_object(self.client, 'qos_policy_group_rename') 

1979 mock_remove_unused_policies = self.mock_object( 

1980 self.client, 'remove_unused_qos_policy_groups') 

1981 self.mock_object(client_cmode_rest.LOG, 'warning') 

1982 

1983 retval = self.client.mark_qos_policy_group_for_deletion( 

1984 fake.QOS_POLICY_GROUP_NAME) 

1985 

1986 self.assertIsNone(retval) 

1987 

1988 if exists: 

1989 self.client.qos_policy_group_rename.assert_called_once_with( 

1990 fake.QOS_POLICY_GROUP_NAME, 

1991 client_cmode_rest.DELETED_PREFIX + fake.QOS_POLICY_GROUP_NAME) 

1992 mock_remove_unused_policies.assert_called_once_with() 

1993 else: 

1994 self.assertFalse(self.client.qos_policy_group_rename.called) 

1995 self.assertFalse( 

1996 self.client.remove_unused_qos_policy_groups.called) 

1997 self.assertFalse(client_cmode_rest.LOG.warning.called) 

1998 

1999 def test_set_volume_size(self): 

2000 unique_volume_return = {'uuid': 'fake_uuid'} 

2001 self.mock_object(self.client, '_get_volume_by_args', 

2002 mock.Mock(return_value=unique_volume_return)) 

2003 mock_sr = self.mock_object(self.client, 'send_request') 

2004 self.client.set_volume_size('fake_name', 1) 

2005 

2006 body = { 

2007 'space.size': 1 * units.Gi 

2008 } 

2009 mock_sr.assert_called_once_with( 

2010 '/storage/volumes/fake_uuid', 'patch', body=body) 

2011 

2012 def test_qos_policy_group_modify(self): 

2013 return_request = { 

2014 'records': [{'uuid': 'fake_uuid'}] 

2015 } 

2016 mock_sr = self.mock_object(self.client, 'send_request', 

2017 mock.Mock(return_value=return_request)) 

2018 self.client.qos_policy_group_modify('qos_fake_name', '1000iops') 

2019 

2020 query = { 

2021 'name': 'qos_fake_name', 

2022 } 

2023 body = { 

2024 'fixed.max_throughput_iops': 1000, 

2025 'fixed.max_throughput_mbps': 0 

2026 } 

2027 mock_sr.assert_has_calls([ 

2028 mock.call('/storage/qos/policies', 'get', query=query), 

2029 mock.call('/storage/qos/policies/fake_uuid', 'patch', body=body), 

2030 ]) 

2031 

2032 @ddt.data(True, False) 

2033 def test_set_volume_filesys_size_fixed(self, filesys_size_fixed): 

2034 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

2035 

2036 self.mock_object(self.client, '_get_volume_by_args', 

2037 mock.Mock(return_value=volume)) 

2038 mock_send_request = self.mock_object(self.client, 'send_request') 

2039 fake_uuid = volume['uuid'] 

2040 

2041 self.client.set_volume_filesys_size_fixed(fake.SHARE_NAME, 

2042 filesys_size_fixed) 

2043 body = { 

2044 'space.filesystem_size_fixed': filesys_size_fixed} 

2045 mock_send_request.assert_called_once_with( 

2046 f'/storage/volumes/{fake_uuid}', 

2047 'patch', body=body) 

2048 

2049 def test_create_snapshot(self): 

2050 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

2051 mock_get_volume = self.mock_object( 

2052 self.client, '_get_volume_by_args', 

2053 mock.Mock(return_value=volume)) 

2054 mock_send_request = self.mock_object(self.client, 'send_request') 

2055 

2056 self.client.create_snapshot(fake.VOLUME_NAMES[0], fake.SNAPSHOT_NAME) 

2057 

2058 mock_get_volume.assert_called_once_with( 

2059 vol_name=fake.VOLUME_NAMES[0]) 

2060 body = { 

2061 'name': fake.SNAPSHOT_NAME, 

2062 } 

2063 uuid = volume['uuid'] 

2064 mock_send_request.assert_called_once_with( 

2065 f'/storage/volumes/{uuid}/snapshots', 'post', body=body) 

2066 

2067 def test_is_flexgroup_supported(self): 

2068 flexgroup_supported = self.client.is_flexgroup_supported() 

2069 

2070 self.assertTrue(flexgroup_supported) 

2071 

2072 def test_reset_volume_autosize(self): 

2073 """Test reset_volume_autosize method.""" 

2074 mock_sr = self.mock_object(self.client, 'send_request') 

2075 

2076 volume_name = fake.VOLUME_NAMES[0] 

2077 vserver_name = fake.VSERVER_NAME 

2078 

2079 self.client.reset_volume_autosize(volume_name, vserver_name) 

2080 

2081 expected_query = { 

2082 "vserver": vserver_name, 

2083 "volume": volume_name 

2084 } 

2085 expected_body = { 

2086 "autosize-reset": "true" 

2087 } 

2088 

2089 mock_sr.assert_called_once_with( 

2090 '/private/cli/volume', 'patch', 

2091 query=expected_query, body=expected_body) 

2092 

2093 def test_reset_volume_autosize_api_error(self): 

2094 """Test reset_volume_autosize method handles API errors.""" 

2095 mock_sr = self.mock_object( 

2096 self.client, 'send_request', 

2097 mock.Mock(side_effect=netapp_api.api.NaApiError( 

2098 code='fake_code', message='fake_message'))) 

2099 

2100 volume_name = fake.VOLUME_NAMES[0] 

2101 vserver_name = fake.VSERVER_NAME 

2102 

2103 self.assertRaises( 

2104 netapp_api.api.NaApiError, 

2105 self.client.reset_volume_autosize, 

2106 volume_name, vserver_name) 

2107 

2108 self.assertTrue(mock_sr.called) 

2109 

2110 @ddt.data(True, False) 

2111 def test_is_flexgroup_volume(self, is_flexgroup): 

2112 response = copy.deepcopy(fake.VOLUME_LIST_SIMPLE_RESPONSE_REST) 

2113 expected_style = 'flexgroup' if is_flexgroup else 'flexvol' 

2114 response['records'][0]['style'] = expected_style 

2115 mock_send_request = self.mock_object(self.client, 'send_request', 

2116 mock.Mock(return_value=response)) 

2117 mock_has_records = self.mock_object( 

2118 self.client, '_has_records', mock.Mock(return_value=True)) 

2119 mock_na_utils_is_flexgroup = self.mock_object( 

2120 netapp_utils, 'is_style_extended_flexgroup', 

2121 mock.Mock(return_value=is_flexgroup)) 

2122 

2123 result = self.client.is_flexgroup_volume(fake.VOLUME_NAMES[0]) 

2124 

2125 self.assertEqual(is_flexgroup, result) 

2126 query = { 

2127 'name': fake.VOLUME_NAMES[0], 

2128 'fields': 'style' 

2129 } 

2130 mock_send_request.assert_called_once_with('/storage/volumes/', 'get', 

2131 query=query) 

2132 mock_has_records.assert_called_once_with(response) 

2133 mock_na_utils_is_flexgroup.assert_called_once_with(expected_style) 

2134 

2135 def test_is_flexgroup_volume_raise_no_records(self): 

2136 self.mock_object(self.client, 'send_request', 

2137 mock.Mock(return_value=fake.NO_RECORDS_RESPONSE_REST)) 

2138 self.mock_object( 

2139 self.client, '_has_records', mock.Mock(return_value=False)) 

2140 

2141 self.assertRaises( 

2142 exception.StorageResourceNotFound, 

2143 self.client.is_flexgroup_volume, 

2144 fake.VOLUME_NAMES[0]) 

2145 

2146 def test_is_flexgroup_volume_raise_more_than_one_volume(self): 

2147 self.mock_object( 

2148 self.client, 'send_request', 

2149 mock.Mock(return_value=fake.VOLUME_GET_ITER_RESPONSE_REST_PAGE)) 

2150 self.mock_object( 

2151 self.client, '_has_records', mock.Mock(return_value=True)) 

2152 

2153 self.assertRaises( 

2154 exception.NetAppException, 

2155 self.client.is_flexgroup_volume, 

2156 fake.VOLUME_NAMES[0]) 

2157 

2158 @ddt.data( 

2159 {'is_busy': True, 'owners': ['volume_clone']}, 

2160 {'is_busy': False, 'owners': ['snap_restore_dependent']}) 

2161 @ddt.unpack 

2162 def test__is_busy_snapshot(self, is_busy, owners): 

2163 result = self.client._is_busy_snapshot(owners) 

2164 

2165 self.assertEqual(is_busy, result) 

2166 

2167 @ddt.data(True, False) 

2168 def test_get_snapshot(self, locked): 

2169 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

2170 mock_get_volume = self.mock_object( 

2171 self.client, '_get_volume_by_args', 

2172 mock.Mock(return_value=volume)) 

2173 response = copy.deepcopy(fake.SNAPSHOTS_REST_RESPONSE) 

2174 owners = ['volume_clone'] if locked else [] 

2175 response['records'][0]['owners'] = owners 

2176 mock_send_request = self.mock_object(self.client, 'send_request', 

2177 mock.Mock(return_value=response)) 

2178 mock_has_records = self.mock_object( 

2179 self.client, '_has_records', mock.Mock(return_value=True)) 

2180 

2181 mock_is_busy = self.mock_object(self.client, '_is_busy_snapshot', 

2182 mock.Mock(return_value=True)) 

2183 

2184 result = self.client.get_snapshot(fake.VOLUME_NAMES[0], 

2185 fake.SNAPSHOT_NAME) 

2186 

2187 expected_snapshot = { 

2188 'access-time': fake.SNAPSHOT_REST['create_time'], 

2189 'name': fake.SNAPSHOT_REST['name'], 

2190 'volume': fake.SNAPSHOT_REST['volume']['name'], 

2191 'owners': set(owners), 

2192 'busy': True, 

2193 'locked_by_clone': locked, 

2194 } 

2195 self.assertEqual(expected_snapshot, result) 

2196 mock_get_volume.assert_called_once_with( 

2197 vol_name=fake.VOLUME_NAMES[0]) 

2198 uuid = volume['uuid'] 

2199 query = { 

2200 'name': fake.SNAPSHOT_NAME, 

2201 'fields': 'name,volume,create_time,owners' 

2202 } 

2203 mock_send_request.assert_called_once_with( 

2204 f'/storage/volumes/{uuid}/snapshots', 'get', query=query) 

2205 mock_has_records.assert_called_once_with(response) 

2206 mock_is_busy.assert_called_once_with(set(owners)) 

2207 

2208 def test_get_snapshot_raise_not_found(self): 

2209 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

2210 self.mock_object( 

2211 self.client, '_get_volume_by_args', 

2212 mock.Mock(return_value=volume)) 

2213 self.mock_object( 

2214 self.client, 'send_request', 

2215 mock.Mock(return_value=fake.NO_RECORDS_RESPONSE_REST)) 

2216 self.mock_object( 

2217 self.client, '_has_records', mock.Mock(return_value=False)) 

2218 

2219 self.assertRaises( 

2220 exception.SnapshotResourceNotFound, 

2221 self.client.get_snapshot, 

2222 fake.VOLUME_NAMES[0], 

2223 fake.SNAPSHOT_NAME) 

2224 

2225 def test_get_snapshot_raise_more_than_one(self): 

2226 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

2227 self.mock_object( 

2228 self.client, '_get_volume_by_args', 

2229 mock.Mock(return_value=volume)) 

2230 self.mock_object( 

2231 self.client, 'send_request', 

2232 mock.Mock(return_value=fake.SNAPSHOTS_MULTIPLE_REST_RESPONSE)) 

2233 self.mock_object( 

2234 self.client, '_has_records', mock.Mock(return_value=True)) 

2235 

2236 self.assertRaises( 

2237 exception.NetAppException, 

2238 self.client.get_snapshot, 

2239 fake.VOLUME_NAMES[0], 

2240 fake.SNAPSHOT_NAME) 

2241 

2242 def test_get_clone_children_for_snapshot(self): 

2243 mock_get_records = self.mock_object( 

2244 self.client, 'get_records', 

2245 mock.Mock(return_value=fake.VOLUME_LIST_SIMPLE_RESPONSE_REST)) 

2246 

2247 result = self.client.get_clone_children_for_snapshot( 

2248 fake.VOLUME_NAMES[0], fake.SNAPSHOT_NAME) 

2249 

2250 expected_children = [{'name': fake.VOLUME_NAMES[0]}] 

2251 self.assertEqual(expected_children, result) 

2252 query = { 

2253 'clone.parent_snapshot.name': fake.SNAPSHOT_NAME, 

2254 'clone.parent_volume.name': fake.VOLUME_NAMES[0], 

2255 'fields': 'name' 

2256 } 

2257 mock_get_records.assert_called_once_with( 

2258 '/storage/volumes', query=query) 

2259 

2260 def test_volume_clone_split_start(self): 

2261 fake_resp_vol = fake.REST_SIMPLE_RESPONSE["records"][0] 

2262 fake_uuid = fake_resp_vol['uuid'] 

2263 mock_get_unique_volume = self.mock_object( 

2264 self.client, "_get_volume_by_args", 

2265 mock.Mock(return_value=fake_resp_vol) 

2266 ) 

2267 mock_send_request = self.mock_object( 

2268 self.client, 'send_request', 

2269 mock.Mock(return_value=fake.VOLUME_LIST_SIMPLE_RESPONSE_REST)) 

2270 

2271 self.client.volume_clone_split_start(fake.VOLUME_NAMES[0]) 

2272 mock_get_unique_volume.assert_called_once() 

2273 body = { 

2274 'clone.split_initiated': 'true', 

2275 } 

2276 mock_send_request.assert_called_once_with( 

2277 f'/storage/volumes/{fake_uuid}', 'patch', body=body, 

2278 wait_on_accepted=False) 

2279 

2280 def test_volume_clone_split_stop(self): 

2281 fake_resp_vol = fake.REST_SIMPLE_RESPONSE["records"][0] 

2282 fake_uuid = fake_resp_vol['uuid'] 

2283 mock_get_unique_volume = self.mock_object( 

2284 self.client, "_get_volume_by_args", 

2285 mock.Mock(return_value=fake_resp_vol) 

2286 ) 

2287 mock_send_request = self.mock_object( 

2288 self.client, 'send_request', 

2289 mock.Mock(return_value=fake.VOLUME_LIST_SIMPLE_RESPONSE_REST)) 

2290 

2291 self.client.volume_clone_split_stop(fake.VOLUME_NAMES[0]) 

2292 mock_get_unique_volume.assert_called_once() 

2293 body = { 

2294 'clone.split_initiated': 'false', 

2295 } 

2296 mock_send_request.assert_called_once_with( 

2297 f'/storage/volumes/{fake_uuid}', 'patch', body=body, 

2298 wait_on_accepted=False) 

2299 

2300 def test_rename_snapshot(self): 

2301 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

2302 mock_get_volume = self.mock_object( 

2303 self.client, '_get_volume_by_args', 

2304 mock.Mock(return_value=volume)) 

2305 mock_send_request = self.mock_object(self.client, 'send_request') 

2306 

2307 self.client.rename_snapshot( 

2308 fake.VOLUME_NAMES[0], fake.SNAPSHOT_NAME, 

2309 'new_' + fake.SNAPSHOT_NAME) 

2310 

2311 mock_get_volume.assert_called_once_with( 

2312 vol_name=fake.VOLUME_NAMES[0]) 

2313 query = { 

2314 'name': fake.SNAPSHOT_NAME, 

2315 } 

2316 body = { 

2317 'name': 'new_' + fake.SNAPSHOT_NAME, 

2318 } 

2319 uuid = volume['uuid'] 

2320 mock_send_request.assert_called_once_with( 

2321 f'/storage/volumes/{uuid}/snapshots', 'patch', query=query, 

2322 body=body) 

2323 

2324 def test__get_soft_deleted_snapshots(self): 

2325 mock_get_records = self.mock_object( 

2326 self.client, 'get_records', 

2327 mock.Mock(return_value=fake.SNAPSHOTS_MULTIPLE_REST_RESPONSE)) 

2328 self.mock_object( 

2329 self.client, '_is_busy_snapshot', 

2330 mock.Mock(side_effect=[True, False])) 

2331 

2332 snapshots_map = self.client._get_soft_deleted_snapshots() 

2333 

2334 expected_snapshots = { 

2335 fake.VSERVER_NAME: [{ 

2336 "uuid": fake.FAKE_SNAPSHOT_UUID, 

2337 "volume_uuid": fake.FAKE_VOLUME_UUID, 

2338 }] 

2339 } 

2340 self.assertEqual(expected_snapshots, snapshots_map) 

2341 query = { 

2342 'name': 'deleted_manila_*', 

2343 'fields': 'uuid,volume,owners,svm.name' 

2344 } 

2345 mock_get_records.assert_called_once_with( 

2346 '/storage/volumes/*/snapshots', query=query) 

2347 

2348 @ddt.data(True, False) 

2349 def test_prune_deleted_snapshots(self, fail_deleting): 

2350 soft_deleted_snapshots = { 

2351 fake.VSERVER_NAME: [{ 

2352 "uuid": fake.FAKE_SNAPSHOT_UUID, 

2353 "volume_uuid": fake.FAKE_VOLUME_UUID, 

2354 }] 

2355 } 

2356 mock_get_snaps = self.mock_object( 

2357 self.client, '_get_soft_deleted_snapshots', 

2358 mock.Mock(return_value=soft_deleted_snapshots) 

2359 ) 

2360 if fail_deleting: 

2361 mock_send_request = self.mock_object( 

2362 self.client, 'send_request', 

2363 mock.Mock(side_effect=netapp_api.api.NaApiError)) 

2364 else: 

2365 mock_send_request = self.mock_object(self.client, 'send_request') 

2366 

2367 self.client.prune_deleted_snapshots() 

2368 

2369 mock_get_snaps.assert_called_once_with() 

2370 vol_uuid = fake.FAKE_VOLUME_UUID 

2371 snap_uuid = fake.FAKE_SNAPSHOT_UUID 

2372 mock_send_request.assert_called_once_with( 

2373 f'/storage/volumes/{vol_uuid}/snapshots/{snap_uuid}', 'delete') 

2374 

2375 @ddt.data(True, False) 

2376 def test_snapshot_exists(self, exists): 

2377 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

2378 vol_uuid = volume['uuid'] 

2379 mock_get_vol = self.mock_object( 

2380 self.client, '_get_volume_by_args', 

2381 mock.Mock(return_value=volume)) 

2382 mock_send_request = self.mock_object( 

2383 self.client, 'send_request', 

2384 mock.Mock(return_value=fake.SNAPSHOTS_REST_RESPONSE)) 

2385 mock_has_records = self.mock_object(self.client, '_has_records', 

2386 mock.Mock(return_value=exists)) 

2387 

2388 res = self.client.snapshot_exists(fake.SNAPSHOT_NAME, 

2389 fake.VOLUME_NAMES[0]) 

2390 

2391 self.assertEqual(exists, res) 

2392 mock_get_vol.assert_called_once_with( 

2393 vol_name=fake.VOLUME_NAMES[0], fields='uuid,state') 

2394 query = { 

2395 'name': fake.SNAPSHOT_NAME 

2396 } 

2397 mock_send_request.assert_called_once_with( 

2398 f'/storage/volumes/{vol_uuid}/snapshots/', 'get', query=query) 

2399 mock_has_records.assert_called_once_with(fake.SNAPSHOTS_REST_RESPONSE) 

2400 

2401 def test_snapshot_exists_error(self): 

2402 volume = {'state': 'offline'} 

2403 self.mock_object( 

2404 self.client, '_get_volume_by_args', 

2405 mock.Mock(return_value=volume)) 

2406 

2407 self.assertRaises( 

2408 exception.SnapshotUnavailable, 

2409 self.client.snapshot_exists, 

2410 fake.SNAPSHOT_NAME, fake.VOLUME_NAMES[0]) 

2411 

2412 @ddt.data('source', 'destination', None) 

2413 def test_volume_has_snapmirror_relationships(self, snapmirror_rel_type): 

2414 """Snapmirror relationships can be both ways.""" 

2415 

2416 vol = fake.FAKE_MANAGE_VOLUME 

2417 snapmirror = { 

2418 'source-vserver': fake.SM_SOURCE_VSERVER, 

2419 'source-volume': fake.SM_SOURCE_VOLUME, 

2420 'destination-vserver': fake.SM_DEST_VSERVER, 

2421 'destination-volume': fake.SM_DEST_VOLUME, 

2422 'mirror-state': 'snapmirrored', 

2423 'schedule': 'daily', 

2424 } 

2425 expected_get_snapmirrors_call_count = 2 

2426 expected_get_snapmirrors_calls = [ 

2427 mock.call(source_vserver=vol['owning-vserver-name'], 

2428 source_volume=vol['name']), 

2429 mock.call(dest_vserver=vol['owning-vserver-name'], 

2430 dest_volume=vol['name']), 

2431 ] 

2432 if snapmirror_rel_type is None: 

2433 side_effect = ([], []) 

2434 elif snapmirror_rel_type == 'source': 

2435 snapmirror['source-vserver'] = vol['owning-vserver-name'] 

2436 snapmirror['source-volume'] = vol['name'] 

2437 side_effect = ([snapmirror], None) 

2438 expected_get_snapmirrors_call_count = 1 

2439 expected_get_snapmirrors_calls.pop() 

2440 else: 

2441 snapmirror['destination-vserver'] = vol['owning-vserver-name'] 

2442 snapmirror['destination-volume'] = vol['name'] 

2443 side_effect = (None, [snapmirror]) 

2444 mock_get_snapmirrors_call = self.mock_object( 

2445 self.client, 'get_snapmirrors', mock.Mock(side_effect=side_effect)) 

2446 mock_exc_log = self.mock_object(client_cmode.LOG, 'exception') 

2447 expected_retval = True if snapmirror_rel_type else False 

2448 

2449 retval = self.client.volume_has_snapmirror_relationships(vol) 

2450 

2451 self.assertEqual(expected_retval, retval) 

2452 self.assertEqual(expected_get_snapmirrors_call_count, 

2453 mock_get_snapmirrors_call.call_count) 

2454 mock_get_snapmirrors_call.assert_has_calls( 

2455 expected_get_snapmirrors_calls) 

2456 self.assertFalse(mock_exc_log.called) 

2457 

2458 def test_volume_has_snapmirror_relationships_api_error(self): 

2459 

2460 vol = fake.FAKE_MANAGE_VOLUME 

2461 expected_get_snapmirrors_calls = [ 

2462 mock.call(source_vserver=vol['owning-vserver-name'], 

2463 source_volume=vol['name']), 

2464 ] 

2465 mock_get_snapmirrors_call = self.mock_object( 

2466 self.client, 'get_snapmirrors', mock.Mock( 

2467 side_effect=self._mock_api_error())) 

2468 mock_exc_log = self.mock_object(client_cmode_rest.LOG, 'exception') 

2469 

2470 retval = self.client.volume_has_snapmirror_relationships(vol) 

2471 

2472 self.assertFalse(retval) 

2473 self.assertEqual(1, mock_get_snapmirrors_call.call_count) 

2474 mock_get_snapmirrors_call.assert_has_calls( 

2475 expected_get_snapmirrors_calls) 

2476 self.assertTrue(mock_exc_log.called) 

2477 

2478 def test_get_snapmirrors_svm(self): 

2479 return_get_snp = fake.REST_GET_SNAPMIRRORS_RESPONSE 

2480 

2481 mock_get_snap = self.mock_object( 

2482 self.client, 'get_snapmirrors', 

2483 mock.Mock(return_value=return_get_snp)) 

2484 

2485 res = self.client.get_snapmirrors_svm(fake.SM_SOURCE_VSERVER, 

2486 fake.SM_DEST_VSERVER, 

2487 None) 

2488 

2489 mock_get_snap.assert_called_once_with( 

2490 source_path=fake.SM_SOURCE_VSERVER + ':*', 

2491 dest_path=fake.SM_DEST_VSERVER + ':*', 

2492 desired_attributes=None) 

2493 self.assertEqual(return_get_snp, res) 

2494 

2495 def test_get_snapmirrors(self): 

2496 

2497 api_response = fake.SNAPMIRROR_GET_ITER_RESPONSE_REST 

2498 mock_send_request = self.mock_object( 

2499 self.client, 

2500 'send_request', 

2501 mock.Mock(return_value=api_response)) 

2502 

2503 result = self.client.get_snapmirrors( 

2504 fake.SM_SOURCE_PATH, fake.SM_DEST_PATH, 

2505 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

2506 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME, 

2507 enable_tunneling=True) 

2508 

2509 expected = fake.REST_GET_SNAPMIRRORS_RESPONSE 

2510 

2511 query = { 

2512 'source.path': (fake.SM_SOURCE_VSERVER + ':' + 

2513 fake.SM_SOURCE_VOLUME), 

2514 'destination.path': (fake.SM_DEST_VSERVER + 

2515 ':' + fake.SM_DEST_VOLUME), 

2516 'fields': 'state,source.svm.name,source.path,destination.svm.name,' 

2517 'destination.path,transfer.end_time,uuid,policy.type,' 

2518 'transfer_schedule.name,transfer.state,' 

2519 'last_transfer_type,transfer.bytes_transferred,healthy' 

2520 } 

2521 

2522 mock_send_request.assert_called_once_with('/snapmirror/relationships', 

2523 'get', query=query, 

2524 enable_tunneling=True) 

2525 self.assertEqual(expected, result) 

2526 

2527 @ddt.data( 

2528 {'source_path': fake.SM_SOURCE_PATH, 'dest_path': fake.SM_DEST_PATH}, 

2529 {'source_path': None, 'dest_path': None}) 

2530 @ddt.unpack 

2531 def test__get_snapmirrors(self, source_path, dest_path): 

2532 

2533 api_response = fake.SNAPMIRROR_GET_ITER_RESPONSE_REST 

2534 mock_send_request = self.mock_object( 

2535 self.client, 

2536 'send_request', 

2537 mock.Mock(return_value=api_response)) 

2538 

2539 result = self.client._get_snapmirrors( 

2540 source_path, dest_path, 

2541 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

2542 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME) 

2543 

2544 query = { 

2545 'source.path': (fake.SM_SOURCE_VSERVER + ':' + 

2546 fake.SM_SOURCE_VOLUME), 

2547 'destination.path': (fake.SM_DEST_VSERVER + 

2548 ':' + fake.SM_DEST_VOLUME), 

2549 'fields': 'state,source.svm.name,source.path,destination.svm.name,' 

2550 'destination.path,transfer.end_time,uuid,policy.type,' 

2551 'transfer_schedule.name,transfer.state,' 

2552 'last_transfer_type,transfer.bytes_transferred,healthy' 

2553 } 

2554 

2555 mock_send_request.assert_called_once_with('/snapmirror/relationships', 

2556 'get', query=query, 

2557 enable_tunneling=True) 

2558 self.assertEqual(1, len(result)) 

2559 

2560 def test__get_snapmirrors_not_found(self): 

2561 

2562 api_response = fake.NO_RECORDS_RESPONSE_REST 

2563 mock_send_request = self.mock_object( 

2564 self.client, 

2565 'send_request', 

2566 mock.Mock(return_value=api_response)) 

2567 

2568 result = self.client._get_snapmirrors( 

2569 fake.SM_SOURCE_PATH, fake.SM_DEST_PATH, 

2570 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

2571 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME) 

2572 

2573 query = { 

2574 'source.path': (fake.SM_SOURCE_VSERVER + ':' + 

2575 fake.SM_SOURCE_VOLUME), 

2576 'destination.path': (fake.SM_DEST_VSERVER + 

2577 ':' + fake.SM_DEST_VOLUME), 

2578 'fields': 'state,source.svm.name,source.path,destination.svm.name,' 

2579 'destination.path,transfer.end_time,uuid,policy.type,' 

2580 'transfer_schedule.name,transfer.state,' 

2581 'last_transfer_type,transfer.bytes_transferred,healthy' 

2582 } 

2583 

2584 mock_send_request.assert_called_once_with('/snapmirror/relationships', 

2585 'get', query=query, 

2586 enable_tunneling=True) 

2587 self.assertEqual([], result) 

2588 

2589 @ddt.data(True, False) 

2590 def test_modify_volume_no_optional_args(self, is_flexgroup): 

2591 

2592 self.mock_object(self.client, 'send_request') 

2593 mock_update_volume_efficiency_attributes = self.mock_object( 

2594 self.client, 'update_volume_efficiency_attributes') 

2595 

2596 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

2597 self.mock_object(self.client, '_get_volume_by_args', 

2598 mock.Mock(return_value=volume)) 

2599 self.mock_object(self.client, '_is_snaplock_enabled_volume', 

2600 mock.Mock(return_value=True)) 

2601 aggr = fake.SHARE_AGGREGATE_NAME 

2602 if is_flexgroup: 

2603 aggr = list(fake.SHARE_AGGREGATE_NAMES) 

2604 

2605 self.client.modify_volume(aggr, fake.SHARE_NAME) 

2606 

2607 # default body for call with no optional params 

2608 body = {'guarantee': {'type': 'volume'}} 

2609 self.client.send_request.assert_called_once_with( 

2610 '/storage/volumes/' + volume['uuid'], 'patch', body=body) 

2611 mock_update_volume_efficiency_attributes.assert_called_once_with( 

2612 fake.SHARE_NAME, False, False, 

2613 is_flexgroup=is_flexgroup, efficiency_policy=None 

2614 ) 

2615 

2616 @ddt.data((fake.QOS_POLICY_GROUP_NAME, None), 

2617 (None, fake.ADAPTIVE_QOS_POLICY_GROUP_NAME)) 

2618 @ddt.unpack 

2619 def test_modify_volume_all_optional_args(self, qos_group, 

2620 adaptive_qos_group): 

2621 self.client.features.add_feature('ADAPTIVE_QOS') 

2622 self.mock_object(self.client, 'send_request') 

2623 mock_update_volume_efficiency_attributes = self.mock_object( 

2624 self.client, 'update_volume_efficiency_attributes') 

2625 

2626 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

2627 self.mock_object(self.client, '_get_volume_by_args', 

2628 mock.Mock(return_value=volume)) 

2629 options = {'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME} 

2630 self.mock_object(self.client, '_is_snaplock_enabled_volume', 

2631 mock.Mock(return_value=True)) 

2632 

2633 self.client.modify_volume( 

2634 fake.SHARE_AGGREGATE_NAME, 

2635 fake.SHARE_NAME, 

2636 thin_provisioned=True, 

2637 snapshot_policy=fake.SNAPSHOT_POLICY_NAME, 

2638 language=fake.LANGUAGE, 

2639 dedup_enabled=True, 

2640 compression_enabled=False, 

2641 max_files=fake.MAX_FILES, 

2642 qos_policy_group=qos_group, 

2643 adaptive_qos_policy_group=adaptive_qos_group, 

2644 autosize_attributes=fake.VOLUME_AUTOSIZE_ATTRS, 

2645 hide_snapdir=True, 

2646 **options 

2647 ) 

2648 

2649 qos_policy_name = qos_group or adaptive_qos_group 

2650 body = { 

2651 'guarantee': {'type': 'none'}, 

2652 'autosize': { 

2653 'mode': 'off', 

2654 'grow_threshold': '85', 

2655 'shrink_threshold': '50', 

2656 'maximum': '1258288', 

2657 'minimum': '1048576' 

2658 }, 

2659 'files': {'maximum': 5000}, 

2660 'snapshot_policy': {'name': 'fake_snapshot_policy'}, 

2661 'qos': {'policy': {'name': qos_policy_name}}, 

2662 'snapshot_directory_access_enabled': 'false', 

2663 'language': 'fake_language' 

2664 } 

2665 

2666 self.client.send_request.assert_called_once_with( 

2667 '/storage/volumes/' + volume['uuid'], 'patch', body=body) 

2668 mock_update_volume_efficiency_attributes.assert_called_once_with( 

2669 fake.SHARE_NAME, True, False, 

2670 is_flexgroup=False, 

2671 efficiency_policy=fake.VOLUME_EFFICIENCY_POLICY_NAME 

2672 ) 

2673 

2674 def test__parse_timestamp(self): 

2675 test_time_str = '2022-11-25T14:41:20+00:00' 

2676 res = self.client._parse_timestamp(test_time_str) 

2677 self.assertEqual(1669387280.0, res) 

2678 

2679 def test__parse_timestamp_exception(self): 

2680 test_time_str = None 

2681 self.assertRaises(TypeError, 

2682 self.client._parse_timestamp, 

2683 test_time_str) 

2684 

2685 def test__build_autosize_attributes(self): 

2686 """Test _build_autosize_attributes with various input scenarios.""" 

2687 

2688 # Test case 1: Basic functionality with all supported attributes 

2689 autosize_attrs = { 

2690 'grow-threshold-percent': 90, 

2691 'shrink-threshold-percent': 50, 

2692 'maximum-size': '10GB', 

2693 'minimum-size': '1GB', 

2694 'mode': 'grow' 

2695 } 

2696 

2697 result = self.client._build_autosize_attributes(autosize_attrs) 

2698 

2699 expected = { 

2700 'grow_threshold': 90, 

2701 'shrink_threshold': 50, 

2702 'maximum': '10GB', 

2703 'minimum': '1GB', 

2704 'mode': 'grow' 

2705 } 

2706 self.assertEqual(expected, result) 

2707 

2708 def test__build_autosize_attributes_partial_attrs(self): 

2709 """Test _build_autosize_attributes with only some attributes.""" 

2710 autosize_attrs = { 

2711 'grow-threshold-percent': 85, 

2712 'maximum-size': '5GB' 

2713 } 

2714 

2715 result = self.client._build_autosize_attributes(autosize_attrs) 

2716 

2717 expected = { 

2718 'grow_threshold': 85, 

2719 'maximum': '5GB' 

2720 } 

2721 self.assertEqual(expected, result) 

2722 

2723 def test__build_autosize_attributes_empty_dict(self): 

2724 """Test _build_autosize_attributes returns None for empty dict.""" 

2725 autosize_attrs = {} 

2726 

2727 result = self.client._build_autosize_attributes(autosize_attrs) 

2728 

2729 self.assertIsNone(result) 

2730 

2731 def test__build_autosize_attributes_with_mode_only(self): 

2732 """Test _build_autosize_attributes with only mode attribute.""" 

2733 autosize_attrs = { 

2734 'mode': 'grow_shrink' 

2735 } 

2736 

2737 result = self.client._build_autosize_attributes(autosize_attrs) 

2738 

2739 expected = { 

2740 'mode': 'grow_shrink' 

2741 } 

2742 self.assertEqual(expected, result) 

2743 autosize_attrs = { 

2744 'grow-threshold-percent': 90, 

2745 'maximum-size': '10GB' 

2746 } 

2747 

2748 result = self.client._build_autosize_attributes(autosize_attrs) 

2749 

2750 expected = { 

2751 'grow_threshold': 90, 

2752 'maximum': '10GB' 

2753 } 

2754 self.assertEqual(expected, result) 

2755 

2756 def test_start_volume_move(self): 

2757 

2758 mock__send_volume_move_request = self.mock_object( 

2759 self.client, '_send_volume_move_request') 

2760 

2761 self.client.start_volume_move(fake.VOLUME_NAMES[0], fake.VSERVER_NAME, 

2762 fake.SHARE_AGGREGATE_NAME, 

2763 'fake_cutover', False) 

2764 

2765 mock__send_volume_move_request.assert_called_once_with( 

2766 fake.VOLUME_NAMES[0], fake.VSERVER_NAME, fake.SHARE_AGGREGATE_NAME, 

2767 cutover_action='fake_cutover', encrypt_destination=False) 

2768 

2769 def test_check_volume_move(self): 

2770 

2771 mock__send_volume_move_request = self.mock_object( 

2772 self.client, '_send_volume_move_request') 

2773 

2774 self.client.check_volume_move(fake.VOLUME_NAMES[0], fake.VSERVER_NAME, 

2775 fake.SHARE_AGGREGATE_NAME, False) 

2776 

2777 mock__send_volume_move_request.assert_called_once_with( 

2778 fake.VOLUME_NAMES[0], fake.VSERVER_NAME, fake.SHARE_AGGREGATE_NAME, 

2779 validation_only=True, encrypt_destination=False) 

2780 

2781 def test__send_volume_move_request(self): 

2782 mock_sr = self.mock_object(self.client, 'send_request') 

2783 self.client._send_volume_move_request('volume_name', 'vserver', 

2784 'destination_aggregate', 

2785 cutover_action='wait', 

2786 validation_only=True, 

2787 encrypt_destination=False) 

2788 query = {'name': 'volume_name'} 

2789 body = { 

2790 'movement.destination_aggregate.name': 'destination_aggregate', 

2791 'encryption.enabled': 'false', 

2792 'validate_only': 'true', 

2793 'movement.state': 'wait', 

2794 } 

2795 mock_sr.assert_called_once_with( 

2796 '/storage/volumes/', 'patch', query=query, body=body, 

2797 wait_on_accepted=False) 

2798 

2799 def test_get_nfs_export_policy_for_volume(self): 

2800 

2801 fake_query = { 

2802 'name': 'fake_volume_name', 

2803 'fields': 'nas.export_policy.name' 

2804 } 

2805 

2806 ret = { 

2807 'records': [ 

2808 { 

2809 'nas': { 

2810 'export_policy': { 

2811 'name': 'fake_name' 

2812 } 

2813 } 

2814 } 

2815 ] 

2816 } 

2817 

2818 mock_records = self.mock_object(self.client, '_has_records', 

2819 mock.Mock(return_value=True)) 

2820 mock_sr = self.mock_object(self.client, 'send_request', 

2821 mock.Mock(return_value=ret)) 

2822 

2823 res = self.client.get_nfs_export_policy_for_volume('fake_volume_name') 

2824 

2825 mock_records.assert_called_once_with(ret) 

2826 mock_sr.assert_called_once_with('/storage/volumes/', 'get', 

2827 query=fake_query) 

2828 expected = 'fake_name' 

2829 self.assertEqual(expected, res) 

2830 

2831 def test_get_unique_export_policy_id(self): 

2832 mock_records = self.mock_object(self.client, '_has_records', 

2833 mock.Mock(return_value=True)) 

2834 expected = 'fake_uuid' 

2835 ret = { 

2836 'records': [ 

2837 { 

2838 'id': 'fake_uuid' 

2839 } 

2840 ] 

2841 } 

2842 mock_sr = self.mock_object(self.client, 'send_request', 

2843 mock.Mock(return_value=ret)) 

2844 res = self.client.get_unique_export_policy_id('fake_policy_name') 

2845 mock_records.assert_called_once_with(ret) 

2846 mock_sr.assert_called_once_with( 

2847 '/protocols/nfs/export-policies', 'get', 

2848 query={'name': 'fake_policy_name'}) 

2849 self.assertEqual(expected, res) 

2850 

2851 def test__get_nfs_export_rule_indices(self): 

2852 mockpid = self.mock_object(self.client, 'get_unique_export_policy_id', 

2853 mock.Mock(return_value='fake_policy_id')) 

2854 

2855 fake_uuid = 'fake_policy_id' 

2856 

2857 fake_query = { 

2858 'clients.match': 'fakecl', 

2859 'fields': 'clients.match,index' 

2860 } 

2861 

2862 ret = { 

2863 'records': [ 

2864 { 

2865 'index': '0' 

2866 } 

2867 ] 

2868 } 

2869 

2870 mock_sr = self.mock_object(self.client, 'send_request', 

2871 mock.Mock(return_value=ret)) 

2872 res = self.client._get_nfs_export_rule_indices('fake_policy', 'fakecl') 

2873 mockpid.assert_called_once_with('fake_policy') 

2874 mock_sr.assert_called_once_with( 

2875 f'/protocols/nfs/export-policies/{fake_uuid}/rules', 'get', 

2876 query=fake_query) 

2877 expected = ['0'] 

2878 self.assertEqual(expected, res) 

2879 

2880 def test__add_nfs_export_rule(self): 

2881 mockpid = self.mock_object(self.client, 'get_unique_export_policy_id', 

2882 mock.Mock(return_value='fake_policy_id')) 

2883 mock_sr = self.mock_object(self.client, 'send_request') 

2884 self.client._add_nfs_export_rule('fake_policy', 'fakecl', False, 

2885 ['rw']) 

2886 mockpid.assert_called_once_with('fake_policy') 

2887 

2888 body = { 

2889 'clients': [{'match': 'fakecl'}], 

2890 'ro_rule': ['rw'], 

2891 'rw_rule': ['rw'], 

2892 'superuser': ['rw'] 

2893 } 

2894 mock_sr.assert_called_once_with( 

2895 '/protocols/nfs/export-policies/fake_policy_id/rules', 

2896 'post', body=body) 

2897 

2898 def test__update_nfs_export_rule(self): 

2899 

2900 fake_body = { 

2901 'client_match': 'fake_cli', 

2902 'ro_rule': ['rw'], 

2903 'rw_rule': ['rw'], 

2904 'superuser': ['rw'] 

2905 } 

2906 

2907 mockpid = self.mock_object(self.client, 'get_unique_export_policy_id', 

2908 mock.Mock(return_value='fake_policy_id')) 

2909 mock_sr = self.mock_object(self.client, 'send_request') 

2910 self.client._update_nfs_export_rule('fake_policy', 'fake_cli', False, 

2911 '0', ['rw']) 

2912 mockpid.assert_called_once_with('fake_policy') 

2913 mock_sr.assert_called_once_with( 

2914 '/protocols/nfs/export-policies/fake_policy_id/rules/0', 

2915 'patch', body=fake_body) 

2916 

2917 def test__remove_nfs_export_rules(self): 

2918 

2919 fake_body = { 

2920 'index': 0 

2921 } 

2922 

2923 mockpid = self.mock_object(self.client, 'get_unique_export_policy_id', 

2924 mock.Mock(return_value='fake_policy_id')) 

2925 mock_sr = self.mock_object(self.client, 'send_request') 

2926 self.client._remove_nfs_export_rules('fake_policy', [0]) 

2927 mockpid.assert_called_once_with('fake_policy') 

2928 mock_sr.assert_called_once_with( 

2929 '/protocols/nfs/export-policies/fake_policy_id/rules/0', 'delete', 

2930 body=fake_body) 

2931 

2932 def test_modify_cifs_share_access(self): 

2933 return_uuid = fake.GENERIC_EXPORT_POLICY_RESPONSE_AND_VOLUMES 

2934 self.mock_object(self.client, 'send_request', 

2935 mock.Mock(return_value=return_uuid)) 

2936 self.client.modify_cifs_share_access(fake.SHARE_NAME, fake.USER_NAME, 

2937 'read') 

2938 fake_user = 'fake_user' 

2939 FAKE_CIFS_USER_GROUP_TYPE = 'windows' 

2940 fake_uuid = 'fake_uuid' 

2941 fake_share = fake.SHARE_NAME 

2942 query = {'name': 'fake_share'} 

2943 body = {'permission': 'read'} 

2944 

2945 self.client.send_request.assert_has_calls([ 

2946 mock.call('/protocols/cifs/shares', 'get', query=query), 

2947 mock.call(f'/protocols/cifs/shares/{fake_uuid}/{fake_share}' 

2948 f'/acls/{fake_user}/{FAKE_CIFS_USER_GROUP_TYPE}', 

2949 'patch', body=body)]) 

2950 

2951 def test_add_cifs_share_access(self): 

2952 return_uuid = fake.GENERIC_EXPORT_POLICY_RESPONSE_AND_VOLUMES 

2953 self.mock_object(self.client, 'send_request', 

2954 mock.Mock(return_value=return_uuid)) 

2955 self.client.add_cifs_share_access(fake.SHARE_NAME, 

2956 fake.USER_NAME, 'read') 

2957 fake_uuid = "fake_uuid" 

2958 query = {'name': 'fake_share'} 

2959 body = {'permission': 'read', 

2960 'user_or_group': 'fake_user'} 

2961 self.client.send_request.assert_has_calls([ 

2962 mock.call('/protocols/cifs/shares', 'get', query=query), 

2963 mock.call(f'/protocols/cifs/shares/{fake_uuid}/{fake.SHARE_NAME}' 

2964 '/acls', 'post', body=body)]) 

2965 

2966 def test_get_cifs_share_access_rules_empty(self): 

2967 return_uuid = fake.GENERIC_EXPORT_POLICY_RESPONSE_AND_VOLUMES 

2968 self.mock_object(self.client, 'send_request', 

2969 mock.Mock(return_value=return_uuid)) 

2970 

2971 def test_get_cifs_share_access_rules_not_empty(self): 

2972 return_uuid = fake.GENERIC_EXPORT_POLICY_RESPONSE_AND_VOLUMES 

2973 self.mock_object(self.client, 'send_request', 

2974 mock.Mock(return_value=return_uuid)) 

2975 

2976 rules = {} 

2977 

2978 fake_results = fake.FAKE_CIFS_RECORDS 

2979 

2980 for record in fake_results['records']: 

2981 user_or_group = record['user_or_group'] 

2982 permission = record['permission'] 

2983 rules[user_or_group] = permission 

2984 

2985 def test_mount_volume_with_junction_path(self): 

2986 volume_name = fake.SHARE_NAME 

2987 junction_path = '/fake_path' 

2988 volume = fake.VOLUME 

2989 

2990 self.mock_object(self.client, '_get_volume_by_args', 

2991 mock.Mock(return_value=volume)) 

2992 self.mock_object(self.client, 'send_request') 

2993 

2994 self.client.mount_volume(volume_name, junction_path=junction_path) 

2995 

2996 uuid = volume['uuid'] 

2997 

2998 body = { 

2999 'nas.path': junction_path 

3000 } 

3001 

3002 self.client.send_request.assert_called_once_with( 

3003 f'/storage/volumes/{uuid}', 'patch', body=body) 

3004 

3005 def test_mount_volume_with_volume_name(self): 

3006 volume_name = fake.SHARE_NAME 

3007 volume = fake.VOLUME 

3008 

3009 self.mock_object(self.client, '_get_volume_by_args', 

3010 mock.Mock(return_value=volume)) 

3011 self.mock_object(self.client, 'send_request') 

3012 

3013 self.client.mount_volume(volume_name) 

3014 

3015 uuid = volume['uuid'] 

3016 

3017 body = { 

3018 'nas.path': '/%s' % volume_name 

3019 } 

3020 

3021 self.client.send_request.assert_called_once_with( 

3022 f'/storage/volumes/{uuid}', 'patch', body=body) 

3023 

3024 def test_set_volume_name(self): 

3025 volume_name = fake.SHARE_NAME 

3026 new_volume_name = 'fake_name' 

3027 

3028 volume = fake.VOLUME 

3029 

3030 self.mock_object(self.client, '_get_volume_by_args', 

3031 mock.Mock(return_value=volume)) 

3032 self.mock_object(self.client, 'send_request') 

3033 

3034 self.client.set_volume_name(volume_name, new_volume_name) 

3035 

3036 uuid = volume['uuid'] 

3037 

3038 body = { 

3039 'name': new_volume_name 

3040 } 

3041 

3042 self.client.send_request.assert_called_once_with( 

3043 f'/storage/volumes/{uuid}', 'patch', body=body) 

3044 

3045 def test_get_job(self): 

3046 mock_sr = self.mock_object(self.client, 'send_request') 

3047 self.client.get_job('fake_job_uuid') 

3048 mock_sr.assert_called_once_with('/cluster/jobs/fake_job_uuid', 

3049 'get', enable_tunneling=False) 

3050 

3051 @ddt.data(netapp_api.EREST_VSERVER_NOT_FOUND, 'fake') 

3052 def test_vserver_exists_exception(self, er): 

3053 self.mock_object(self.client, 'send_request', 

3054 mock.Mock(side_effect=self._mock_api_error(code=er))) 

3055 if er == netapp_api.EREST_VSERVER_NOT_FOUND: 

3056 result = self.client.vserver_exists(fake.VSERVER_NAME) 

3057 self.assertFalse(result) 

3058 else: 

3059 self.assertRaises(netapp_api.api.NaApiError, 

3060 self.client.vserver_exists, 

3061 fake.VSERVER_NAME) 

3062 

3063 def test__get_aggregate_disk_types(self): 

3064 response = fake.FAKE_DISK_TYPE_RESPONSE 

3065 aggr = fake.SHARE_AGGREGATE_NAME 

3066 mock_sr = self.mock_object(self.client, 'send_request', 

3067 mock.Mock(return_value=response)) 

3068 query = { 

3069 'aggregates.name': aggr, 

3070 'fields': 'effective_type' 

3071 } 

3072 expected = {'fakedisk'} 

3073 

3074 result = self.client._get_aggregate_disk_types(aggr) 

3075 

3076 mock_sr.assert_called_once_with('/storage/disks', 'get', query=query) 

3077 self.assertEqual(expected, result) 

3078 

3079 def test__get_aggregate_disk_types_exception(self): 

3080 aggr = fake.SHARE_AGGREGATE_NAME 

3081 self.mock_object(self.client, 'send_request', 

3082 mock.Mock(side_effect=self._mock_api_error())) 

3083 result = self.client._get_aggregate_disk_types(aggr) 

3084 self.assertEqual(set(), result) 

3085 

3086 def test_create_nfs_export_policy_exception(self): 

3087 self.mock_object(self.client, 'send_request', 

3088 mock.Mock(side_effect=self._mock_api_error())) 

3089 self.assertRaises(netapp_api.api.NaApiError, 

3090 self.client.create_nfs_export_policy, 

3091 fake.EXPORT_POLICY_NAME) 

3092 

3093 @ddt.data(True, False) 

3094 def test__get_create_volume_body(self, thin_provisioned): 

3095 expected = { 

3096 'type': 'fake_type', 

3097 'guarantee.type': ('none' if thin_provisioned else 'volume'), 

3098 'nas.path': '/%s' % fake.SHARE_MOUNT_POINT, 

3099 'snapshot_policy.name': fake.SNAPSHOT_POLICY_NAME, 

3100 'language': 'fake_language', 

3101 'space.snapshot.reserve_percent': 'fake_percent', 

3102 'qos.policy.name': fake.QOS_POLICY_GROUP_NAME, 

3103 'svm.name': 'fake_vserver', 

3104 'encryption.enabled': 'true', 

3105 'snaplock.type': 'compliance', 

3106 } 

3107 

3108 self.mock_object(self.client.connection, 'get_vserver', 

3109 mock.Mock(return_value='fake_vserver')) 

3110 res = self.client._get_create_volume_body(fake.VOLUME_NAMES[0], 

3111 thin_provisioned, 

3112 fake.SNAPSHOT_POLICY_NAME, 

3113 'fake_language', 

3114 'fake_percent', 

3115 'fake_type', 

3116 fake.QOS_POLICY_GROUP_NAME, 

3117 True, 

3118 fake.QOS_POLICY_GROUP_NAME, 

3119 fake.SHARE_MOUNT_POINT, 

3120 "compliance") 

3121 self.assertEqual(expected, res) 

3122 

3123 def test_get_job_state(self): 

3124 expected = 'success' 

3125 query = { 

3126 'uuid': 'fake_uuid', 

3127 'fields': 'state' 

3128 } 

3129 response = { 

3130 'records': [fake.JOB_SUCCESSFUL_REST] 

3131 } 

3132 mock_sr = self.mock_object(self.client, 'send_request', 

3133 mock.Mock(return_value=response)) 

3134 self.mock_object(self.client, '_has_records', 

3135 mock.Mock(return_value=True)) 

3136 result = self.client.get_job_state('fake_uuid') 

3137 mock_sr.assert_called_once_with('/cluster/jobs/', 'get', query=query, 

3138 enable_tunneling=False) 

3139 self.assertEqual(expected, result) 

3140 

3141 def test_get_job_state_not_found(self): 

3142 self.mock_object(self.client, 'send_request') 

3143 self.mock_object(self.client, '_has_records', 

3144 mock.Mock(return_value=False)) 

3145 self.assertRaises(exception.NetAppException, 

3146 self.client.get_job_state, 

3147 'fake_uuid') 

3148 

3149 def test_update_volume_snapshot_policy(self): 

3150 return_uuid = { 

3151 'uuid': 'fake_uuid' 

3152 } 

3153 mock_get_vol = self.mock_object(self.client, '_get_volume_by_args', 

3154 mock.Mock(return_value=return_uuid)) 

3155 mock_sr = self.mock_object(self.client, 'send_request') 

3156 

3157 self.client.update_volume_snapshot_policy('fake_volume_name', 

3158 fake.SNAPSHOT_POLICY_NAME) 

3159 body = { 

3160 'snapshot_policy.name': fake.SNAPSHOT_POLICY_NAME 

3161 } 

3162 mock_sr.assert_called_once_with('/storage/volumes/fake_uuid', 

3163 'patch', body=body) 

3164 mock_get_vol.assert_called_once_with(vol_name='fake_volume_name') 

3165 

3166 @ddt.data(True, False) 

3167 def test_update_volume_efficiency_attributes(self, status): 

3168 response = { 

3169 'dedupe': not status, 

3170 'compression': not status 

3171 } 

3172 self.mock_object(self.client, 'get_volume_efficiency_status', 

3173 mock.Mock(return_value=response)) 

3174 en_dedupe = self.mock_object(self.client, 'enable_dedupe_async') 

3175 dis_dedupe = self.mock_object(self.client, 'disable_dedupe_async') 

3176 en_comp = self.mock_object(self.client, 'enable_compression_async') 

3177 dis_comp = self.mock_object(self.client, 'disable_compression_async') 

3178 apply_efficiency_policy = self.mock_object( 

3179 self.client, 'apply_volume_efficiency_policy' 

3180 ) 

3181 

3182 self.client.update_volume_efficiency_attributes( 

3183 fake.VOLUME_NAMES[0], 

3184 status, status, 

3185 efficiency_policy=fake.VOLUME_EFFICIENCY_POLICY_NAME) 

3186 

3187 if status: 

3188 en_dedupe.assert_called_once_with(fake.VOLUME_NAMES[0]) 

3189 en_comp.assert_called_once_with(fake.VOLUME_NAMES[0]) 

3190 apply_efficiency_policy.assert_called_once_with( 

3191 fake.VOLUME_NAMES[0], 

3192 efficiency_policy=fake.VOLUME_EFFICIENCY_POLICY_NAME 

3193 ) 

3194 else: 

3195 dis_dedupe.assert_called_once_with(fake.VOLUME_NAMES[0]) 

3196 dis_comp.assert_called_once_with(fake.VOLUME_NAMES[0]) 

3197 apply_efficiency_policy.assert_called_once_with( 

3198 fake.VOLUME_NAMES[0], 

3199 efficiency_policy=fake.VOLUME_EFFICIENCY_POLICY_NAME 

3200 ) 

3201 

3202 def test_trigger_volume_move_cutover(self): 

3203 query = { 

3204 'name': fake.VOLUME_NAMES[0] 

3205 } 

3206 body = { 

3207 'movement.state': 'cutover' 

3208 } 

3209 self.mock_object(self.client, 'send_request') 

3210 self.client.trigger_volume_move_cutover( 

3211 fake.VOLUME_NAMES[0], fake.VSERVER_NAME) 

3212 self.client.send_request.assert_called_once_with( 

3213 '/storage/volumes/', 'patch', query=query, 

3214 body=body) 

3215 

3216 def test_abort_volume_move(self): 

3217 return_uuid = { 

3218 'uuid': 'fake_uuid' 

3219 } 

3220 mock_get_vol = self.mock_object(self.client, '_get_volume_by_args', 

3221 mock.Mock(return_value=return_uuid)) 

3222 mock_sr = self.mock_object(self.client, 'send_request') 

3223 

3224 self.client.abort_volume_move('fake_volume_name', 'fake_vserver') 

3225 

3226 mock_sr.assert_called_once_with('/storage/volumes/fake_uuid', 'patch') 

3227 mock_get_vol.assert_called_once_with(vol_name='fake_volume_name') 

3228 

3229 def test_get_volume_move_status(self): 

3230 """Gets the current state of a volume move operation.""" 

3231 

3232 return_sr = fake.FAKE_VOL_MOVE_STATUS 

3233 

3234 fields = 'movement.percent_complete,movement.state' 

3235 

3236 query = { 

3237 'name': 'fake_name', 

3238 'svm.name': 'fake_svm', 

3239 'fields': fields 

3240 } 

3241 

3242 mock_sr = self.mock_object(self.client, 'send_request', 

3243 mock.Mock(return_value=return_sr)) 

3244 

3245 result = self.client.get_volume_move_status('fake_name', 'fake_svm') 

3246 

3247 mock_sr.assert_called_once_with('/storage/volumes/', 

3248 'get', query=query) 

3249 

3250 volume_move_info = return_sr.get('records')[0] 

3251 volume_movement = volume_move_info['movement'] 

3252 

3253 expected = { 

3254 'percent-complete': volume_movement['percent_complete'], 

3255 'estimated-completion-time': '', 

3256 'state': volume_movement['state'], 

3257 'details': '', 

3258 'cutover-action': '', 

3259 'phase': volume_movement['state'], 

3260 } 

3261 

3262 self.assertEqual(expected, result) 

3263 

3264 def test_list_snapmirror_snapshots(self): 

3265 fake_response = fake.SNAPSHOTS_REST_RESPONSE 

3266 api_response = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

3267 mock_volume = self.mock_object(self.client, 

3268 '_get_volume_by_args', 

3269 mock.Mock(return_value=api_response)) 

3270 mock_request = self.mock_object(self.client, 'send_request', 

3271 mock.Mock(return_value=fake_response)) 

3272 self.client.list_snapmirror_snapshots(fake.VOLUME_NAMES[0]) 

3273 

3274 query = { 

3275 'owners': 'snapmirror_dependent', 

3276 } 

3277 mock_request.assert_called_once_with( 

3278 '/storage/volumes/fake_uuid/snapshots/', 

3279 'get', query=query) 

3280 mock_volume.assert_called_once_with(vol_name=fake.VOLUME_NAMES[0]) 

3281 

3282 @ddt.data({'policy': 'fake_policy'}, 

3283 {'policy': None}) 

3284 @ddt.unpack 

3285 def test_create_snapmirror_vol(self, policy): 

3286 api_responses = [ 

3287 { 

3288 "job": { 

3289 "uuid": fake.FAKE_UUID, 

3290 }, 

3291 }, 

3292 ] 

3293 self.mock_object(self.client, 'send_request', 

3294 mock.Mock(side_effect=copy.deepcopy(api_responses))) 

3295 self.client.create_snapmirror_vol( 

3296 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

3297 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME, 

3298 relationship_type=netapp_utils.EXTENDED_DATA_PROTECTION_TYPE, 

3299 policy=policy) 

3300 

3301 body = { 

3302 'source': { 

3303 'path': (fake.SM_SOURCE_VSERVER + ':' + 

3304 fake.SM_SOURCE_VOLUME), 

3305 }, 

3306 'destination': { 

3307 'path': (fake.SM_DEST_VSERVER + ':' + 

3308 fake.SM_DEST_VOLUME) 

3309 } 

3310 } 

3311 

3312 if policy: 

3313 body['policy.name'] = policy 

3314 

3315 self.client.send_request.assert_has_calls([ 

3316 mock.call('/snapmirror/relationships/', 'post', body=body)]) 

3317 

3318 def test_create_snapmirror_vol_already_exists(self): 

3319 api_responses = netapp_api.api.NaApiError( 

3320 code=netapp_api.EREST_ERELATION_EXISTS) 

3321 self.mock_object(self.client, 'send_request', 

3322 mock.Mock(side_effect=api_responses)) 

3323 

3324 response = self.client.create_snapmirror_vol( 

3325 fake.SM_SOURCE_VSERVER, 

3326 fake.SM_SOURCE_VOLUME, 

3327 fake.SM_DEST_VSERVER, 

3328 fake.SM_DEST_VOLUME, 

3329 schedule=None, 

3330 policy=None, 

3331 relationship_type='data_protection') 

3332 self.assertIsNone(response) 

3333 self.assertTrue(self.client.send_request.called) 

3334 

3335 def test_create_snapmirror_vol_error(self): 

3336 self.mock_object( 

3337 self.client, 'send_request', 

3338 mock.Mock(side_effect=netapp_api.api.NaApiError(code=123))) 

3339 

3340 self.assertRaises(netapp_api.api.NaApiError, 

3341 self.client.create_snapmirror_vol, 

3342 fake.SM_SOURCE_VSERVER, 

3343 fake.SM_SOURCE_VOLUME, 

3344 fake.SM_DEST_VSERVER, 

3345 fake.SM_DEST_VOLUME, 

3346 schedule=None, 

3347 policy=None, 

3348 relationship_type='data_protection') 

3349 self.assertTrue(self.client.send_request.called) 

3350 

3351 def test__set_snapmirror_state(self): 

3352 

3353 api_responses = [ 

3354 fake.SNAPMIRROR_GET_ITER_RESPONSE_REST, 

3355 { 

3356 "job": 

3357 { 

3358 "uuid": fake.FAKE_UUID 

3359 }, 

3360 "num_records": 1 

3361 } 

3362 ] 

3363 

3364 expected_body = {'state': 'snapmirrored'} 

3365 self.mock_object(self.client, 

3366 'send_request', 

3367 mock.Mock(side_effect=copy.deepcopy(api_responses))) 

3368 

3369 result = self.client._set_snapmirror_state( 

3370 'snapmirrored', None, None, 

3371 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

3372 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME) 

3373 

3374 self.client.send_request.assert_has_calls([ 

3375 mock.call('/snapmirror/relationships/' + fake.FAKE_UUID, 

3376 'patch', body=expected_body, wait_on_accepted=True)]) 

3377 

3378 expected = { 

3379 'operation-id': None, 

3380 'status': None, 

3381 'jobid': fake.FAKE_UUID, 

3382 'error-code': None, 

3383 'error-message': None, 

3384 'relationship-uuid': fake.FAKE_UUID 

3385 } 

3386 self.assertEqual(expected, result) 

3387 

3388 def test_initialize_snapmirror_vol(self): 

3389 

3390 expected_job = { 

3391 'operation-id': None, 

3392 'status': None, 

3393 'jobid': fake.FAKE_UUID, 

3394 'error-code': None, 

3395 'error-message': None, 

3396 } 

3397 

3398 mock_set_snapmirror_state = self.mock_object( 

3399 self.client, 

3400 '_set_snapmirror_state', 

3401 mock.Mock(return_value=expected_job)) 

3402 

3403 result = self.client.initialize_snapmirror_vol( 

3404 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

3405 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME) 

3406 

3407 mock_set_snapmirror_state.assert_called_once_with( 

3408 'snapmirrored', None, None, 

3409 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

3410 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME, 

3411 wait_result=False) 

3412 

3413 self.assertEqual(expected_job, result) 

3414 

3415 def test_modify_snapmirror_vol(self): 

3416 

3417 expected_job = { 

3418 'operation-id': None, 

3419 'status': None, 

3420 'jobid': fake.FAKE_UUID, 

3421 'error-code': None, 

3422 'error-message': None, 

3423 } 

3424 

3425 mock_set_snapmirror_state = self.mock_object( 

3426 self.client, 

3427 '_set_snapmirror_state', 

3428 mock.Mock(return_value=expected_job)) 

3429 

3430 result = self.client.modify_snapmirror_vol( 

3431 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

3432 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME, 

3433 None) 

3434 

3435 mock_set_snapmirror_state.assert_called_once_with( 

3436 None, None, None, 

3437 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

3438 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME, 

3439 wait_result=False, schedule=None) 

3440 

3441 self.assertEqual(expected_job, result) 

3442 

3443 def test__abort_snapmirror(self): 

3444 return_snp = fake.REST_GET_SNAPMIRRORS_RESPONSE 

3445 mock_get_snap = self.mock_object(self.client, '_get_snapmirrors', 

3446 mock.Mock(return_value=return_snp)) 

3447 return_sr = fake.REST_SIMPLE_RESPONSE 

3448 mock_sr = self.mock_object(self.client, 'send_request', 

3449 mock.Mock(return_value=return_sr)) 

3450 

3451 self.client._abort_snapmirror(fake.SM_SOURCE_PATH, fake.SM_DEST_PATH) 

3452 

3453 mock_get_snap.assert_called_once_with( 

3454 source_path=fake.SM_SOURCE_PATH, 

3455 dest_path=fake.SM_DEST_PATH, 

3456 source_vserver=None, 

3457 source_volume=None, 

3458 dest_vserver=None, 

3459 dest_volume=None, 

3460 enable_tunneling=None, 

3461 list_destinations_only=None) 

3462 

3463 mock_sr.assert_has_calls([ 

3464 mock.call(f'/snapmirror/relationships/{return_snp[0]["uuid"]}' 

3465 '/transfers/', 'get', 

3466 query={'state': 'transferring'}), 

3467 mock.call(f'/snapmirror/relationships/{return_snp[0]["uuid"]}' 

3468 f'/transfers/{return_sr["records"][0]["uuid"]}', 

3469 'patch', body={'state': 'aborted'}), 

3470 ]) 

3471 

3472 def test_abort_snapmirror_vol(self): 

3473 mock_abort = self.mock_object(self.client, '_abort_snapmirror') 

3474 self.client.abort_snapmirror_vol(fake.VSERVER_NAME, 

3475 fake.VOLUME_NAMES[0], 

3476 fake.VSERVER_NAME_2, 

3477 fake.VOLUME_NAMES[1]) 

3478 mock_abort.assert_called_once_with(source_vserver=fake.VSERVER_NAME, 

3479 source_volume=fake.VOLUME_NAMES[0], 

3480 dest_vserver=fake.VSERVER_NAME_2, 

3481 dest_volume=fake.VOLUME_NAMES[1], 

3482 clear_checkpoint=False) 

3483 

3484 def test_release_snapmirror_vol(self): 

3485 mock_sr = self.mock_object(self.client, 'send_request') 

3486 return_snp = fake.REST_GET_SNAPMIRRORS_RESPONSE 

3487 mock_sd = self.mock_object(self.client, 'get_snapmirror_destinations', 

3488 mock.Mock(return_value=return_snp)) 

3489 

3490 self.client.release_snapmirror_vol(fake.VSERVER_NAME, 

3491 fake.VOLUME_NAMES[0], 

3492 fake.VSERVER_NAME_2, 

3493 fake.VOLUME_NAMES[1]) 

3494 

3495 mock_sd.assert_called_once_with(source_vserver=fake.VSERVER_NAME, 

3496 source_volume=fake.VOLUME_NAMES[0], 

3497 dest_vserver=fake.VSERVER_NAME_2, 

3498 dest_volume=fake.VOLUME_NAMES[1], 

3499 desired_attributes=['relationship-id']) 

3500 

3501 uuid = return_snp[0].get("uuid") 

3502 query = {"source_only": 'true'} 

3503 mock_sr.assert_called_once_with(f'/snapmirror/relationships/{uuid}', 

3504 'delete', query=query) 

3505 

3506 def test_delete_snapmirror_no_records(self): 

3507 query_uuid = {} 

3508 query_uuid['source.path'] = (fake.SM_SOURCE_VSERVER + ':' + 

3509 fake.SM_SOURCE_VOLUME) 

3510 

3511 query_uuid['destination.path'] = (fake.SM_DEST_VSERVER + ':' + 

3512 fake.SM_DEST_VOLUME) 

3513 query_uuid['fields'] = 'uuid' 

3514 

3515 self.mock_object(self.client, 'send_request', 

3516 mock.Mock(return_value=fake.NO_RECORDS_RESPONSE_REST)) 

3517 self.client._delete_snapmirror(fake.SM_SOURCE_VSERVER, 

3518 fake.SM_SOURCE_VOLUME, 

3519 fake.SM_DEST_VSERVER, 

3520 fake.SM_DEST_VOLUME) 

3521 self.client.send_request.assert_called_once_with( 

3522 '/snapmirror/relationships/', 'get', query=query_uuid) 

3523 

3524 def test_delete_snapmirror(self): 

3525 query_uuid = {} 

3526 query_uuid['source.path'] = (fake.SM_SOURCE_VSERVER + ':' + 

3527 fake.SM_SOURCE_VOLUME) 

3528 

3529 query_uuid['destination.path'] = (fake.SM_DEST_VSERVER + ':' + 

3530 fake.SM_DEST_VOLUME) 

3531 query_uuid['fields'] = 'uuid' 

3532 fake_cluster = fake.FAKE_GET_CLUSTER_NODE_VERSION_REST 

3533 self.mock_object(self.client, 'send_request', 

3534 mock.Mock(return_value=fake_cluster)) 

3535 self.client._delete_snapmirror(fake.SM_SOURCE_VSERVER, 

3536 fake.SM_SOURCE_VOLUME, 

3537 fake.SM_DEST_VSERVER, 

3538 fake.SM_DEST_VOLUME) 

3539 

3540 query_delete = {"destination_only": "true"} 

3541 snapmirror_uuid = fake_cluster.get('records')[0].get('uuid') 

3542 self.client.send_request.assert_has_calls([ 

3543 mock.call('/snapmirror/relationships/', 'get', query=query_uuid), 

3544 mock.call('/snapmirror/relationships/' + snapmirror_uuid, 'delete', 

3545 query=query_delete) 

3546 ]) 

3547 

3548 def test_get_snapmirror_destinations(self): 

3549 mock_get_sm = self.mock_object(self.client, '_get_snapmirrors') 

3550 self.client.get_snapmirror_destinations(fake.SM_SOURCE_PATH, 

3551 fake.SM_DEST_PATH, 

3552 fake.SM_SOURCE_VSERVER, 

3553 fake.SM_SOURCE_VOLUME, 

3554 fake.SM_DEST_VSERVER, 

3555 fake.SM_DEST_VOLUME) 

3556 

3557 mock_get_sm.assert_called_once_with( 

3558 source_path=fake.SM_SOURCE_PATH, 

3559 dest_path=fake.SM_DEST_PATH, 

3560 source_vserver=fake.SM_SOURCE_VSERVER, 

3561 source_volume=fake.SM_SOURCE_VOLUME, 

3562 dest_vserver=fake.SM_DEST_VSERVER, 

3563 dest_volume=fake.SM_DEST_VOLUME, 

3564 enable_tunneling=False, 

3565 list_destinations_only=True) 

3566 

3567 def test_delete_snapmirror_vol(self): 

3568 mock_delete = self.mock_object(self.client, '_delete_snapmirror') 

3569 self.client.delete_snapmirror_vol(fake.SM_SOURCE_VSERVER, 

3570 fake.SM_SOURCE_VOLUME, 

3571 fake.SM_DEST_VSERVER, 

3572 fake.SM_DEST_VOLUME) 

3573 mock_delete.assert_called_once_with( 

3574 source_vserver=fake.SM_SOURCE_VSERVER, 

3575 dest_vserver=fake.SM_DEST_VSERVER, 

3576 source_volume=fake.SM_SOURCE_VOLUME, 

3577 dest_volume=fake.SM_DEST_VOLUME) 

3578 

3579 def test_disable_fpolicy_policy(self): 

3580 query = { 

3581 'name': fake.VSERVER_NAME, 

3582 'fields': 'uuid' 

3583 } 

3584 response_svm = fake.SVMS_LIST_SIMPLE_RESPONSE_REST 

3585 self.client.vserver = fake.VSERVER_NAME 

3586 self.mock_object(self.client, 

3587 'send_request', 

3588 mock.Mock(side_effect=[response_svm, None])) 

3589 

3590 self.client.disable_fpolicy_policy(fake.FPOLICY_POLICY_NAME) 

3591 

3592 svm_id = response_svm.get('records')[0]['uuid'] 

3593 

3594 self.client.send_request.assert_has_calls([ 

3595 mock.call('/svm/svms', 'get', query=query, 

3596 enable_tunneling=False), 

3597 mock.call(f'/protocols/fpolicy/{svm_id}/policies' 

3598 f'/{fake.FPOLICY_POLICY_NAME}', 'patch') 

3599 ]) 

3600 

3601 @ddt.data([fake.NO_RECORDS_RESPONSE_REST, None], 

3602 [fake.SVMS_LIST_SIMPLE_RESPONSE_REST, 

3603 netapp_api.api.NaApiError(code="1000", message="")]) 

3604 def test_disable_fpolicy_policy_failure(self, side_effect): 

3605 self.mock_object(self.client, 

3606 'send_request', 

3607 mock.Mock(side_effect=side_effect)) 

3608 

3609 self.assertRaises(exception.NetAppException, 

3610 self.client.disable_fpolicy_policy, 

3611 fake.FPOLICY_POLICY_NAME) 

3612 

3613 @ddt.data({'qos_policy_group_name': None, 

3614 'adaptive_qos_policy_group_name': None}, 

3615 {'qos_policy_group_name': fake.QOS_POLICY_GROUP_NAME, 

3616 'adaptive_qos_policy_group_name': None}, 

3617 {'qos_policy_group_name': None, 

3618 'adaptive_qos_policy_group_name': 

3619 fake.ADAPTIVE_QOS_POLICY_GROUP_NAME}, 

3620 {'mount_point_name': None}, 

3621 ) 

3622 @ddt.unpack 

3623 def test_create_volume_clone(self, qos_policy_group_name=None, 

3624 adaptive_qos_policy_group_name=None, 

3625 mount_point_name=None): 

3626 self.mock_object(self.client, 'send_request') 

3627 

3628 if qos_policy_group_name: 

3629 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

3630 uuid = volume["uuid"] 

3631 self.mock_object(self.client, 

3632 '_get_volume_by_args', 

3633 mock.Mock(return_value=volume)) 

3634 self.mock_object(self.client, 'volume_clone_split_start') 

3635 self.mock_object( 

3636 self.client.connection, 'get_vserver', 

3637 mock.Mock(return_value='fake_svm')) 

3638 set_qos_adapt_mock = self.mock_object( 

3639 self.client, 

3640 'set_qos_adaptive_policy_group_for_volume') 

3641 

3642 self.client.create_volume_clone( 

3643 fake.SHARE_NAME, 

3644 fake.PARENT_SHARE_NAME, 

3645 fake.PARENT_SNAPSHOT_NAME, 

3646 mount_point_name=mount_point_name, 

3647 qos_policy_group=qos_policy_group_name, 

3648 adaptive_qos_policy_group=adaptive_qos_policy_group_name) 

3649 

3650 body = { 

3651 'name': fake.SHARE_NAME, 

3652 'clone.parent_volume.name': fake.PARENT_SHARE_NAME, 

3653 'clone.parent_snapshot.name': fake.PARENT_SNAPSHOT_NAME, 

3654 'nas.path': '/%s' % (mount_point_name or fake.SHARE_NAME), 

3655 'clone.is_flexclone': 'true', 

3656 'svm.name': 'fake_svm', 

3657 } 

3658 

3659 if adaptive_qos_policy_group_name is not None: 

3660 set_qos_adapt_mock.assert_called_once_with( 

3661 fake.SHARE_NAME, fake.ADAPTIVE_QOS_POLICY_GROUP_NAME 

3662 ) 

3663 

3664 if qos_policy_group_name: 

3665 self.client._get_volume_by_args.assert_called_once_with( 

3666 vol_name=fake.SHARE_NAME) 

3667 self.client.send_request.assert_has_calls([ 

3668 mock.call('/storage/volumes', 'post', body=body), 

3669 mock.call(f'/storage/volumes/{uuid}', 'patch', 

3670 body={'qos.policy.name': qos_policy_group_name}) 

3671 ]) 

3672 else: 

3673 self.client.send_request.assert_called_once_with( 

3674 '/storage/volumes', 'post', body=body) 

3675 self.assertFalse(self.client.volume_clone_split_start.called) 

3676 

3677 @ddt.data(True, False) 

3678 def test_create_volume_split(self, split): 

3679 self.mock_object(self.client, 'send_request') 

3680 self.mock_object(self.client, 'volume_clone_split_start') 

3681 self.mock_object( 

3682 self.client.connection, 'get_vserver', 

3683 mock.Mock(return_value='fake_svm')) 

3684 body = { 

3685 'name': fake.SHARE_NAME, 

3686 'clone.parent_volume.name': fake.PARENT_SHARE_NAME, 

3687 'clone.parent_snapshot.name': fake.PARENT_SNAPSHOT_NAME, 

3688 'nas.path': '/%s' % fake.SHARE_NAME, 

3689 'clone.is_flexclone': 'true', 

3690 'svm.name': 'fake_svm', 

3691 } 

3692 

3693 self.client.create_volume_clone( 

3694 fake.SHARE_NAME, 

3695 fake.PARENT_SHARE_NAME, 

3696 fake.PARENT_SNAPSHOT_NAME, 

3697 split=split) 

3698 

3699 self.assertFalse(self.client.volume_clone_split_start.called) 

3700 

3701 self.client.send_request.assert_called_once_with( 

3702 '/storage/volumes', 'post', body=body) 

3703 

3704 def test_quiesce_snapmirror_vol(self): 

3705 mock__quiesce_snapmirror = self.mock_object( 

3706 self.client, '_quiesce_snapmirror') 

3707 

3708 self.client.quiesce_snapmirror_vol(fake.SM_SOURCE_VSERVER, 

3709 fake.SM_SOURCE_VOLUME, 

3710 fake.SM_DEST_VSERVER, 

3711 fake.SM_DEST_VOLUME) 

3712 

3713 mock__quiesce_snapmirror.assert_called_once_with( 

3714 source_vserver=fake.SM_SOURCE_VSERVER, 

3715 source_volume=fake.SM_SOURCE_VOLUME, 

3716 dest_vserver=fake.SM_DEST_VSERVER, 

3717 dest_volume=fake.SM_DEST_VOLUME) 

3718 

3719 def test__quiesce_snapmirror(self): 

3720 fake_snapmirror = fake.REST_GET_SNAPMIRRORS_RESPONSE 

3721 fake_uuid = fake_snapmirror[0]['uuid'] 

3722 fake_body = {'state': 'paused'} 

3723 

3724 self.mock_object(self.client, 'send_request') 

3725 

3726 mock_get_snap = self.mock_object( 

3727 self.client, '_get_snapmirrors', 

3728 mock.Mock(return_value=fake_snapmirror)) 

3729 

3730 self.client._quiesce_snapmirror() 

3731 

3732 mock_get_snap.assert_called_once() 

3733 self.client.send_request.assert_called_once_with( 

3734 f'/snapmirror/relationships/{fake_uuid}', 'patch', body=fake_body) 

3735 

3736 def test_break_snapmirror_vol(self): 

3737 

3738 self.mock_object(self.client, '_break_snapmirror') 

3739 

3740 self.client.break_snapmirror_vol(source_vserver=fake.SM_SOURCE_VSERVER, 

3741 source_volume=fake.SM_SOURCE_VOLUME, 

3742 dest_vserver=fake.SM_DEST_VSERVER, 

3743 dest_volume=fake.SM_DEST_VOLUME) 

3744 

3745 self.client._break_snapmirror.assert_called_once_with( 

3746 source_vserver=fake.SM_SOURCE_VSERVER, 

3747 source_volume=fake.SM_SOURCE_VOLUME, 

3748 dest_vserver=fake.SM_DEST_VSERVER, 

3749 dest_volume=fake.SM_DEST_VOLUME) 

3750 

3751 def test__break_snapmirror(self): 

3752 fake_snapmirror = fake.REST_GET_SNAPMIRRORS_RESPONSE 

3753 fake_uuid = fake_snapmirror[0]['uuid'] 

3754 fake_body = {'state': 'broken_off'} 

3755 

3756 self.mock_object(self.client, 'send_request') 

3757 

3758 mock_get_snap = self.mock_object( 

3759 self.client, '_get_snapmirrors', 

3760 mock.Mock(return_value=fake_snapmirror)) 

3761 

3762 self.client._break_snapmirror() 

3763 

3764 mock_get_snap.assert_called_once() 

3765 self.client.send_request.assert_called_once_with( 

3766 f'/snapmirror/relationships/{fake_uuid}', 'patch', body=fake_body) 

3767 

3768 def test_resume_snapmirror_vol(self): 

3769 mock = self.mock_object(self.client, '_resume_snapmirror') 

3770 self.client.resume_snapmirror_vol(fake.SM_SOURCE_VSERVER, 

3771 fake.SM_SOURCE_VOLUME, 

3772 fake.SM_DEST_VSERVER, 

3773 fake.SM_DEST_VOLUME) 

3774 mock.assert_called_once_with( 

3775 source_vserver=fake.SM_SOURCE_VSERVER, 

3776 dest_vserver=fake.SM_DEST_VSERVER, 

3777 source_volume=fake.SM_SOURCE_VOLUME, 

3778 dest_volume=fake.SM_DEST_VOLUME) 

3779 

3780 def test_resync_snapmirror_vol(self): 

3781 mock = self.mock_object(self.client, '_resync_snapmirror') 

3782 self.client.resync_snapmirror_vol(fake.SM_SOURCE_VSERVER, 

3783 fake.SM_SOURCE_VOLUME, 

3784 fake.SM_DEST_VSERVER, 

3785 fake.SM_DEST_VOLUME) 

3786 mock.assert_called_once_with( 

3787 source_vserver=fake.SM_SOURCE_VSERVER, 

3788 dest_vserver=fake.SM_DEST_VSERVER, 

3789 source_volume=fake.SM_SOURCE_VOLUME, 

3790 dest_volume=fake.SM_DEST_VOLUME) 

3791 

3792 @ddt.data('async', 'sync') 

3793 def test__resume_snapmirror(self, snapmirror_policy): 

3794 api_response = copy.deepcopy(fake.REST_GET_SNAPMIRRORS_RESPONSE) 

3795 api_response[0]['policy-type'] = snapmirror_policy 

3796 mock_snapmirror = self.mock_object( 

3797 self.client, '_get_snapmirrors', 

3798 mock.Mock(return_value=api_response)) 

3799 mock_request = self.mock_object(self.client, 'send_request') 

3800 

3801 snapmirror_uuid = fake.FAKE_UUID 

3802 

3803 body_resync = {} 

3804 if snapmirror_policy == 'async': 

3805 body_resync['state'] = 'snapmirrored' 

3806 elif snapmirror_policy == 'sync': 3806 ↛ 3809line 3806 didn't jump to line 3809 because the condition on line 3806 was always true

3807 body_resync['state'] = 'in_sync' 

3808 

3809 self.client._resume_snapmirror(fake.SM_SOURCE_PATH, fake.SM_DEST_PATH) 

3810 

3811 mock_request.assert_called_once_with('/snapmirror/relationships/' + 

3812 snapmirror_uuid, 'patch', 

3813 body=body_resync, 

3814 wait_on_accepted=False) 

3815 

3816 mock_snapmirror.assert_called_once_with( 

3817 source_path=fake.SM_SOURCE_PATH, 

3818 dest_path=fake.SM_DEST_PATH, 

3819 source_vserver=None, 

3820 source_volume=None, 

3821 dest_vserver=None, 

3822 dest_volume=None, 

3823 enable_tunneling=None, 

3824 list_destinations_only=None) 

3825 

3826 def test__resync_snapmirror(self): 

3827 mock = self.mock_object(self.client, '_resume_snapmirror') 

3828 self.client._resume_snapmirror(fake.SM_SOURCE_PATH, 

3829 fake.SM_DEST_PATH) 

3830 mock.assert_called_once_with(fake.SM_SOURCE_PATH, fake.SM_DEST_PATH) 

3831 

3832 def test_add_nfs_export_rule(self): 

3833 

3834 mock_get_nfs_export_rule_indices = self.mock_object( 

3835 self.client, '_get_nfs_export_rule_indices', 

3836 mock.Mock(return_value=[])) 

3837 mock_add_nfs_export_rule = self.mock_object( 

3838 self.client, '_add_nfs_export_rule') 

3839 mock_update_nfs_export_rule = self.mock_object( 

3840 self.client, '_update_nfs_export_rule') 

3841 auth_methods = ['sys'] 

3842 

3843 self.client.add_nfs_export_rule(fake.EXPORT_POLICY_NAME, 

3844 fake.IP_ADDRESS, 

3845 False, 

3846 auth_methods) 

3847 

3848 mock_get_nfs_export_rule_indices.assert_called_once_with( 

3849 fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS) 

3850 mock_add_nfs_export_rule.assert_called_once_with( 

3851 fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS, False, auth_methods) 

3852 self.assertFalse(mock_update_nfs_export_rule.called) 

3853 

3854 def test_set_qos_policy_group_for_volume(self): 

3855 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

3856 mock_get_volume = self.mock_object( 

3857 self.client, '_get_volume_by_args', 

3858 mock.Mock(return_value=volume)) 

3859 

3860 mock_send_request = self.mock_object( 

3861 self.client, 'send_request') 

3862 

3863 self.client.set_qos_policy_group_for_volume( 

3864 volume['name'], fake.QOS_POLICY_GROUP_NAME) 

3865 

3866 mock_get_volume.assert_called_once_with(vol_name=volume['name']) 

3867 

3868 body = {'qos.policy.name': fake.QOS_POLICY_GROUP_NAME} 

3869 mock_send_request.assert_called_once_with( 

3870 f'/storage/volumes/{volume["uuid"]}', 'patch', body=body) 

3871 

3872 def test__update_snapmirror(self): 

3873 api_response = copy.deepcopy(fake.REST_GET_SNAPMIRRORS_RESPONSE) 

3874 mock_snapmirror = self.mock_object( 

3875 self.client, '_get_snapmirrors', 

3876 mock.Mock(return_value=api_response)) 

3877 mock_sr = self.mock_object(self.client, 'send_request') 

3878 self.client._update_snapmirror(fake.SM_SOURCE_PATH, 

3879 fake.SM_DEST_PATH, 

3880 fake.SM_SOURCE_VSERVER, 

3881 fake.SM_DEST_VSERVER, 

3882 fake.SM_SOURCE_VOLUME, 

3883 fake.SM_DEST_VOLUME) 

3884 mock_sr.assert_called_once() 

3885 mock_snapmirror.assert_called_once_with( 

3886 source_path=fake.SM_SOURCE_PATH, 

3887 dest_path=fake.SM_DEST_PATH, 

3888 source_vserver=fake.SM_SOURCE_VSERVER, 

3889 source_volume=fake.SM_SOURCE_VOLUME, 

3890 dest_vserver=fake.SM_DEST_VSERVER, 

3891 dest_volume=fake.SM_DEST_VOLUME, 

3892 enable_tunneling=None, 

3893 list_destinations_only=None) 

3894 

3895 def test_get_cluster_name(self): 

3896 """Get all available cluster nodes.""" 

3897 

3898 return_value = fake.FAKE_GET_CLUSTER_NODE_VERSION_REST 

3899 

3900 self.mock_object(self.client, 'send_request', 

3901 mock.Mock(return_value=return_value)) 

3902 test_result = self.client.get_cluster_name() 

3903 

3904 self.client.send_request.assert_called_once_with( 

3905 '/cluster', 'get', enable_tunneling=False 

3906 ) 

3907 

3908 expected_result = return_value.get('name') 

3909 

3910 self.assertEqual(test_result, expected_result) 

3911 

3912 @ddt.data(True, False) 

3913 def test_check_volume_clone_split_completed(self, clone): 

3914 mock__get_volume_by_args = self.mock_object( 

3915 self.client, '_get_volume_by_args', 

3916 mock.Mock(return_value={'clone': {'is_flexclone': clone}})) 

3917 

3918 res = self.client.check_volume_clone_split_completed( 

3919 fake.VOLUME_NAMES[0]) 

3920 

3921 mock__get_volume_by_args.assert_called_once_with( 

3922 vol_name=fake.VOLUME_NAMES[0], fields='clone.is_flexclone') 

3923 self.assertEqual(not clone, res) 

3924 

3925 def test_rehost_volume(self): 

3926 self.mock_object(self.client, 'send_request') 

3927 self.client.rehost_volume("fake_vol", "fake_svm", "fake_svm_2") 

3928 body = { 

3929 "vserver": "fake_svm", 

3930 "volume": "fake_vol", 

3931 "destination_vserver": "fake_svm_2" 

3932 } 

3933 self.client.send_request.assert_called_once_with( 

3934 "/private/cli/volume/rehost", 'post', body=body) 

3935 

3936 def test_get_net_options(self): 

3937 

3938 res = self.client.get_net_options() 

3939 

3940 self.assertTrue(res['ipv6-enabled']) 

3941 

3942 def test_set_qos_adaptive_policy_group_for_volume(self): 

3943 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

3944 mock_get_volume = self.mock_object( 

3945 self.client, '_get_volume_by_args', 

3946 mock.Mock(return_value=volume)) 

3947 

3948 mock_send_request = self.mock_object( 

3949 self.client, 'send_request') 

3950 

3951 self.client.set_qos_adaptive_policy_group_for_volume( 

3952 volume['name'], fake.QOS_POLICY_GROUP_NAME) 

3953 

3954 mock_get_volume.assert_called_once_with(vol_name=volume['name']) 

3955 

3956 body = {'qos.policy.name': fake.QOS_POLICY_GROUP_NAME} 

3957 mock_send_request.assert_called_once_with( 

3958 f'/storage/volumes/{volume["uuid"]}', 'patch', body=body) 

3959 

3960 def test__list_vservers(self): 

3961 api_response = fake.VSERVER_DATA_LIST_RESPONSE_REST 

3962 self.mock_object(self.client, 

3963 'send_request', 

3964 mock.Mock(return_value=api_response)) 

3965 result = self.client._list_vservers() 

3966 query = { 

3967 'fields': 'name', 

3968 } 

3969 self.client.send_request.assert_has_calls([ 

3970 mock.call('/svm/svms', 'get', query=query, 

3971 enable_tunneling=False)]) 

3972 self.assertListEqual( 

3973 [fake.VSERVER_NAME, fake.VSERVER_NAME_2], result) 

3974 

3975 def test_list_vservers_not_found(self): 

3976 api_response = fake.NO_RECORDS_RESPONSE_REST 

3977 self.mock_object(self.client, 

3978 'send_request', 

3979 mock.Mock(return_value=api_response)) 

3980 result = self.client._list_vservers() 

3981 self.assertListEqual([], result) 

3982 

3983 def test_get_ems_log_destination_vserver(self): 

3984 mock_list_vservers = self.mock_object( 

3985 self.client, 

3986 '_list_vservers', 

3987 mock.Mock(return_value=[fake.VSERVER_NAME])) 

3988 result = self.client._get_ems_log_destination_vserver() 

3989 mock_list_vservers.assert_called_once_with() 

3990 self.assertEqual(fake.VSERVER_NAME, result) 

3991 

3992 def test_get_ems_log_destination_vserver_not_found(self): 

3993 mock_list_vservers = self.mock_object( 

3994 self.client, 

3995 '_list_vservers', 

3996 mock.Mock(return_value=[])) 

3997 

3998 self.assertRaises(exception.NotFound, 

3999 self.client._get_ems_log_destination_vserver) 

4000 

4001 mock_list_vservers.assert_called_once_with() 

4002 

4003 def test_send_ems_log_message(self): 

4004 

4005 message_dict = { 

4006 'computer-name': '25-dev-vm', 

4007 'event-source': 'Cinder driver NetApp_iSCSI_Cluster_direct', 

4008 'app-version': '20.1.0.dev|vendor|Linux-5.4.0-120-generic-x86_64', 

4009 'category': 'provisioning', 

4010 'log-level': '5', 

4011 'auto-support': 'false', 

4012 'event-id': '1', 

4013 'event-description': 

4014 '{"pools": {"vserver": "vserver_name",' 

4015 + '"aggregates": [], "flexvols": ["flexvol_01"]}}' 

4016 } 

4017 

4018 body = { 

4019 'computer_name': message_dict['computer-name'], 

4020 'event_source': message_dict['event-source'], 

4021 'app_version': message_dict['app-version'], 

4022 'category': message_dict['category'], 

4023 'severity': 'notice', 

4024 'autosupport_required': message_dict['auto-support'] == 'true', 

4025 'event_id': message_dict['event-id'], 

4026 'event_description': message_dict['event-description'], 

4027 } 

4028 

4029 self.mock_object(self.client, '_get_ems_log_destination_vserver', 

4030 mock.Mock(return_value='vserver_name')) 

4031 self.mock_object(self.client, 'send_request') 

4032 

4033 self.client.send_ems_log_message(message_dict) 

4034 

4035 self.client.send_request.assert_called_once_with( 

4036 '/support/ems/application-logs', 'post', body=body) 

4037 

4038 @ddt.data('cp_phase_times', 'domain_busy') 

4039 def test_get_performance_counter_info(self, counter_name): 

4040 

4041 response1 = fake.PERF_COUNTER_LIST_INFO_WAFL_RESPONSE_REST 

4042 response2 = fake.PERF_COUNTER_TABLE_ROWS_WAFL 

4043 

4044 object_name = 'wafl' 

4045 

4046 mock_send_request = self.mock_object( 

4047 self.client, 'send_request', 

4048 mock.Mock(side_effect=[response1, response2])) 

4049 

4050 result = self.client.get_performance_counter_info(object_name, 

4051 counter_name) 

4052 

4053 expected = { 

4054 'name': 'cp_phase_times', 

4055 'base-counter': 'total_cp_msecs', 

4056 'labels': fake.PERF_COUNTER_TOTAL_CP_MSECS_LABELS_RESULT, 

4057 } 

4058 

4059 query1 = { 

4060 'counter_schemas.name': counter_name, 

4061 'fields': 'counter_schemas.*' 

4062 } 

4063 

4064 query2 = { 

4065 'counters.name': counter_name, 

4066 'fields': 'counters.*' 

4067 } 

4068 

4069 if counter_name == 'domain_busy': 

4070 expected['name'] = 'domain_busy' 

4071 expected['labels'] = ( 

4072 fake.PERF_COUNTER_TOTAL_CP_MSECS_LABELS_REST) 

4073 query1['counter_schemas.name'] = 'domain_busy_percent' 

4074 query2['counters.name'] = 'domain_busy_percent' 

4075 

4076 self.assertEqual(expected, result) 

4077 

4078 mock_send_request.assert_has_calls([ 

4079 mock.call(f'/cluster/counter/tables/{object_name}', 

4080 'get', query=query1), 

4081 mock.call(f'/cluster/counter/tables/{object_name}/rows', 

4082 'get', query=query2, enable_tunneling=False), 

4083 ]) 

4084 

4085 def test_get_performance_counter_info_not_found_rows(self): 

4086 response1 = fake.PERF_COUNTER_LIST_INFO_WAFL_RESPONSE_REST 

4087 response2 = fake.NO_RECORDS_RESPONSE_REST 

4088 

4089 object_name = 'wafl' 

4090 counter_name = 'cp_phase_times' 

4091 

4092 self.mock_object( 

4093 self.client, 'send_request', 

4094 mock.Mock(side_effect=[response1, response2])) 

4095 

4096 result = self.client.get_performance_counter_info(object_name, 

4097 counter_name) 

4098 

4099 expected = { 

4100 'name': 'cp_phase_times', 

4101 'base-counter': 'total_cp_msecs', 

4102 'labels': [], 

4103 } 

4104 self.assertEqual(expected, result) 

4105 

4106 def test_get_performance_instance_uuids(self): 

4107 response = fake.PERF_COUNTER_TABLE_ROWS_WAFL 

4108 

4109 mock_send_request = self.mock_object( 

4110 self.client, 'send_request', 

4111 mock.Mock(return_value=response)) 

4112 

4113 object_name = 'wafl' 

4114 result = self.client.get_performance_instance_uuids( 

4115 object_name, fake.NODE_NAME) 

4116 

4117 expected = [fake.NODE_NAME + ':wafl'] 

4118 self.assertEqual(expected, result) 

4119 

4120 query = { 

4121 'id': fake.NODE_NAME + ':*', 

4122 } 

4123 mock_send_request.assert_called_once_with( 

4124 f'/cluster/counter/tables/{object_name}/rows', 

4125 'get', query=query, enable_tunneling=False) 

4126 

4127 def test_get_performance_counters(self): 

4128 response = fake.PERF_GET_INSTANCES_PROCESSOR_RESPONSE_REST 

4129 

4130 mock_send_request = self.mock_object( 

4131 self.client, 'send_request', 

4132 mock.Mock(return_value=response)) 

4133 

4134 instance_uuids = [ 

4135 fake.NODE_NAME + ':processor0', 

4136 fake.NODE_NAME + ':processor1', 

4137 ] 

4138 object_name = 'processor' 

4139 counter_names = ['domain_busy', 'processor_elapsed_time'] 

4140 rest_counter_names = ['domain_busy_percent', 'elapsed_time'] 

4141 result = self.client.get_performance_counters(object_name, 

4142 instance_uuids, 

4143 counter_names) 

4144 

4145 expected = fake.PERF_COUNTERS_PROCESSOR_EXPECTED 

4146 self.assertEqual(expected, result) 

4147 

4148 query = { 

4149 'id': '|'.join(instance_uuids), 

4150 'counters.name': '|'.join(rest_counter_names), 

4151 'fields': 'id,counter_table.name,counters.*', 

4152 } 

4153 

4154 mock_send_request.assert_called_once_with( 

4155 f'/cluster/counter/tables/{object_name}/rows', 

4156 'get', query=query) 

4157 

4158 def test__get_deleted_nfs_export_policies(self): 

4159 

4160 api_response = fake.DELETED_EXPORT_POLICY_GET_ITER_RESPONSE_REST 

4161 self.mock_object(self.client, 

4162 'send_request', 

4163 mock.Mock(return_value=api_response)) 

4164 

4165 result = self.client._get_deleted_nfs_export_policies() 

4166 

4167 query = { 

4168 'name': 'deleted_manila_*', 

4169 'fields': 'name,svm.name', 

4170 } 

4171 

4172 self.assertSequenceEqual(fake.DELETED_EXPORT_POLICIES, result) 

4173 self.client.send_request.assert_has_calls([ 

4174 mock.call('/protocols/nfs/export-policies', 

4175 'get', query=query)]) 

4176 

4177 def test_prune_deleted_nfs_export_policies(self): 

4178 self.mock_object(self.client, '_get_deleted_nfs_export_policies', 

4179 mock.Mock(return_value=fake.DELETED_EXPORT_POLICIES)) 

4180 self.mock_object(self.client, 'delete_nfs_export_policy') 

4181 

4182 self.client.prune_deleted_nfs_export_policies() 

4183 

4184 self.assertTrue(self.client.delete_nfs_export_policy.called) 

4185 

4186 self.client.delete_nfs_export_policy.assert_has_calls([ 

4187 mock.call(fake.DELETED_EXPORT_POLICIES[fake.VSERVER_NAME][0]), 

4188 mock.call(fake.DELETED_EXPORT_POLICIES[fake.VSERVER_NAME][1]), 

4189 mock.call(fake.DELETED_EXPORT_POLICIES[fake.VSERVER_NAME_2][0]), 

4190 ]) 

4191 

4192 def test_prune_deleted_nfs_export_policies_api_error(self): 

4193 self.mock_object(self.client, 

4194 '_get_deleted_nfs_export_policies', 

4195 mock.Mock(return_value=fake.DELETED_EXPORT_POLICIES)) 

4196 self.mock_object(self.client, 

4197 'delete_nfs_export_policy', 

4198 self._mock_api_error()) 

4199 

4200 self.client.prune_deleted_nfs_export_policies() 

4201 

4202 def test__get_security_key_manager_nve_support_enabled(self): 

4203 api_response = fake.SECUTITY_KEY_MANAGER_SUPPORT_RESPONSE_TRUE_REST 

4204 self.mock_object(self.client, 

4205 'send_request', 

4206 mock.Mock(return_value=api_response)) 

4207 

4208 result = self.client._get_security_key_manager_nve_support() 

4209 

4210 self.assertTrue(result) 

4211 

4212 query = {'fields': 'volume_encryption.*'} 

4213 self.client.send_request.assert_has_calls([ 

4214 mock.call('/security/key-managers', 'get', query=query)]) 

4215 

4216 def test__get_security_key_manager_nve_support_disabled(self): 

4217 api_response = fake.SECUTITY_KEY_MANAGER_SUPPORT_RESPONSE_FALSE_REST 

4218 self.mock_object(self.client, 

4219 'send_request', 

4220 mock.Mock(return_value=api_response)) 

4221 

4222 result = self.client._get_security_key_manager_nve_support() 

4223 

4224 self.assertFalse(result) 

4225 

4226 query = {'fields': 'volume_encryption.*'} 

4227 self.client.send_request.assert_has_calls([ 

4228 mock.call('/security/key-managers', 'get', query=query)]) 

4229 

4230 def test__get_security_key_manager_nve_support_no_records(self): 

4231 self.mock_object(self.client, 

4232 'send_request', 

4233 mock.Mock(return_value=fake.NO_RECORDS_RESPONSE_REST)) 

4234 

4235 result = self.client._get_security_key_manager_nve_support() 

4236 

4237 self.assertFalse(result) 

4238 

4239 query = {'fields': 'volume_encryption.*'} 

4240 self.client.send_request.assert_has_calls([ 

4241 mock.call('/security/key-managers', 'get', query=query)]) 

4242 

4243 def test__get_security_key_manager_nve_support_no_license(self): 

4244 self.mock_object(self.client, 

4245 'send_request', 

4246 self._mock_api_error()) 

4247 

4248 result = self.client._get_security_key_manager_nve_support() 

4249 

4250 self.assertFalse(result) 

4251 

4252 query = {'fields': 'volume_encryption.*'} 

4253 self.client.send_request.assert_has_calls([ 

4254 mock.call('/security/key-managers', 'get', query=query)]) 

4255 

4256 def test_get_nfs_config_default(self): 

4257 api_response = fake.NFS_CONFIG_DEFAULT_RESULT_REST 

4258 self.mock_object(self.client, 

4259 'send_request', 

4260 mock.Mock(return_value=api_response)) 

4261 

4262 result = self.client.get_nfs_config_default(['tcp-max-xfer-size', 

4263 'udp-max-xfer-size']) 

4264 expected = { 

4265 'tcp-max-xfer-size': '65536', 

4266 'udp-max-xfer-size': '32768', 

4267 } 

4268 self.assertEqual(expected, result) 

4269 

4270 query = {'fields': 'transport.*'} 

4271 self.client.send_request.assert_called_once_with( 

4272 '/protocols/nfs/services/', 'get', query=query) 

4273 

4274 def test_get_kerberos_service_principal_name(self): 

4275 

4276 spn = self.client._get_kerberos_service_principal_name( 

4277 fake.KERBEROS_SECURITY_SERVICE, fake.VSERVER_NAME 

4278 ) 

4279 self.assertEqual(fake.KERBEROS_SERVICE_PRINCIPAL_NAME, spn) 

4280 

4281 def test_get_cifs_server_name(self): 

4282 

4283 expected_return = 'FAKE-VSE-SERVER' 

4284 

4285 cifs_server = self.client._get_cifs_server_name(fake.VSERVER_NAME) 

4286 

4287 self.assertEqual(expected_return, cifs_server) 

4288 

4289 def test_list_network_interfaces(self): 

4290 

4291 api_response = fake.GENERIC_NETWORK_INTERFACES_GET_REPONSE 

4292 expected_result = [fake.LIF_NAME] 

4293 

4294 self.mock_object(self.client, 

4295 'send_request', 

4296 mock.Mock(return_value=api_response)) 

4297 self.mock_object(self.client, '_has_records', 

4298 mock.Mock(return_value=True)) 

4299 

4300 fake_query = { 

4301 'fields': 'name' 

4302 } 

4303 

4304 result = self.client.list_network_interfaces() 

4305 

4306 self.client.send_request.assert_has_calls([ 

4307 mock.call('/network/ip/interfaces', 'get', query=fake_query)]) 

4308 self.assertEqual(expected_result, result) 

4309 

4310 def test_create_kerberos_realm(self): 

4311 

4312 fake_security = fake.KERBEROS_SECURITY_SERVICE 

4313 

4314 fake_body = { 

4315 'comment': '', 

4316 'kdc.ip': fake_security['server'], 

4317 'kdc.port': '88', 

4318 'kdc.vendor': 'other', 

4319 'name': fake_security['domain'].upper(), 

4320 } 

4321 

4322 self.mock_object(self.client, 'send_request') 

4323 

4324 self.client.create_kerberos_realm(fake.KERBEROS_SECURITY_SERVICE) 

4325 

4326 self.client.send_request.assert_called_once_with( 

4327 '/protocols/nfs/kerberos/realms', 'post', body=fake_body) 

4328 

4329 def test_configure_kerberos(self): 

4330 

4331 fake_api_response = fake.NFS_LIFS_REST 

4332 fake_security = fake.KERBEROS_SECURITY_SERVICE 

4333 fake_keberos_name = fake.KERBEROS_SERVICE_PRINCIPAL_NAME 

4334 

4335 fake_body = { 

4336 'password': fake_security['password'], 

4337 'user': fake_security['user'], 

4338 'interface.name': fake.LIF_NAME, 

4339 'enabled': True, 

4340 'spn': fake_keberos_name 

4341 } 

4342 

4343 self.mock_object(self.client, 'configure_dns') 

4344 self_get_kerberos = self.mock_object( 

4345 self.client, '_get_kerberos_service_principal_name', 

4346 mock.Mock(return_value=fake_keberos_name)) 

4347 self.mock_object(self.client, 'get_network_interfaces', 

4348 mock.Mock(return_value=fake_api_response)) 

4349 self.mock_object(self.client, 'send_request') 

4350 

4351 self.client.configure_kerberos(fake.KERBEROS_SECURITY_SERVICE, 

4352 fake.VSERVER_NAME) 

4353 

4354 self.client.configure_dns.assert_called_once_with( 

4355 fake.KERBEROS_SECURITY_SERVICE, vserver_name=fake.VSERVER_NAME) 

4356 self_get_kerberos.assert_called_once_with( 

4357 fake.KERBEROS_SECURITY_SERVICE, fake.VSERVER_NAME) 

4358 self.client.get_network_interfaces.assert_called_once_with() 

4359 self.client.send_request.assert_has_calls([ 

4360 mock.call('/protocols/nfs/kerberos/interfaces/fake_uuid_1', 

4361 'patch', body=fake_body), 

4362 mock.call('/protocols/nfs/kerberos/interfaces/fake_uuid_2', 

4363 'patch', body=fake_body), 

4364 mock.call('/protocols/nfs/kerberos/interfaces/fake_uuid_3', 

4365 'patch', body=fake_body) 

4366 ]) 

4367 

4368 @ddt.data(fake.CIFS_SECURITY_SERVICE, fake.CIFS_SECURITY_SERVICE_3) 

4369 def test_configure_active_directory(self, security_service): 

4370 

4371 fake_security = copy.deepcopy(security_service) 

4372 

4373 fake_body1 = { 

4374 'ad_domain.user': fake_security['user'], 

4375 'ad_domain.password': fake_security['password'], 

4376 'force': 'true', 

4377 'name': 'FAKE-VSE-SERVER', 

4378 'ad_domain.fqdn': fake_security['domain'], 

4379 } 

4380 

4381 self.mock_object(self.client, 'configure_dns') 

4382 self.mock_object(self.client, 'set_preferred_dc') 

4383 self.mock_object(self.client, 'configure_cifs_aes_encryption') 

4384 self.mock_object(self.client, '_get_cifs_server_name', 

4385 mock.Mock(return_value='FAKE-VSE-SERVER')) 

4386 self.mock_object(self.client, 'send_request') 

4387 

4388 self.client.configure_active_directory(fake_security, 

4389 fake.VSERVER_NAME, 

4390 False) 

4391 

4392 self.client.configure_dns.assert_called_once_with( 

4393 fake_security, vserver_name=fake.VSERVER_NAME) 

4394 self.client.set_preferred_dc.assert_called_once_with( 

4395 fake_security, fake.VSERVER_NAME) 

4396 self.client.configure_cifs_aes_encryption.assert_called_once_with( 

4397 fake.VSERVER_NAME, False) 

4398 self.client._get_cifs_server_name.assert_called_once_with( 

4399 fake.VSERVER_NAME) 

4400 

4401 if fake_security['ou'] is not None: 4401 ↛ 4408line 4401 didn't jump to line 4408 because the condition on line 4401 was always true

4402 fake_body1['ad_domain.organizational_unit'] = fake_security['ou'] 

4403 fake_body2 = fake_body1 

4404 

4405 self.client.send_request.assert_called_once_with( 

4406 '/protocols/cifs/services', 'post', body=fake_body2) 

4407 else: 

4408 self.client.send_request.assert_called_once_with( 

4409 '/protocols/cifs/services', 'post', body=fake_body1) 

4410 

4411 def test__create_ldap_client_ad(self): 

4412 mock_dns = self.mock_object(self.client, 'configure_dns') 

4413 mock_sr = self.mock_object(self.client, 'send_request') 

4414 security_service = { 

4415 'domain': 'fake_domain', 

4416 'user': 'fake_user', 

4417 'ou': 'fake_ou', 

4418 'dns_ip': 'fake_ip', 

4419 'password': 'fake_password' 

4420 } 

4421 

4422 ad_domain = security_service.get('domain') 

4423 body = { 

4424 'port': '389', 

4425 'schema': 'MS-AD-BIS', 

4426 'bind_dn': (security_service.get('user') + '@' + ad_domain), 

4427 'bind_password': security_service.get('password'), 

4428 'svm.name': fake.VSERVER_NAME, 

4429 'base_dn': security_service.get('ou'), 

4430 'ad_domain': security_service.get('domain'), 

4431 } 

4432 

4433 self.client._create_ldap_client(security_service, 

4434 vserver_name=fake.VSERVER_NAME) 

4435 mock_dns.assert_called_once_with(security_service) 

4436 mock_sr.assert_called_once_with('/name-services/ldap', 'post', 

4437 body=body) 

4438 

4439 def test__create_ldap_client_linux(self): 

4440 mock_dns = self.mock_object(self.client, 'configure_dns') 

4441 mock_sr = self.mock_object(self.client, 'send_request') 

4442 security_service = { 

4443 'server': 'fake_server', 

4444 'user': 'fake_user', 

4445 'ou': 'fake_ou', 

4446 'dns_ip': 'fake_ip' 

4447 } 

4448 

4449 body = { 

4450 'port': '389', 

4451 'schema': 'RFC-2307', 

4452 'bind_dn': security_service.get('user'), 

4453 'bind_password': security_service.get('password'), 

4454 'svm.name': fake.VSERVER_NAME, 

4455 'base_dn': security_service.get('ou'), 

4456 'servers': [security_service.get('server')] 

4457 } 

4458 

4459 self.client._create_ldap_client(security_service, 

4460 vserver_name=fake.VSERVER_NAME) 

4461 mock_dns.assert_called_once_with(security_service) 

4462 mock_sr.assert_called_once_with('/name-services/ldap', 'post', 

4463 body=body) 

4464 

4465 def test_configure_dns_already_present(self): 

4466 dns_config = { 

4467 'domains': [fake.KERBEROS_SECURITY_SERVICE['domain']], 

4468 'dns-ips': [fake.KERBEROS_SECURITY_SERVICE['dns_ip']], 

4469 } 

4470 self.mock_object(self.client, 'get_dns_config', 

4471 mock.Mock(return_value=dns_config)) 

4472 self.mock_object(self.client, 'send_request', 

4473 mock.Mock(return_value=fake.FAKE_VOL_MOVE_STATUS)) 

4474 

4475 security_service = copy.deepcopy(fake.KERBEROS_SECURITY_SERVICE) 

4476 self.client.configure_dns(security_service) 

4477 

4478 net_dns_create_args = { 

4479 'domains': [security_service['domain']], 

4480 'servers': [security_service['dns_ip']], 

4481 } 

4482 

4483 uuid = fake.FAKE_VOL_MOVE_STATUS['records'][0]['uuid'] 

4484 self.client.send_request.assert_has_calls([ 

4485 mock.call('/svm/svms', 'get', 

4486 query={'name': None, 'fields': 'uuid'}), 

4487 mock.call(f'/name-services/dns/{uuid}', 'patch', 

4488 body=net_dns_create_args)]) 

4489 

4490 def test_configure_dns_for_active_directory(self): 

4491 

4492 self.mock_object(self.client, 'send_request', 

4493 mock.Mock(return_value=fake.FAKE_VOL_MOVE_STATUS)) 

4494 self.mock_object(self.client, 'get_dns_config', 

4495 mock.Mock(return_value={})) 

4496 

4497 security_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE) 

4498 self.client.configure_dns(security_service) 

4499 

4500 net_dns_create_args = { 

4501 'domains': [security_service['domain']], 

4502 'servers': [security_service['dns_ip']], 

4503 } 

4504 

4505 self.client.send_request.assert_has_calls([ 

4506 mock.call('/svm/svms', 'get', 

4507 query={'name': None, 'fields': 'uuid'}), 

4508 mock.call('/name-services/dns', 'post', body=net_dns_create_args)]) 

4509 

4510 def test_configure_dns_multiple_dns_ip(self): 

4511 

4512 self.mock_object(self.client, 'send_request', 

4513 mock.Mock(return_value=fake.FAKE_VOL_MOVE_STATUS)) 

4514 self.mock_object(self.client, 'get_dns_config', 

4515 mock.Mock(return_value={})) 

4516 mock_dns_ips = '10.0.0.5, 10.0.0.6, 10.0.0.7' 

4517 security_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE) 

4518 security_service['dns_ip'] = mock_dns_ips 

4519 

4520 args_dns = {'domains': [security_service['domain']], 

4521 'servers': ['10.0.0.5', 

4522 '10.0.0.6', 

4523 '10.0.0.7']} 

4524 self.client.configure_dns(security_service) 

4525 

4526 self.client.send_request.assert_has_calls([ 

4527 mock.call('/svm/svms', 'get', 

4528 query={'name': None, 'fields': 'uuid'}), 

4529 mock.call('/name-services/dns', 'post', body=args_dns)]) 

4530 

4531 def test_configure_dns_for_kerberos(self): 

4532 

4533 self.mock_object(self.client, 'send_request', 

4534 mock.Mock(return_value=fake.FAKE_VOL_MOVE_STATUS)) 

4535 self.mock_object(self.client, 'get_dns_config', 

4536 mock.Mock(return_value={})) 

4537 

4538 security_service = copy.deepcopy(fake.KERBEROS_SECURITY_SERVICE) 

4539 self.client.configure_dns(security_service) 

4540 

4541 net_dns_create_args = { 

4542 'domains': [security_service['domain']], 

4543 'servers': [security_service['dns_ip']], 

4544 } 

4545 

4546 self.client.send_request.assert_has_calls([ 

4547 mock.call('/svm/svms', 'get', 

4548 query={'name': None, 'fields': 'uuid'}), 

4549 mock.call('/name-services/dns', 'post', body=net_dns_create_args)]) 

4550 

4551 def test_configure_dns_api_error(self): 

4552 self.mock_object(self.client, 'send_request', self._mock_api_error()) 

4553 self.mock_object(self.client, 'get_dns_config', 

4554 mock.Mock(return_value={})) 

4555 self.mock_object(self.client, '_get_unique_svm_by_name', 

4556 mock.Mock(return_value={})) 

4557 

4558 self.assertRaises(exception.NetAppException, 

4559 self.client.configure_dns, 

4560 copy.deepcopy(fake.KERBEROS_SECURITY_SERVICE)) 

4561 

4562 def test_get_dns_config_no_response(self): 

4563 self.mock_object(self.client, 'send_request', 

4564 mock.Mock(side_effect=netapp_api.api.NaApiError)) 

4565 self.mock_object(self.client, '_get_unique_svm_by_name', 

4566 mock.Mock(return_value={})) 

4567 self.assertRaises(exception.NetAppException, 

4568 self.client.get_dns_config) 

4569 

4570 def test_get_dns_config(self): 

4571 api_response = fake.DNS_REST_RESPONSE 

4572 self.mock_object(self.client, 'send_request', 

4573 mock.Mock(return_value=api_response)) 

4574 fake_uuid = fake.FAKE_VOL_MOVE_STATUS['records'][0]['svm']['uuid'] 

4575 self.mock_object(self.client, '_get_unique_svm_by_name', 

4576 mock.Mock(return_value=fake_uuid)) 

4577 

4578 result = self.client.get_dns_config() 

4579 

4580 expected_result = { 

4581 'dns-state': 'true', 

4582 'domains': ['example.com', 'example2.example3.com'], 

4583 'dns-ips': ['10.224.65.20', '2001:db08:a0b:12f0::1'] 

4584 } 

4585 self.assertEqual(expected_result, result) 

4586 self.client.send_request.assert_called_once_with( 

4587 f'/name-services/dns/{fake_uuid}', 'get') 

4588 

4589 @ddt.data(fake.LDAP_AD_SECURITY_SERVICE, fake.CIFS_SECURITY_SERVICE_3, 

4590 fake.KERBEROS_SECURITY_SERVICE) 

4591 def test_setup_security_services(self, security_service): 

4592 fake_response = fake.FAKE_GET_CLUSTER_NODE_VERSION_REST 

4593 mock_request = self.mock_object(self.client, 'send_request', 

4594 mock.Mock(return_value=fake_response)) 

4595 self.mock_object(self.client, 'configure_ldap') 

4596 self.mock_object(self.client, 'configure_active_directory') 

4597 self.mock_object(self.client, 'configure_cifs_options') 

4598 self.mock_object(self.client, 'create_kerberos_realm') 

4599 self.mock_object(self.client, 'configure_kerberos') 

4600 

4601 ss_copy = copy.deepcopy(security_service) 

4602 self.client.setup_security_services([ss_copy], self.client, 

4603 'fake_vservername', False) 

4604 uuid = fake_response.get('records')[0].get('uuid') 

4605 body = { 

4606 'nsswitch.namemap': ['ldap', 'files'], 

4607 'nsswitch.group': ['ldap', 'files'], 

4608 'nsswitch.netgroup': ['ldap', 'files'], 

4609 'nsswitch.passwd': ['ldap', 'files'], 

4610 } 

4611 mock_request.assert_has_calls([ 

4612 mock.call('/svm/svms', 'get', 

4613 query={'name': 'fake_vservername', 'fields': 'uuid'}), 

4614 mock.call(f'/svm/svms/{uuid}', 'patch', body=body)]) 

4615 

4616 def test_modify_ldap_ad(self): 

4617 fake_svm_uuid = fake.FAKE_UUID 

4618 mock_svm_uuid = self.mock_object(self.client, 

4619 '_get_unique_svm_by_name', 

4620 mock.Mock(return_value=fake_svm_uuid)) 

4621 mock_sr = self.mock_object(self.client, 'send_request') 

4622 security_service = { 

4623 'domain': 'fake_domain', 

4624 'user': 'fake_user', 

4625 'ou': 'fake_ou', 

4626 'dns_ip': 'fake_ip', 

4627 'password': 'fake_password' 

4628 } 

4629 

4630 ad_domain = security_service.get('domain') 

4631 body = { 

4632 'port': '389', 

4633 'schema': 'MS-AD-BIS', 

4634 'bind_dn': (security_service.get('user') + '@' + ad_domain), 

4635 'bind_password': security_service.get('password'), 

4636 'base_dn': security_service.get('ou'), 

4637 'ad_domain': security_service.get('domain'), 

4638 } 

4639 

4640 self.client.modify_ldap(security_service, None) 

4641 mock_svm_uuid.assert_called_once_with(None) 

4642 mock_sr.assert_called_once_with(f'/name-services/ldap/{fake_svm_uuid}', 

4643 'patch', body=body) 

4644 

4645 def test_modify_ldap_linux(self): 

4646 fake_svm_uuid = fake.FAKE_UUID 

4647 mock_svm_uuid = self.mock_object(self.client, 

4648 '_get_unique_svm_by_name', 

4649 mock.Mock(return_value=fake_svm_uuid)) 

4650 mock_sr = self.mock_object(self.client, 'send_request') 

4651 security_service = { 

4652 'server': 'fake_server', 

4653 'user': 'fake_user', 

4654 'ou': 'fake_ou', 

4655 'dns_ip': 'fake_ip' 

4656 } 

4657 

4658 body = { 

4659 'port': '389', 

4660 'schema': 'RFC-2307', 

4661 'bind_dn': security_service.get('user'), 

4662 'bind_password': security_service.get('password'), 

4663 'base_dn': security_service.get('ou'), 

4664 'servers': [security_service.get('server')] 

4665 } 

4666 

4667 self.client.modify_ldap(security_service, None) 

4668 mock_svm_uuid.assert_called_once_with(None) 

4669 mock_sr.assert_called_once_with(f'/name-services/ldap/{fake_svm_uuid}', 

4670 'patch', body=body) 

4671 

4672 def test_update_kerberos_realm(self): 

4673 self.mock_object(self.client, 

4674 '_get_unique_svm_by_name', 

4675 mock.Mock(return_value=fake.FAKE_UUID)) 

4676 fake_uuid = fake.FAKE_UUID 

4677 self.mock_object(self.client, 'send_request') 

4678 self.client.update_kerberos_realm(fake.KERBEROS_SECURITY_SERVICE) 

4679 fake_domain = fake.KERBEROS_SECURITY_SERVICE['domain'] 

4680 body = { 

4681 'kdc-ip': fake.KERBEROS_SECURITY_SERVICE['server'], 

4682 } 

4683 

4684 self.client.send_request.assert_has_calls([ 

4685 mock.call( 

4686 f'/protocols/nfs/kerberos/realms/{fake_uuid}/{fake_domain}', 

4687 'patch', body=body)]) 

4688 

4689 def test__get_unique_svm_by_name(self): 

4690 response = fake.SVMS_LIST_SIMPLE_RESPONSE_REST 

4691 svm = fake.SVM_ITEM_SIMPLE_RESPONSE_REST['uuid'] 

4692 

4693 fake_query = { 

4694 'name': fake.VSERVER_NAME, 

4695 'fields': 'uuid' 

4696 } 

4697 

4698 self.mock_object(self.client, 'send_request', 

4699 mock.Mock(return_value=response)) 

4700 

4701 result = self.client._get_unique_svm_by_name( 

4702 fake.VSERVER_NAME) 

4703 

4704 self.client.send_request.assert_called_once_with( 

4705 '/svm/svms', 'get', query=fake_query) 

4706 

4707 self.assertEqual(svm, result) 

4708 

4709 def test_update_dns_configuration(self): 

4710 dns_config = { 

4711 'domains': [fake.KERBEROS_SECURITY_SERVICE['domain']], 

4712 'dns-ips': [fake.KERBEROS_SECURITY_SERVICE['dns_ip']], 

4713 } 

4714 

4715 body = { 

4716 'domains': [fake.KERBEROS_SECURITY_SERVICE['domain']], 

4717 'servers': [fake.KERBEROS_SECURITY_SERVICE['dns_ip']] 

4718 } 

4719 

4720 fake_uuid = 'fake_uuid' 

4721 

4722 self.mock_object(self.client, 'get_dns_config', 

4723 mock.Mock(return_value=dns_config)) 

4724 

4725 self.mock_object(self.client, 

4726 '_get_unique_svm_by_name', 

4727 mock.Mock(return_value=fake_uuid)) 

4728 

4729 self.mock_object(self.client, 'send_request', 

4730 mock.Mock(return_value=fake.FAKE_VOL_MOVE_STATUS)) 

4731 

4732 self.client.configure_dns(fake.KERBEROS_SECURITY_SERVICE) 

4733 body = { 

4734 'domains': [fake.KERBEROS_SECURITY_SERVICE['domain']], 

4735 'servers': [fake.KERBEROS_SECURITY_SERVICE['dns_ip']] 

4736 } 

4737 

4738 self.client.send_request.assert_called_once_with( 

4739 f'/name-services/dns/{fake_uuid}', 'patch', body=body) 

4740 

4741 def test_remove_preferred_dcs(self): 

4742 svm_uuid = copy.deepcopy(fake.FAKE_UUID) 

4743 fqdn = copy.deepcopy(fake.PREFERRED_DC_REST.get('fqdn')) 

4744 server_ip = copy.deepcopy(fake.PREFERRED_DC_REST.get('server_ip')) 

4745 fake_response = copy.deepcopy(fake.PREFERRED_DC_REST) 

4746 fake_ss = copy.deepcopy(fake.LDAP_AD_SECURITY_SERVICE) 

4747 self.mock_object(self.client, 'send_request', 

4748 mock.Mock(return_value=fake_response)) 

4749 self.client.remove_preferred_dcs(fake_ss, svm_uuid) 

4750 query = { 

4751 'fqdn': fake.LDAP_AD_SECURITY_SERVICE.get('domain'), 

4752 } 

4753 self.client.send_request.assert_has_calls([ 

4754 mock.call(f'/protocols/cifs/domains/{svm_uuid}/' 

4755 f'preferred-domain-controllers/', 'get'), 

4756 mock.call(f'/protocols/cifs/domains/{svm_uuid}/' 

4757 f'preferred-domain-controllers/{fqdn}/{server_ip}', 

4758 'delete', query=query) 

4759 ]) 

4760 

4761 def test_remove_preferred_dcs_api_error(self): 

4762 fake_response = copy.deepcopy(fake.PREFERRED_DC_REST) 

4763 fake_ss = copy.deepcopy(fake.LDAP_AD_SECURITY_SERVICE) 

4764 self.mock_object(self.client, 'send_request', 

4765 mock.Mock(return_value=fake_response)) 

4766 self.mock_object(self.client, 'send_request', 

4767 mock.Mock(side_effect=netapp_api.api.NaApiError)) 

4768 self.assertRaises(netapp_api.api.NaApiError, 

4769 self.client.remove_preferred_dcs, 

4770 fake_ss, fake.FAKE_UUID) 

4771 

4772 def test_configure_cifs_aes_encryption_enable(self): 

4773 self.mock_object(self.client, 'send_request') 

4774 self.mock_object(self.client, '_get_unique_svm_by_name', 

4775 mock.Mock(return_value=fake.FAKE_UUID)) 

4776 

4777 self.client.configure_cifs_aes_encryption(fake.VSERVER_NAME, True) 

4778 self.client._get_unique_svm_by_name.assert_called_once_with( 

4779 fake.VSERVER_NAME) 

4780 

4781 body = { 

4782 'security.advertised_kdc_encryptions': ['aes-128', 'aes-256'], 

4783 } 

4784 self.client.send_request.assert_called_once_with( 

4785 f'/protocols/cifs/services/{fake.FAKE_UUID}', 

4786 'patch', body=body) 

4787 

4788 def test_configure_cifs_aes_encryption_disable(self): 

4789 self.mock_object(self.client, 'send_request') 

4790 self.mock_object(self.client, '_get_unique_svm_by_name', 

4791 mock.Mock(return_value=fake.FAKE_UUID)) 

4792 

4793 self.client.configure_cifs_aes_encryption(fake.VSERVER_NAME, False) 

4794 self.client._get_unique_svm_by_name.assert_called_once_with( 

4795 fake.VSERVER_NAME) 

4796 

4797 body = { 

4798 'security.advertised_kdc_encryptions': ['des', 'rc4'], 

4799 } 

4800 self.client.send_request.assert_called_once_with( 

4801 f'/protocols/cifs/services/{fake.FAKE_UUID}', 

4802 'patch', body=body) 

4803 

4804 def test_set_preferred_dc(self): 

4805 fake_ss = copy.deepcopy(fake.LDAP_AD_SECURITY_SERVICE_WITH_SERVER) 

4806 self.mock_object(self.client, 'send_request') 

4807 self.mock_object(self.client, '_get_unique_svm_by_name', 

4808 mock.Mock(return_value=fake.FAKE_UUID)) 

4809 

4810 self.client.set_preferred_dc(fake_ss, fake.VSERVER_NAME) 

4811 

4812 self.client._get_unique_svm_by_name.assert_called_once_with( 

4813 fake.VSERVER_NAME) 

4814 

4815 query = { 

4816 'fqdn': fake_ss['domain'], 

4817 'skip_config_validation': 'false', 

4818 'server_ip': ['10.10.10.1'] 

4819 } 

4820 self.client.send_request.assert_called_once_with( 

4821 f'/protocols/cifs/domains/{fake.FAKE_UUID}' 

4822 '/preferred-domain-controllers', 'post', query=query) 

4823 

4824 @ddt.data(None, 'cluster_name') 

4825 def test_create_vserver_peer(self, cluster_name): 

4826 

4827 self.mock_object(self.client, 'send_request') 

4828 

4829 self.client.create_vserver_peer(fake.VSERVER_NAME, 

4830 fake.VSERVER_PEER_NAME, 

4831 peer_cluster_name=cluster_name) 

4832 

4833 body = { 

4834 'svm.name': fake.VSERVER_NAME, 

4835 'peer.svm.name': fake.VSERVER_PEER_NAME, 

4836 'applications': ['snapmirror'], 

4837 } 

4838 if cluster_name: 

4839 body['peer.cluster.name'] = cluster_name 

4840 

4841 self.client.send_request.assert_has_calls([ 

4842 mock.call('/svm/peers', 'post', body=body, 

4843 enable_tunneling=False)]) 

4844 

4845 def test__get_svm_peer_uuid(self): 

4846 response = { 

4847 "records": [{ 

4848 "uuid": "fake-vserver-uuid", 

4849 "name": fake.VSERVER_NAME, 

4850 "svm": { 

4851 "name": fake.VSERVER_NAME, 

4852 }, 

4853 "peer": { 

4854 "svm": { 

4855 "name": fake.VSERVER_PEER_NAME, 

4856 } 

4857 } 

4858 }], 

4859 } 

4860 expected_result = "fake-vserver-uuid" 

4861 return_value = response['records'][0]['uuid'] 

4862 self.mock_object(self.client, '_get_svm_peer_uuid', 

4863 mock.Mock(return_value=return_value)) 

4864 

4865 result = self.client._get_svm_peer_uuid( 

4866 fake.VSERVER_NAME, fake.VSERVER_PEER_NAME) 

4867 

4868 self.client._get_svm_peer_uuid.assert_called_once_with( 

4869 fake.VSERVER_NAME, fake.VSERVER_PEER_NAME) 

4870 

4871 self.assertEqual(expected_result, result) 

4872 

4873 def test_accept_vserver_peer(self): 

4874 

4875 fake_resp = { 

4876 'records': [{'uuid': 'fake-vserver-uuid'}], 

4877 'num_records': 1, 

4878 } 

4879 

4880 self.mock_object( 

4881 self.client, 'send_request', 

4882 mock.Mock(side_effect=[fake_resp, None])) 

4883 self.client.accept_vserver_peer( 

4884 fake.VSERVER_NAME, fake.VSERVER_PEER_NAME) 

4885 

4886 body = {'state': 'peered'} 

4887 

4888 uuid = "fake-vserver-uuid" 

4889 self.client.send_request.assert_has_calls([ 

4890 mock.call(f'/svm/peers/{uuid}', 'patch', body=body, 

4891 enable_tunneling=False)]) 

4892 

4893 def test_get_vserver_peers(self): 

4894 self.mock_object(self.client, 

4895 'send_request', 

4896 mock.Mock(return_value=fake.FAKE_PEER_GET_RESPONSE)) 

4897 

4898 result = self.client.get_vserver_peers( 

4899 vserver_name=fake.VSERVER_NAME, 

4900 peer_vserver_name=fake.VSERVER_NAME_2) 

4901 

4902 query = { 

4903 'name': fake.VSERVER_NAME_2, 

4904 'svm.name': fake.VSERVER_NAME 

4905 } 

4906 query['fields'] = 'uuid,svm.name,peer.svm.name,state,peer.cluster.name' 

4907 self.client.send_request.assert_has_calls([ 

4908 mock.call('/svm/peers', 'get', query=query)]) 

4909 

4910 expected = [{ 

4911 'uuid': fake.FAKE_UUID, 

4912 'vserver': fake.VSERVER_NAME, 

4913 'peer-vserver': fake.VSERVER_NAME_2, 

4914 'peer-state': fake.VSERVER_PEER_STATE, 

4915 'peer-cluster': fake.CLUSTER_NAME 

4916 }] 

4917 self.assertEqual(expected, result) 

4918 

4919 def test_get_vserver_peers_not_found(self): 

4920 

4921 self.mock_object(self.client, 

4922 'send_request', 

4923 mock.Mock(return_value=fake.NO_RECORDS_RESPONSE_REST)) 

4924 

4925 result = self.client.get_vserver_peers( 

4926 vserver_name=fake.VSERVER_NAME, 

4927 peer_vserver_name=fake.VSERVER_NAME_2) 

4928 

4929 self.assertEqual([], result) 

4930 self.assertTrue(self.client.send_request.called) 

4931 

4932 def test_delete_vserver_peer(self): 

4933 

4934 self.mock_object(self.client, 'get_vserver_peers', 

4935 mock.Mock(return_value=fake.FAKE_VSERVER_PEERS)) 

4936 

4937 self.mock_object(self.client, 'send_request') 

4938 

4939 self.client.delete_vserver_peer(fake.VSERVER_NAME, 

4940 fake.VSERVER_PEER_NAME) 

4941 

4942 self.client.get_vserver_peers.assert_called_once_with( 

4943 fake.VSERVER_NAME, fake.VSERVER_PEER_NAME) 

4944 self.client.send_request.assert_called_once_with( 

4945 '/svm/peers/fake_uuid', 'delete', enable_tunneling=False) 

4946 

4947 def test_update_showmount(self): 

4948 query = { 

4949 'name': fake.VSERVER_NAME, 

4950 'fields': 'uuid' 

4951 } 

4952 response_svm = fake.SVMS_LIST_SIMPLE_RESPONSE_REST 

4953 self.client.vserver = fake.VSERVER_NAME 

4954 self.mock_object(self.client, 

4955 'send_request', 

4956 mock.Mock(side_effect=[response_svm, None])) 

4957 

4958 fake_showmount = 'true' 

4959 self.client.update_showmount(fake_showmount) 

4960 

4961 svm_id = response_svm.get('records')[0]['uuid'] 

4962 

4963 body = { 

4964 'showmount_enabled': fake_showmount, 

4965 } 

4966 self.client.send_request.assert_has_calls([ 

4967 mock.call('/svm/svms', 'get', query=query), 

4968 mock.call(f'/protocols/nfs/services/{svm_id}', 

4969 'patch', body=body) 

4970 ]) 

4971 

4972 @ddt.data({'tcp-max-xfer-size': 10000}, {}, None) 

4973 def test_enable_nfs(self, nfs_config): 

4974 self.mock_object(self.client, '_get_unique_svm_by_name', 

4975 mock.Mock(return_value=fake.FAKE_UUID)) 

4976 self.mock_object(self.client, 'send_request') 

4977 self.mock_object(self.client, 

4978 '_enable_nfs_protocols') 

4979 self.mock_object(self.client, 

4980 '_configure_nfs') 

4981 self.mock_object(self.client, 

4982 '_create_default_nfs_export_rules') 

4983 

4984 self.mock_object(self.client, '_enable_nfs_protocols') 

4985 

4986 self.client.enable_nfs(fake.NFS_VERSIONS, nfs_config) 

4987 body = { 

4988 'svm.uuid': fake.FAKE_UUID, 

4989 'enabled': 'true' 

4990 } 

4991 

4992 self.client.send_request.assert_called_once_with( 

4993 '/protocols/nfs/services/', 'post', body=body) 

4994 self.client._get_unique_svm_by_name.assert_called_once_with() 

4995 self.client._enable_nfs_protocols.assert_called_once_with( 

4996 fake.NFS_VERSIONS, fake.FAKE_UUID) 

4997 if nfs_config: 

4998 self.client._configure_nfs.assert_called_once_with(nfs_config, 

4999 fake.FAKE_UUID) 

5000 else: 

5001 self.client._configure_nfs.assert_not_called() 

5002 self.client._create_default_nfs_export_rules.assert_called_once_with() 

5003 

5004 @ddt.data((True, True, True), (True, False, False), (False, True, True)) 

5005 @ddt.unpack 

5006 def test_enable_nfs_protocols(self, v3, v40, v41): 

5007 

5008 self.mock_object(self.client, 'send_request') 

5009 

5010 versions = [] 

5011 if v3: 

5012 versions.append('nfs3') 

5013 if v40: 

5014 versions.append('nfs4.0') 

5015 if v41: 

5016 versions.append('nfs4.1') 

5017 

5018 self.client._enable_nfs_protocols(versions, fake.FAKE_UUID) 

5019 

5020 body = { 

5021 'protocol.v3_enabled': 'true' if v3 else 'false', 

5022 'protocol.v40_enabled': 'true' if v40 else 'false', 

5023 'protocol.v41_enabled': 'true' if v41 else 'false', 

5024 'showmount_enabled': 'true', 

5025 'windows.v3_ms_dos_client_enabled': 'true', 

5026 'protocol.v3_features.connection_drop': 'false', 

5027 'protocol.v3_features.ejukebox_enabled': 'false', 

5028 } 

5029 self.client.send_request.assert_called_once_with( 

5030 f'/protocols/nfs/services/{fake.FAKE_UUID}', 

5031 'patch', body=body) 

5032 

5033 def test_configure_nfs(self): 

5034 self.mock_object(self.client, 'send_request') 

5035 

5036 fake_nfs = { 

5037 'tcp-max-xfer-size': 10000, 

5038 } 

5039 self.client._configure_nfs(fake_nfs, fake.FAKE_UUID) 

5040 

5041 body = { 

5042 'transport.tcp_max_transfer_size': 10000 

5043 } 

5044 self.client.send_request.assert_called_once_with( 

5045 f'/protocols/nfs/services/{fake.FAKE_UUID}', 

5046 'patch', body=body) 

5047 

5048 def test__create_default_nfs_export_rules(self): 

5049 

5050 class CopyingMock(mock.Mock): 

5051 def __call__(self, *args, **kwargs): 

5052 args = copy.deepcopy(args) 

5053 kwargs = copy.deepcopy(kwargs) 

5054 return super(CopyingMock, self).__call__(*args, **kwargs) 

5055 

5056 self.mock_object(self.client, 'send_request', CopyingMock()) 

5057 

5058 fake_uuid = fake.FAKE_UUID 

5059 

5060 mock_id = self.mock_object(self.client, 'get_unique_export_policy_id', 

5061 mock.Mock(return_value=fake_uuid)) 

5062 

5063 self.client._create_default_nfs_export_rules() 

5064 

5065 body = { 

5066 'clients': [{ 

5067 'match': '0.0.0.0/0' 

5068 }], 

5069 'ro_rule': [ 

5070 'any', 

5071 ], 

5072 'rw_rule': [ 

5073 'never' 

5074 ], 

5075 } 

5076 body2 = body.copy() 

5077 body2['clients'] = [{ 

5078 'match': '::/0' 

5079 }] 

5080 

5081 mock_id.assert_called_once_with('default') 

5082 self.client.send_request.assert_has_calls([ 

5083 mock.call(f'/protocols/nfs/export-policies/{fake_uuid}/rules', 

5084 "post", body=body), 

5085 mock.call(f'/protocols/nfs/export-policies/{fake_uuid}/rules', 

5086 "post", body=body2)]) 

5087 

5088 def test_get_node_data_ports(self): 

5089 self.mock_object( 

5090 self.client, 'send_request', mock.Mock( 

5091 side_effect=[fake.REST_ETHERNET_PORTS, 

5092 fake.REST_DATA_INTERFACES])) 

5093 self.mock_object( 

5094 self.client, '_sort_data_ports_by_speed', mock.Mock( 

5095 return_value=fake.REST_SPEED_SORTED_PORTS)) 

5096 

5097 test_result = self.client.get_node_data_ports(fake.NODE_NAME) 

5098 

5099 fake_query = { 

5100 'node.name': fake.NODE_NAME, 

5101 'state': 'up', 

5102 'type': 'physical', 

5103 'broadcast_domain.name': 'Default', 

5104 'fields': 'node.name,speed,name' 

5105 } 

5106 

5107 query_interfaces = { 

5108 'service_policy.name': '!default-management', 

5109 'services': 'data_*', 

5110 'fields': 'location.port.name' 

5111 } 

5112 

5113 self.client.send_request.assert_has_calls([ 

5114 mock.call('/network/ethernet/ports', 'get', query=fake_query), 

5115 mock.call('/network/ip/interfaces', 'get', 

5116 query=query_interfaces, enable_tunneling=False), 

5117 ]) 

5118 self.client._sort_data_ports_by_speed.assert_called_once_with( 

5119 fake.REST_SPEED_NOT_SORTED_PORTS) 

5120 self.assertEqual(fake.REST_SPEED_SORTED_PORTS, test_result) 

5121 

5122 def test_list_node_data_ports(self): 

5123 

5124 expected_resulted = ['e0d', 'e0c', 'e0b'] 

5125 

5126 mock_ports = ( 

5127 self.mock_object(self.client, 'get_node_data_ports', mock.Mock( 

5128 return_value=fake.REST_SPEED_SORTED_PORTS))) 

5129 

5130 test_result = self.client.list_node_data_ports(fake.NODE_NAME) 

5131 

5132 mock_ports.assert_called_once_with(fake.NODE_NAME) 

5133 self.assertEqual(test_result, expected_resulted) 

5134 

5135 def test_create_ipspace(self): 

5136 fake_body = {'name': fake.IPSPACE_NAME} 

5137 

5138 self.mock_object(self.client, 'send_request') 

5139 

5140 self.client.create_ipspace(fake.IPSPACE_NAME) 

5141 

5142 self.client.send_request.assert_called_once_with( 

5143 '/network/ipspaces', 'post', body=fake_body) 

5144 

5145 def test_get_ipspace_name_for_vlan_port(self): 

5146 

5147 fake_query = { 

5148 'node.name': fake.NODE_NAME, 

5149 'name': fake.VLAN_PORT, 

5150 'fields': 'broadcast_domain.ipspace.name', 

5151 } 

5152 

5153 expected_result = "Default" 

5154 

5155 self.mock_object( 

5156 self.client, 'send_request', mock.Mock( 

5157 return_value=fake.REST_ETHERNET_PORTS)) 

5158 

5159 test_result = self.client.get_ipspace_name_for_vlan_port( 

5160 fake.NODE_NAME, fake.PORT, fake.VLAN) 

5161 

5162 self.client.send_request.assert_called_once_with( 

5163 '/network/ethernet/ports/', 'get', query=fake_query) 

5164 

5165 self.assertEqual(test_result, expected_result) 

5166 

5167 def test__create_broadcast_domain(self): 

5168 

5169 fake_body = { 

5170 'ipspace.name': fake.IPSPACE_NAME, 

5171 'name': fake.BROADCAST_DOMAIN, 

5172 'mtu': fake.MTU, 

5173 } 

5174 

5175 self.mock_object(self.client, 'send_request') 

5176 

5177 self.client._create_broadcast_domain(fake.BROADCAST_DOMAIN, 

5178 fake.IPSPACE_NAME, 

5179 fake.MTU) 

5180 

5181 self.client.send_request.assert_called_once_with( 

5182 '/network/ethernet/broadcast-domains', 'post', body=fake_body) 

5183 

5184 def test_ensure_broadcast_domain_for_port_domain_match(self): 

5185 

5186 port_info = { 

5187 'ipspace': fake.IPSPACE_NAME, 

5188 'broadcast-domain': fake.BROADCAST_DOMAIN, 

5189 } 

5190 self.mock_object(self.client, 

5191 '_get_broadcast_domain_for_port', 

5192 mock.Mock(return_value=port_info)) 

5193 self.mock_object(self.client, 

5194 '_broadcast_domain_exists', 

5195 mock.Mock(return_value=True)) 

5196 self.mock_object(self.client, '_create_broadcast_domain') 

5197 self.mock_object(self.client, '_modify_broadcast_domain') 

5198 self.mock_object(self.client, '_add_port_to_broadcast_domain') 

5199 

5200 self.client._ensure_broadcast_domain_for_port( 

5201 fake.NODE_NAME, fake.PORT, fake.MTU, ipspace=fake.IPSPACE_NAME) 

5202 

5203 self.client._get_broadcast_domain_for_port.assert_called_once_with( 

5204 fake.NODE_NAME, fake.PORT) 

5205 self.client._modify_broadcast_domain.assert_called_once_with( 

5206 fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME, fake.MTU) 

5207 self.assertFalse(self.client._broadcast_domain_exists.called) 

5208 self.assertFalse(self.client._create_broadcast_domain.called) 

5209 self.assertFalse(self.client._add_port_to_broadcast_domain.called) 

5210 

5211 @ddt.data(fake.IPSPACE_NAME, client_cmode.DEFAULT_IPSPACE) 

5212 def test_ensure_broadcast_domain_for_port_other_domain(self, ipspace): 

5213 

5214 port_info = { 

5215 'ipspace': ipspace, 

5216 'broadcast-domain': 'other_domain', 

5217 } 

5218 self.mock_object(self.client, 

5219 '_get_broadcast_domain_for_port', 

5220 mock.Mock(return_value=port_info)) 

5221 self.mock_object(self.client, 

5222 '_broadcast_domain_exists', 

5223 mock.Mock(return_value=True)) 

5224 self.mock_object(self.client, '_create_broadcast_domain') 

5225 self.mock_object(self.client, '_modify_broadcast_domain') 

5226 self.mock_object(self.client, '_add_port_to_broadcast_domain') 

5227 

5228 self.client._ensure_broadcast_domain_for_port( 

5229 fake.NODE_NAME, fake.PORT, ipspace=fake.IPSPACE_NAME, mtu=fake.MTU) 

5230 

5231 self.client._get_broadcast_domain_for_port.assert_called_once_with( 

5232 fake.NODE_NAME, fake.PORT) 

5233 self.client._broadcast_domain_exists.assert_called_once_with( 

5234 fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME) 

5235 self.assertFalse(self.client._create_broadcast_domain.called) 

5236 self.client._modify_broadcast_domain.assert_called_once_with( 

5237 fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME, fake.MTU) 

5238 self.client._add_port_to_broadcast_domain.assert_called_once_with( 

5239 fake.NODE_NAME, fake.PORT, fake.BROADCAST_DOMAIN, 

5240 fake.IPSPACE_NAME) 

5241 

5242 def test_ensure_broadcast_domain_for_port_no_domain(self): 

5243 

5244 port_info = { 

5245 'ipspace': fake.IPSPACE_NAME, 

5246 'broadcast-domain': None, 

5247 } 

5248 self.mock_object(self.client, 

5249 '_get_broadcast_domain_for_port', 

5250 mock.Mock(return_value=port_info)) 

5251 self.mock_object(self.client, 

5252 '_broadcast_domain_exists', 

5253 mock.Mock(return_value=False)) 

5254 self.mock_object(self.client, '_create_broadcast_domain') 

5255 self.mock_object(self.client, '_modify_broadcast_domain') 

5256 self.mock_object(self.client, '_add_port_to_broadcast_domain') 

5257 

5258 self.client._ensure_broadcast_domain_for_port( 

5259 fake.NODE_NAME, fake.PORT, ipspace=fake.IPSPACE_NAME, mtu=fake.MTU) 

5260 

5261 self.client._get_broadcast_domain_for_port.assert_called_once_with( 

5262 fake.NODE_NAME, fake.PORT) 

5263 self.client._broadcast_domain_exists.assert_called_once_with( 

5264 fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME) 

5265 self.client._create_broadcast_domain.assert_called_once_with( 

5266 fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME, fake.MTU) 

5267 self.assertFalse(self.client._modify_broadcast_domain.called) 

5268 self.client._add_port_to_broadcast_domain.assert_called_once_with( 

5269 fake.NODE_NAME, fake.PORT, fake.BROADCAST_DOMAIN, 

5270 fake.IPSPACE_NAME) 

5271 

5272 def test__add_port_to_broadcast_domain(self): 

5273 query = { 

5274 'name': fake.PORT, 

5275 'node.name': fake.NODE_NAME, 

5276 } 

5277 body = { 

5278 'broadcast_domain.ipspace.name': fake.IPSPACE_NAME, 

5279 'broadcast_domain.name': fake.BROADCAST_DOMAIN, 

5280 } 

5281 

5282 self.mock_object(self.client, 'send_request') 

5283 self.client._add_port_to_broadcast_domain(fake.NODE_NAME, 

5284 fake.PORT, 

5285 fake.BROADCAST_DOMAIN, 

5286 fake.IPSPACE_NAME) 

5287 

5288 self.client.send_request.assert_called_once_with( 

5289 '/network/ethernet/ports/', 'patch', query=query, body=body) 

5290 

5291 def test__add_port_to_broadcast_domain_exists(self): 

5292 query = { 

5293 'name': fake.PORT, 

5294 'node.name': fake.NODE_NAME, 

5295 } 

5296 body = { 

5297 'broadcast_domain.ipspace.name': fake.IPSPACE_NAME, 

5298 'broadcast_domain.name': fake.BROADCAST_DOMAIN, 

5299 } 

5300 self.mock_object( 

5301 self.client, 'send_request', self._mock_api_error( 

5302 code=netapp_api.EREST_FAIL_ADD_PORT_BROADCAST)) 

5303 

5304 self.client._add_port_to_broadcast_domain(fake.NODE_NAME, 

5305 fake.PORT, 

5306 fake.BROADCAST_DOMAIN, 

5307 fake.IPSPACE_NAME) 

5308 

5309 self.client.send_request.assert_called_once_with( 

5310 '/network/ethernet/ports/', 'patch', query=query, body=body) 

5311 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count) 

5312 

5313 def test__add_port_to_broadcast_domain_exception(self): 

5314 self.mock_object(self.client, 'send_request', 

5315 self._mock_api_error()) 

5316 self.assertRaises( 

5317 exception.NetAppException, 

5318 self.client._add_port_to_broadcast_domain, 

5319 fake.NODE_NAME, fake.PORT, fake.BROADCAST_DOMAIN, 

5320 fake.IPSPACE_NAME) 

5321 

5322 def test_rename_vserver(self): 

5323 svm_uuid = fake.SVM_ITEM_SIMPLE_RESPONSE_REST["uuid"] 

5324 body = { 

5325 'name': fake.VSERVER_NAME_2 

5326 } 

5327 

5328 self.mock_object(self.client, '_get_unique_svm_by_name', 

5329 mock.Mock(return_value=svm_uuid)) 

5330 self.mock_object(self.client, 'send_request') 

5331 

5332 self.client.rename_vserver(fake.VSERVER_NAME, fake.VSERVER_NAME_2) 

5333 

5334 self.client._get_unique_svm_by_name.assert_called_once_with( 

5335 fake.VSERVER_NAME) 

5336 self.client.send_request.assert_called_once_with( 

5337 f'/svm/svms/{svm_uuid}', 'patch', body=body) 

5338 

5339 def test_create_network_interface(self): 

5340 api_response = copy.deepcopy(fake.SERVICE_POLICIES_REST) 

5341 self.mock_object( 

5342 self.client, 'send_request', 

5343 mock.Mock(side_effect=[api_response, None, None])) 

5344 

5345 self.client.create_network_interface(fake.IP_ADDRESS, 

5346 fake.NETMASK, 

5347 fake.NODE_NAME, 

5348 fake.VLAN_PORT, 

5349 fake.VSERVER_NAME, 

5350 fake.LIF_NAME) 

5351 query = { 

5352 'name': 'default-data-files', 

5353 'svm.name': fake.VSERVER_NAME, 

5354 'fields': 'uuid,name,services,svm.name' 

5355 } 

5356 

5357 policy = copy.deepcopy(fake.SERVICE_POLICIES_REST['records'][0]) 

5358 uuid = policy['uuid'] 

5359 

5360 policy['services'].append('data_nfs') 

5361 policy['services'].append('data_cifs') 

5362 body1 = {'services': policy['services']} 

5363 

5364 body2 = { 

5365 'ip.address': fake.IP_ADDRESS, 

5366 'ip.netmask': fake.NETMASK, 

5367 'enabled': 'true', 

5368 'service_policy.name': 'default-data-files', 

5369 'location.home_node.name': fake.NODE_NAME, 

5370 'location.home_port.name': fake.VLAN_PORT, 

5371 'name': fake.LIF_NAME, 

5372 'svm.name': fake.VSERVER_NAME, 

5373 } 

5374 

5375 self.client.send_request.assert_has_calls([ 

5376 mock.call('/network/ip/service-policies/', 'get', query=query), 

5377 mock.call(f'/network/ip/service-policies/{uuid}', 

5378 'patch', body=body1), 

5379 mock.call('/network/ip/interfaces', 'post', body=body2) 

5380 ]) 

5381 

5382 def test_create_vserver(self): 

5383 mock = self.mock_object(self.client, '_create_vserver') 

5384 self.mock_object(self.client, '_modify_security_cert', 

5385 mock.Mock(return_value=[])) 

5386 self.client.create_vserver(fake.VSERVER_NAME, None, None, 

5387 [fake.SHARE_AGGREGATE_NAME], 

5388 fake.IPSPACE_NAME, 

5389 fake.SECURITY_CERT_DEFAULT_EXPIRE_DAYS, 

5390 fake.DELETE_RETENTION_HOURS, 

5391 False) 

5392 mock.assert_called_once_with(fake.VSERVER_NAME, 

5393 [fake.SHARE_AGGREGATE_NAME], 

5394 fake.IPSPACE_NAME, 

5395 fake.DELETE_RETENTION_HOURS, 

5396 name_server_switch=['files'], 

5397 logical_space_reporting=False) 

5398 self.client._modify_security_cert.assert_called_once_with( 

5399 fake.VSERVER_NAME, 

5400 fake.SECURITY_CERT_DEFAULT_EXPIRE_DAYS) 

5401 

5402 def test__modify_security_cert(self): 

5403 api_response = copy.deepcopy(fake.SECURITY_CERT_GET_RESPONSE_REST) 

5404 api_response2 = copy.deepcopy(fake.SECURITY_CERT_POST_RESPONSE_REST) 

5405 self.mock_object( 

5406 self.client, 'send_request', 

5407 mock.Mock(side_effect=[api_response, api_response2, None, None])) 

5408 

5409 query = { 

5410 'common-name': fake.VSERVER_NAME, 

5411 'ca': fake.VSERVER_NAME, 

5412 'type': 'server', 

5413 'svm.name': fake.VSERVER_NAME, 

5414 } 

5415 old_cert_info = copy.deepcopy( 

5416 fake.SECURITY_CERT_GET_RESPONSE_REST['records'][0]) 

5417 old_cert_uuid = old_cert_info['uuid'] 

5418 

5419 body1 = { 

5420 'common-name': fake.VSERVER_NAME, 

5421 'type': 'server', 

5422 'svm.name': fake.VSERVER_NAME, 

5423 'expiry_time': 'P' + str( 

5424 fake.SECURITY_CERT_LARGE_EXPIRE_DAYS) + 'DT', 

5425 } 

5426 query1 = { 

5427 'return_records': 'true' 

5428 } 

5429 new_cert_info = copy.deepcopy( 

5430 fake.SECURITY_CERT_POST_RESPONSE_REST['records'][0]) 

5431 new_cert_uuid = new_cert_info['uuid'] 

5432 new_svm_uuid = new_cert_info['svm']['uuid'] 

5433 body2 = { 

5434 'certificate': { 

5435 'uuid': new_cert_uuid, 

5436 }, 

5437 'client_enabled': 'false', 

5438 } 

5439 

5440 self.client._modify_security_cert( 

5441 fake.VSERVER_NAME, 

5442 fake.SECURITY_CERT_LARGE_EXPIRE_DAYS) 

5443 

5444 self.client.send_request.assert_has_calls([ 

5445 mock.call('/security/certificates', 'get', query=query), 

5446 mock.call('/security/certificates', 'post', body=body1, 

5447 query=query1), 

5448 mock.call(f'/svm/svms/{new_svm_uuid}', 'patch', body=body2), 

5449 mock.call(f'/security/certificates/{old_cert_uuid}', 'delete'), 

5450 ]) 

5451 

5452 def test__broadcast_domain_exists(self): 

5453 response = fake.FAKE_GET_BROADCAST_DOMAIN 

5454 self.mock_object(self.client, 'send_request', 

5455 mock.Mock(return_value=response)) 

5456 self.mock_object(self.client, '_has_records', 

5457 mock.Mock(return_value=True)) 

5458 query = { 

5459 'ipspace.name': fake.IPSPACE_NAME, 

5460 'name': fake.BROADCAST_DOMAIN, 

5461 } 

5462 result = self.client._broadcast_domain_exists(fake.BROADCAST_DOMAIN, 

5463 fake.IPSPACE_NAME) 

5464 self.client.send_request.assert_called_once_with( 

5465 '/network/ethernet/broadcast-domains', 

5466 'get', query=query) 

5467 self.assertTrue(result) 

5468 

5469 def test___delete_port_by_ipspace_and_broadcast_domain(self): 

5470 self.mock_object(self.client, 'send_request') 

5471 query = { 

5472 'broadcast_domain.ipspace.name': fake.IPSPACE_NAME, 

5473 'broadcast_domain.name': fake.BROADCAST_DOMAIN, 

5474 'name': fake.PORT 

5475 } 

5476 self.client._delete_port_by_ipspace_and_broadcast_domain( 

5477 fake.PORT, 

5478 fake.BROADCAST_DOMAIN, 

5479 fake.IPSPACE_NAME) 

5480 self.client.send_request.assert_called_once_with( 

5481 '/network/ethernet/ports/', 'delete', 

5482 query=query) 

5483 

5484 def test_get_broadcast_domain_for_port(self): 

5485 

5486 self.mock_object(self.client, 'send_request', mock.Mock( 

5487 return_value=fake.REST_ETHERNET_PORTS)) 

5488 

5489 query = { 

5490 'node.name': fake.NODE_NAME, 

5491 'name': fake.PORT, 

5492 'fields': 'broadcast_domain.name,broadcast_domain.ipspace.name' 

5493 } 

5494 

5495 result = self.client._get_broadcast_domain_for_port(fake.NODE_NAME, 

5496 fake.PORT) 

5497 

5498 expected = { 

5499 'broadcast-domain': "fake_domain_1", 

5500 'ipspace': "Default", 

5501 } 

5502 self.client.send_request.assert_has_calls([ 

5503 mock.call('/network/ethernet/ports', 'get', query=query)]) 

5504 self.assertEqual(expected, result) 

5505 

5506 def test_modify_broadcast_domain(self): 

5507 

5508 self.mock_object(self.client, 'send_request') 

5509 

5510 result = self.client._modify_broadcast_domain(fake.BROADCAST_DOMAIN, 

5511 fake.IPSPACE_NAME, 

5512 fake.MTU) 

5513 

5514 query = { 

5515 'name': fake.BROADCAST_DOMAIN 

5516 } 

5517 

5518 body = { 

5519 'ipspace.name': fake.IPSPACE_NAME, 

5520 'mtu': fake.MTU, 

5521 } 

5522 self.assertIsNone(result) 

5523 self.client.send_request.assert_called_once_with( 

5524 '/network/ethernet/broadcast-domains', 'patch', body=body, 

5525 query=query) 

5526 

5527 @ddt.data(fake.NO_RECORDS_RESPONSE, 

5528 fake.SVMS_LIST_SIMPLE_RESPONSE_REST) 

5529 def test_get_vserver_info(self, api_response): 

5530 self.mock_object(self.client, 'send_request', 

5531 mock.Mock(return_value=api_response)) 

5532 

5533 result = self.client.get_vserver_info(fake.VSERVER_NAME) 

5534 

5535 query = { 

5536 'name': fake.VSERVER_NAME, 

5537 'fields': 'state,subtype' 

5538 } 

5539 self.client.send_request.assert_called_once_with( 

5540 '/svm/svms', 'get', query=query) 

5541 if api_response == fake.NO_RECORDS_RESPONSE: 

5542 self.assertIsNone(result) 

5543 else: 

5544 self.assertDictEqual(fake.VSERVER_INFO, result) 

5545 

5546 def test_get_nfs_config(self): 

5547 api_response = fake.NFS_CONFIG_RESULT_REST 

5548 self.mock_object(self.client, 

5549 'send_request', 

5550 mock.Mock(return_value=api_response)) 

5551 

5552 result = self.client.get_nfs_config(['tcp-max-xfer-size', 

5553 'udp-max-xfer-size'], 

5554 fake.VSERVER_NAME) 

5555 expected = { 

5556 'tcp-max-xfer-size': '65536', 

5557 'udp-max-xfer-size': '32768', 

5558 } 

5559 self.assertEqual(expected, result) 

5560 

5561 query = {'fields': 'transport.*', 'svm.name': 'fake_vserver'} 

5562 self.client.send_request.assert_called_once_with( 

5563 '/protocols/nfs/services/', 'get', query=query) 

5564 

5565 def test_get_vserver_ipspace(self): 

5566 

5567 self.client.features.add_feature('IPSPACES') 

5568 api_response = fake.REST_VSERVER_GET_IPSPACE_NAME_RESPONSE 

5569 self.mock_object(self.client, 

5570 'send_request', 

5571 mock.Mock(return_value=api_response)) 

5572 

5573 result = self.client.get_vserver_ipspace(fake.VSERVER_NAME) 

5574 

5575 query = { 

5576 'name': fake.VSERVER_NAME, 

5577 'fields': 'ipspace.name' 

5578 } 

5579 expected = fake.IPSPACE_NAME 

5580 self.client.send_request.assert_has_calls([ 

5581 mock.call('/svm/svms', 'get', query=query)]) 

5582 self.assertEqual(expected, result) 

5583 

5584 def test_get_vserver_ipspace_not_found(self): 

5585 api_response = fake.NO_RECORDS_RESPONSE_REST 

5586 self.mock_object(self.client, 'send_request', 

5587 mock.Mock(return_value=api_response)) 

5588 result = self.client.get_vserver_ipspace(fake.VSERVER_NAME) 

5589 self.assertIsNone(result) 

5590 

5591 def test_get_vserver_ipspace_exception(self): 

5592 self.mock_object(self.client, 'send_request', 

5593 self._mock_api_error()) 

5594 self.assertRaises(exception.NetAppException, 

5595 self.client.get_vserver_ipspace, 

5596 fake.VSERVER_NAME) 

5597 

5598 def test_get_snapmirror_policies(self): 

5599 api_response = fake.GET_SNAPMIRROR_POLICIES_REST 

5600 self.mock_object(self.client, 'send_request', 

5601 mock.Mock(return_value=api_response)) 

5602 result_elem = [fake.SNAPMIRROR_POLICY_NAME] 

5603 

5604 result = self.client.get_snapmirror_policies( 

5605 fake.VSERVER_NAME) 

5606 

5607 query = { 

5608 'svm.name': fake.VSERVER_NAME, 

5609 'fields': 'name' 

5610 } 

5611 

5612 self.client.send_request.assert_called_once_with( 

5613 '/snapmirror/policies', 'get', query=query) 

5614 self.assertEqual(result_elem, result) 

5615 

5616 def test_delete_snapmirror_policy(self): 

5617 api_response = fake.GET_SNAPMIRROR_POLICIES_REST 

5618 self.mock_object(self.client, 'send_request', 

5619 mock.Mock(return_value=api_response)) 

5620 

5621 self.client.delete_snapmirror_policy('fake_policy') 

5622 

5623 query = {} 

5624 query['name'] = 'fake_policy' 

5625 query['fields'] = 'uuid,name' 

5626 uuid = fake.FAKE_UUID 

5627 self.client.send_request.assert_has_calls([ 

5628 mock.call('/snapmirror/policies', 'get', query=query), 

5629 mock.call(f'/snapmirror/policies/{uuid}', 'delete') 

5630 ]) 

5631 

5632 def test_delete_snapmirror_policy_exception(self): 

5633 api_response = fake.GET_SNAPMIRROR_POLICIES_REST 

5634 api_error = netapp_api.api.NaApiError() 

5635 self.mock_object(self.client, 'send_request', 

5636 mock.Mock(side_effect=[api_response, api_error])) 

5637 self.assertRaises(netapp_api.api.NaApiError, 

5638 self.client.delete_snapmirror_policy, 

5639 'fake_policy') 

5640 

5641 def test_delete_snapmirror_policy_no_records(self): 

5642 api_response = fake.NO_RECORDS_RESPONSE_REST 

5643 self.mock_object(self.client, 'send_request', 

5644 mock.Mock(return_value=api_response)) 

5645 

5646 self.client.delete_snapmirror_policy('fake_policy') 

5647 

5648 query = {} 

5649 query['name'] = 'fake_policy' 

5650 query['fields'] = 'uuid,name' 

5651 self.client.send_request.assert_called_once_with( 

5652 '/snapmirror/policies', 'get', query=query) 

5653 

5654 def test_delete_vserver_one_volume(self): 

5655 self.mock_object(self.client, 'get_vserver_info', 

5656 mock.Mock(return_value=fake.VSERVER_INFO)) 

5657 self.mock_object(self.client, '_get_unique_svm_by_name', 

5658 mock.Mock(return_value=fake.FAKE_UUID)) 

5659 self.mock_object(self.client, 'get_vserver_root_volume_name', 

5660 mock.Mock(return_value=fake.ROOT_VOLUME_NAME)) 

5661 self.mock_object(self.client, 'get_vserver_volume_count', 

5662 mock.Mock(return_value=1)) 

5663 self.mock_object(self.client, 'send_request') 

5664 self.mock_object(self.client, 'offline_volume') 

5665 self.mock_object(self.client, 'delete_volume') 

5666 self.mock_object(self.client, '_terminate_vserver_services') 

5667 

5668 self.client.delete_vserver(fake.VSERVER_NAME, self.client, 

5669 fake.CIFS_SECURITY_SERVICE) 

5670 

5671 self.client.offline_volume.assert_called_with(fake.ROOT_VOLUME_NAME) 

5672 self.client.delete_volume.assert_called_with(fake.ROOT_VOLUME_NAME) 

5673 self.client._terminate_vserver_services( 

5674 fake.VSERVER_NAME, self.client, fake.CIFS_SECURITY_SERVICE) 

5675 

5676 svm_uuid = fake.FAKE_UUID 

5677 self.client.send_request.assert_has_calls([ 

5678 mock.call(f'/svm/svms/{svm_uuid}', 'delete')]) 

5679 

5680 def test_delete_vserver_one_volume_already_offline(self): 

5681 

5682 self.mock_object(self.client, 

5683 'get_vserver_info', 

5684 mock.Mock(return_value=fake.VSERVER_INFO)) 

5685 self.mock_object(self.client, 

5686 '_get_unique_svm_by_name', 

5687 mock.Mock(return_value=fake.FAKE_UUID)) 

5688 self.mock_object(self.client, 

5689 'get_vserver_root_volume_name', 

5690 mock.Mock(return_value=fake.ROOT_VOLUME_NAME)) 

5691 self.mock_object(self.client, 

5692 'get_vserver_volume_count', 

5693 mock.Mock(return_value=1)) 

5694 self.mock_object(self.client, 

5695 'offline_volume', 

5696 self._mock_api_error( 

5697 code=netapp_api.EREST_ENTRY_NOT_FOUND)) 

5698 self.mock_object(self.client, 'send_request') 

5699 self.mock_object(self.client, 'delete_volume') 

5700 

5701 self.client.delete_vserver(fake.VSERVER_NAME, 

5702 self.client) 

5703 

5704 self.client.offline_volume.assert_called_with( 

5705 fake.ROOT_VOLUME_NAME) 

5706 self.client.delete_volume.assert_called_with( 

5707 fake.ROOT_VOLUME_NAME) 

5708 

5709 svm_uuid = fake.FAKE_UUID 

5710 self.client.send_request.assert_has_calls([ 

5711 mock.call(f'/svm/svms/{svm_uuid}', 'delete')]) 

5712 self.assertEqual(1, client_cmode_rest.LOG.error.call_count) 

5713 

5714 def test_delete_vserver_one_volume_api_error(self): 

5715 

5716 self.mock_object(self.client, 

5717 'get_vserver_info', 

5718 mock.Mock(return_value=fake.VSERVER_INFO)) 

5719 self.mock_object(self.client, 

5720 '_get_unique_svm_by_name', 

5721 mock.Mock(return_value=fake.FAKE_UUID)) 

5722 self.mock_object(self.client, 

5723 'get_vserver_root_volume_name', 

5724 mock.Mock(return_value=fake.ROOT_VOLUME_NAME)) 

5725 self.mock_object(self.client, 'send_request') 

5726 self.mock_object(self.client, 

5727 'get_vserver_volume_count', 

5728 mock.Mock(return_value=1)) 

5729 self.mock_object(self.client, 

5730 'offline_volume', 

5731 self._mock_api_error()) 

5732 self.mock_object(self.client, 'delete_volume') 

5733 

5734 self.assertRaises(netapp_api.api.NaApiError, 

5735 self.client.delete_vserver, 

5736 fake.VSERVER_NAME, 

5737 self.client) 

5738 

5739 def test_delete_vserver_multiple_volumes(self): 

5740 

5741 self.mock_object(self.client, 

5742 'get_vserver_info', 

5743 mock.Mock(return_value=fake.VSERVER_INFO)) 

5744 self.mock_object(self.client, 

5745 '_get_unique_svm_by_name', 

5746 mock.Mock(return_value=fake.FAKE_UUID)) 

5747 self.mock_object(self.client, 

5748 'get_vserver_root_volume_name', 

5749 mock.Mock(return_value=fake.ROOT_VOLUME_NAME)) 

5750 self.mock_object(self.client, 

5751 'get_vserver_volume_count', 

5752 mock.Mock(return_value=2)) 

5753 

5754 self.assertRaises(exception.NetAppException, 

5755 self.client.delete_vserver, 

5756 fake.VSERVER_NAME, 

5757 self.client) 

5758 

5759 def test_delete_vserver_not_found(self): 

5760 

5761 self.mock_object(self.client, 

5762 'get_vserver_info', 

5763 mock.Mock(return_value=None)) 

5764 self.mock_object(self.client, 

5765 '_get_unique_svm_by_name', 

5766 mock.Mock(return_value=fake.FAKE_UUID)) 

5767 

5768 self.client.delete_vserver(fake.VSERVER_NAME, 

5769 self.client) 

5770 

5771 self.assertEqual(1, client_cmode_rest.LOG.error.call_count) 

5772 

5773 def test_get_vserver_volume_count(self): 

5774 fake_response = fake.VOLUME_GET_ITER_RESPONSE_REST_PAGE 

5775 mock_request = self.mock_object(self.client, 'send_request', 

5776 mock.Mock(return_value=fake_response)) 

5777 response = self.client.get_vserver_volume_count() 

5778 

5779 self.assertEqual(response, 10) 

5780 query = {'return_records': 'false'} 

5781 mock_request.assert_called_once_with( 

5782 '/storage/volumes', 'get', query=query) 

5783 

5784 def test__terminate_vserver_services(self): 

5785 

5786 fake_uuid = fake.FAKE_UUID 

5787 

5788 self.mock_object(self.client, 'send_request') 

5789 self.mock_object(self.client, 'disable_kerberos') 

5790 self.mock_object(self.client, '_get_unique_svm_by_name', 

5791 mock.Mock(return_value=fake_uuid)) 

5792 

5793 security_services = [ 

5794 copy.deepcopy(fake.CIFS_SECURITY_SERVICE), 

5795 copy.deepcopy(fake.KERBEROS_SECURITY_SERVICE) 

5796 ] 

5797 self.client._terminate_vserver_services( 

5798 fake.VSERVER_NAME, self.client, security_services) 

5799 

5800 cifs_server_delete_body = { 

5801 'ad_domain.password': security_services[0]['password'], 

5802 'ad_domain.user': security_services[0]['user'], 

5803 } 

5804 self.client.send_request.assert_called_once_with( 

5805 f'/protocols/cifs/services/{fake_uuid}', 'delete', 

5806 body=cifs_server_delete_body) 

5807 self.client.disable_kerberos.assert_called_once_with( 

5808 security_services[1]) 

5809 

5810 def test_terminate_vserver_services_cifs_not_found(self): 

5811 

5812 fake_uuid = fake.FAKE_UUID 

5813 

5814 self.mock_object( 

5815 self.client, 'send_request', 

5816 self._mock_api_error(code=netapp_api.EREST_ENTRY_NOT_FOUND)) 

5817 self.mock_object(self.client, '_get_unique_svm_by_name', 

5818 mock.Mock(return_value=fake_uuid)) 

5819 

5820 security_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE) 

5821 self.client._terminate_vserver_services(fake.VSERVER_NAME, 

5822 self.client, 

5823 [security_service]) 

5824 

5825 cifs_server_delete_body = { 

5826 'ad_domain.password': security_service['password'], 

5827 'ad_domain.user': security_service['user'], 

5828 } 

5829 self.client.send_request.assert_called_once_with( 

5830 f'/protocols/cifs/services/{fake_uuid}', 'delete', 

5831 body=cifs_server_delete_body) 

5832 self.assertEqual(1, client_cmode_rest.LOG.error.call_count) 

5833 

5834 def test_terminate_vserver_services_api_error(self): 

5835 

5836 fake_uuid = fake.FAKE_UUID 

5837 side_effects = [netapp_api.api.NaApiError(code='fake'), None] 

5838 

5839 self.mock_object(self.client, 

5840 'send_request', 

5841 mock.Mock(side_effect=side_effects)) 

5842 self.mock_object(self.client, '_get_unique_svm_by_name', 

5843 mock.Mock(return_value=fake_uuid)) 

5844 

5845 security_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE) 

5846 self.client._terminate_vserver_services(fake.VSERVER_NAME, 

5847 self.client, 

5848 [security_service]) 

5849 

5850 cifs_server_delete_body = { 

5851 'ad_domain.password': security_service['password'], 

5852 'ad_domain.user': security_service['user'], 

5853 } 

5854 cifs_server_delete_force_body = { 

5855 'ad_domain.password': security_service['password'], 

5856 'ad_domain.user': security_service['user'], 

5857 'force': True 

5858 } 

5859 

5860 self.client.send_request.assert_has_calls([ 

5861 mock.call(f'/protocols/cifs/services/{fake_uuid}', 'delete', 

5862 body=cifs_server_delete_body), 

5863 mock.call(f'/protocols/cifs/services/{fake_uuid}', 'delete', 

5864 body=cifs_server_delete_force_body)]) 

5865 self.assertEqual(0, client_cmode_rest.LOG.error.call_count) 

5866 

5867 def test_disable_kerberos(self): 

5868 fake_api_response = fake.NFS_LIFS_REST 

5869 api_error = self._mock_api_error( 

5870 code=netapp_api.EREST_KERBEROS_IS_ENABLED_DISABLED) 

5871 self.mock_object(self.client, 'get_network_interfaces', 

5872 mock.Mock(return_value=fake_api_response)) 

5873 self.mock_object( 

5874 self.client, 'send_request', 

5875 mock.Mock(side_effect=[None, api_error, None])) 

5876 

5877 self.client.disable_kerberos(fake.KERBEROS_SECURITY_SERVICE) 

5878 

5879 kerberos_config_modify_body = { 

5880 'password': fake.KERBEROS_SECURITY_SERVICE['password'], 

5881 'user': fake.KERBEROS_SECURITY_SERVICE['user'], 

5882 'interface.name': fake.LIF_NAME, 

5883 'enabled': False, 

5884 } 

5885 

5886 self.client.send_request.assert_has_calls([ 

5887 mock.call('/protocols/nfs/kerberos/interfaces/fake_uuid_1', 

5888 'patch', body=kerberos_config_modify_body), 

5889 mock.call('/protocols/nfs/kerberos/interfaces/fake_uuid_2', 

5890 'patch', body=kerberos_config_modify_body), 

5891 mock.call('/protocols/nfs/kerberos/interfaces/fake_uuid_3', 

5892 'patch', body=kerberos_config_modify_body) 

5893 ]) 

5894 self.client.get_network_interfaces.assert_called_once() 

5895 

5896 def test_get_vserver_root_volume_name(self): 

5897 response = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

5898 self.mock_object(self.client, '_get_volume_by_args', 

5899 mock.Mock(return_value=response)) 

5900 self.client.get_vserver_root_volume_name(fake.VSERVER_NAME) 

5901 self.client._get_volume_by_args.assert_called_once_with( 

5902 vserver=fake.VSERVER_NAME, is_root=True) 

5903 

5904 def test_ipspace_has_data_vservers(self): 

5905 api_response = fake.REST_VSERVER_GET_IPSPACE_NAME_RESPONSE 

5906 self.mock_object(self.client, 

5907 'send_request', 

5908 mock.Mock(return_value=api_response)) 

5909 

5910 result = self.client.ipspace_has_data_vservers(fake.IPSPACE_NAME) 

5911 

5912 query = {'ipspace.name': fake.IPSPACE_NAME} 

5913 self.client.send_request.assert_has_calls([ 

5914 mock.call('/svm/svms', 'get', query=query)]) 

5915 self.assertTrue(result) 

5916 

5917 def test_ipspace_has_data_vservers_not_supported(self): 

5918 self.mock_object(self.client, 'send_request', 

5919 mock.Mock(return_value='fake_response')) 

5920 self.mock_object(self.client, '_has_records', 

5921 mock.Mock(return_value=False)) 

5922 

5923 result = self.client.ipspace_has_data_vservers(fake.IPSPACE_NAME) 

5924 

5925 self.assertFalse(result) 

5926 query = {'ipspace.name': fake.IPSPACE_NAME} 

5927 self.client.send_request.assert_called_once_with( 

5928 '/svm/svms', 'get', query=query) 

5929 self.client._has_records.assert_called_once_with('fake_response') 

5930 

5931 def test_ipspace_has_data_vservers_not_found(self): 

5932 api_response = fake.NO_RECORDS_RESPONSE_REST 

5933 self.mock_object(self.client, 

5934 'send_request', 

5935 mock.Mock(return_value=api_response)) 

5936 

5937 result = self.client.ipspace_has_data_vservers(fake.IPSPACE_NAME) 

5938 

5939 self.assertFalse(result) 

5940 

5941 def test_delete_vlan(self): 

5942 self.mock_object(self.client, 'send_request') 

5943 

5944 query = { 

5945 'vlan.base_port.name': fake.PORT, 

5946 'node.name': fake.NODE_NAME, 

5947 'vlan.tag': fake.VLAN 

5948 } 

5949 

5950 self.client.delete_vlan(fake.NODE_NAME, fake.PORT, fake.VLAN) 

5951 

5952 self.client.send_request.assert_has_calls([ 

5953 mock.call('/network/ethernet/ports/', 'delete', query=query)]) 

5954 

5955 def test_delete_vlan_not_found(self): 

5956 self.mock_object( 

5957 self.client, 'send_request', 

5958 self._mock_api_error(code=netapp_api.EREST_ENTRY_NOT_FOUND)) 

5959 

5960 query = { 

5961 'vlan.base_port.name': fake.PORT, 

5962 'node.name': fake.NODE_NAME, 

5963 'vlan.tag': fake.VLAN 

5964 } 

5965 

5966 self.client.delete_vlan(fake.NODE_NAME, fake.PORT, fake.VLAN) 

5967 

5968 self.client.send_request.assert_has_calls([ 

5969 mock.call('/network/ethernet/ports/', 'delete', query=query)]) 

5970 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count) 

5971 

5972 def test_delete_vlan_still_used(self): 

5973 self.mock_object( 

5974 self.client, 'send_request', 

5975 self._mock_api_error(code=netapp_api.EREST_PORT_IN_USE)) 

5976 

5977 query = { 

5978 'vlan.base_port.name': fake.PORT, 

5979 'node.name': fake.NODE_NAME, 

5980 'vlan.tag': fake.VLAN 

5981 } 

5982 

5983 self.client.delete_vlan(fake.NODE_NAME, fake.PORT, fake.VLAN) 

5984 

5985 self.client.send_request.assert_has_calls([ 

5986 mock.call('/network/ethernet/ports/', 'delete', query=query)]) 

5987 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count) 

5988 

5989 def test_delete_vlan_api_error(self): 

5990 self.mock_object(self.client, 'send_request', self._mock_api_error()) 

5991 self.assertRaises(exception.NetAppException, 

5992 self.client.delete_vlan, 

5993 fake.NODE_NAME, 

5994 fake.PORT, 

5995 fake.VLAN) 

5996 

5997 @ddt.data(None, fake.IPSPACE_NAME) 

5998 def test_svm_migration_start(self, dest_ipspace): 

5999 check_only = True 

6000 self.mock_object(self.client, 'send_request', 

6001 mock.Mock(return_value='fake_migration')) 

6002 

6003 res = self.client.svm_migration_start( 

6004 fake.CLUSTER_NAME, fake.VSERVER_NAME, fake.SHARE_AGGREGATE_NAMES, 

6005 dest_ipspace=dest_ipspace, check_only=check_only) 

6006 

6007 self.assertEqual('fake_migration', res) 

6008 expected_body = { 

6009 "auto_cutover": False, 

6010 "auto_source_cleanup": True, 

6011 "check_only": True, 

6012 "source": { 

6013 "cluster": {"name": fake.CLUSTER_NAME}, 

6014 "svm": {"name": fake.VSERVER_NAME}, 

6015 }, 

6016 "destination": { 

6017 "volume_placement": { 

6018 "aggregates": fake.SHARE_AGGREGATE_NAMES, 

6019 }, 

6020 }, 

6021 } 

6022 if dest_ipspace is not None: 

6023 ipspace_data = { 

6024 "ipspace": { 

6025 "name": dest_ipspace, 

6026 } 

6027 } 

6028 expected_body["destination"].update(ipspace_data) 

6029 self.client.send_request.assert_called_once_with( 

6030 '/svm/migrations', 'post', body=expected_body, 

6031 wait_on_accepted=False) 

6032 

6033 def test_get_migration_check_job_state(self): 

6034 self.mock_object(self.client, 'get_job', 

6035 mock.Mock(return_value='fake_job')) 

6036 

6037 res = self.client.get_migration_check_job_state(fake.JOB_ID) 

6038 

6039 self.assertEqual('fake_job', res) 

6040 self.client.get_job.assert_called_once_with(fake.JOB_ID) 

6041 

6042 @ddt.data(netapp_api.api.ENFS_V4_0_ENABLED_MIGRATION_FAILURE, 

6043 netapp_api.api.EVSERVER_MIGRATION_TO_NON_AFF_CLUSTER, 'none') 

6044 def test_get_migration_check_job_state_raise_error(self, error_code): 

6045 e = netapp_api.api.NaApiError(code=error_code) 

6046 self.mock_object(self.client, 'get_job', mock.Mock(side_effect=e)) 

6047 

6048 self.assertRaises( 

6049 exception.NetAppException, 

6050 self.client.get_migration_check_job_state, 

6051 fake.JOB_ID) 

6052 

6053 def test_svm_migrate_complete(self): 

6054 self.mock_object(self.client, 'send_request', 

6055 mock.Mock(return_value='fake_migration')) 

6056 

6057 res = self.client.svm_migrate_complete(fake.FAKE_MIGRATION_POST_ID) 

6058 

6059 self.assertEqual('fake_migration', res) 

6060 expected_body = { 

6061 "action": "cutover" 

6062 } 

6063 self.client.send_request.assert_called_once_with( 

6064 f'/svm/migrations/{fake.FAKE_MIGRATION_POST_ID}', 'patch', 

6065 body=expected_body, wait_on_accepted=False) 

6066 

6067 def test_svm_migrate_cancel(self): 

6068 self.mock_object(self.client, 'send_request', 

6069 mock.Mock(return_value='fake_migration')) 

6070 

6071 res = self.client.svm_migrate_cancel(fake.FAKE_MIGRATION_POST_ID) 

6072 

6073 self.assertEqual('fake_migration', res) 

6074 self.client.send_request.assert_called_once_with( 

6075 f'/svm/migrations/{fake.FAKE_MIGRATION_POST_ID}', 'delete', 

6076 wait_on_accepted=False) 

6077 

6078 def test_svm_migration_get(self): 

6079 self.mock_object(self.client, 'send_request', 

6080 mock.Mock(return_value='fake_migration')) 

6081 

6082 res = self.client.svm_migration_get(fake.FAKE_MIGRATION_POST_ID) 

6083 

6084 self.assertEqual('fake_migration', res) 

6085 self.client.send_request.assert_called_once_with( 

6086 f'/svm/migrations/{fake.FAKE_MIGRATION_POST_ID}', 'get') 

6087 

6088 def test_svm_migrate_pause(self): 

6089 self.mock_object(self.client, 'send_request', 

6090 mock.Mock(return_value='fake_migration')) 

6091 

6092 res = self.client.svm_migrate_pause(fake.FAKE_MIGRATION_POST_ID) 

6093 

6094 self.assertEqual('fake_migration', res) 

6095 expected_body = { 

6096 "action": "pause" 

6097 } 

6098 self.client.send_request.assert_called_once_with( 

6099 f'/svm/migrations/{fake.FAKE_MIGRATION_POST_ID}', 'patch', 

6100 body=expected_body, wait_on_accepted=False) 

6101 

6102 def test_delete_network_interface(self): 

6103 self.mock_object(self.client, 'disable_network_interface') 

6104 self.mock_object(self.client, 'send_request') 

6105 

6106 self.client.delete_network_interface(fake.VSERVER_NAME, fake.LIF_NAME) 

6107 

6108 self.client.disable_network_interface.assert_called_once_with( 

6109 fake.VSERVER_NAME, fake.LIF_NAME) 

6110 expected_query = { 

6111 'svm.name': fake.VSERVER_NAME, 

6112 'name': fake.LIF_NAME 

6113 } 

6114 self.client.send_request.assert_called_once_with( 

6115 '/network/ip/interfaces', 'delete', query=expected_query) 

6116 

6117 def test_disable_network_interface(self): 

6118 self.mock_object(self.client, 'send_request') 

6119 

6120 self.client.disable_network_interface(fake.VSERVER_NAME, fake.LIF_NAME) 

6121 

6122 expected_body = { 

6123 'enabled': 'false' 

6124 } 

6125 expected_query = { 

6126 'svm.name': fake.VSERVER_NAME, 

6127 'name': fake.LIF_NAME 

6128 } 

6129 self.client.send_request.assert_called_once_with( 

6130 '/network/ip/interfaces', 'patch', body=expected_body, 

6131 query=expected_query) 

6132 

6133 def test__delete_port_and_broadcast_domain(self): 

6134 

6135 domain = copy.deepcopy(fake.BROADCAST_DOMAIN) 

6136 ipspace = copy.deepcopy(fake.GET_IPSPACES_RESPONSE) 

6137 

6138 query = {'name': domain, 'ipspace.name': ipspace['ipspace']} 

6139 

6140 response_broadcast = copy.deepcopy( 

6141 fake.BROADCAST_DOMAIN_LIST_SIMPLE_RESPONSE_REST) 

6142 self.mock_object(self.client, 

6143 'send_request', 

6144 mock.Mock(side_effect=[response_broadcast, None])) 

6145 

6146 self.mock_object(self.client, 

6147 '_delete_port_by_ipspace_and_broadcast_domain') 

6148 

6149 self.client._delete_port_and_broadcast_domain(domain, ipspace) 

6150 self.client.send_request.assert_has_calls([ 

6151 mock.call('/network/ethernet/broadcast-domains', 

6152 'delete', query=query)]) 

6153 

6154 def test_delete_ipspace(self): 

6155 ipspace = copy.deepcopy(fake.IPSPACES[0]) 

6156 mock_del_brcst = self.mock_object( 

6157 self.client, '_delete_port_and_broadcast_domains_for_ipspace') 

6158 self.mock_object(self.client, 'ipspace_has_data_vservers', 

6159 mock.Mock(return_value=[])) 

6160 mock_send_request = self.mock_object(self.client, 'send_request') 

6161 

6162 query = {'name': fake.IPSPACE_NAME} 

6163 

6164 self.client.delete_ipspace(ipspace['ipspace']) 

6165 

6166 mock_del_brcst.assert_called_once_with(fake.IPSPACE_NAME) 

6167 

6168 mock_send_request.assert_called_once_with( 

6169 '/network/ipspaces', 'delete', query=query) 

6170 

6171 def test_get_ipspaces(self): 

6172 expected = copy.deepcopy(fake.GET_IPSPACES_RESPONSE) 

6173 sr_responses = [fake.IPSPACE_INFO, 

6174 fake.REST_SINGLE_PORT, 

6175 fake.SVMS_LIST_SIMPLE_RESPONSE_REST, 

6176 fake.FAKE_GET_BROADCAST_DOMAIN] 

6177 self.mock_object(self.client, 'send_request', 

6178 mock.Mock(side_effect=sr_responses)) 

6179 self.mock_object(self.client, '_has_records', 

6180 mock.Mock(return_value=True)) 

6181 result = self.client.get_ipspaces(fake.IPSPACE_NAME) 

6182 self.assertEqual(expected, result) 

6183 

6184 def test_get_ipspaces_no_records(self): 

6185 api_response = fake.NO_RECORDS_RESPONSE_REST 

6186 self.mock_object(self.client, 'send_request', 

6187 mock.Mock(return_value=api_response)) 

6188 result = self.client.get_ipspaces(fake.IPSPACE_NAME) 

6189 self.assertEqual([], result) 

6190 

6191 def test_delete_port_and_broadcast_domains_for_ipspace_not_found(self): 

6192 

6193 self.mock_object(self.client, 

6194 'get_ipspaces', 

6195 mock.Mock(return_value=[])) 

6196 self.mock_object(self.client, '_delete_port_and_broadcast_domain') 

6197 

6198 self.client._delete_port_and_broadcast_domains_for_ipspace( 

6199 fake.IPSPACE_NAME) 

6200 

6201 self.client.get_ipspaces.assert_called_once_with( 

6202 fake.IPSPACE_NAME) 

6203 self.assertFalse(self.client._delete_port_and_broadcast_domain.called) 

6204 

6205 def test_delete_port_and_broadcast_domains_for_ipspace(self): 

6206 

6207 self.mock_object(self.client, 

6208 'get_ipspaces', 

6209 mock.Mock(return_value=fake.IPSPACES[0])) 

6210 self.mock_object(self.client, '_delete_port_and_broadcast_domain') 

6211 

6212 self.client._delete_port_and_broadcast_domains_for_ipspace( 

6213 fake.IPSPACE_NAME) 

6214 

6215 self.client.get_ipspaces.assert_called_once_with( 

6216 fake.IPSPACE_NAME) 

6217 self.client._delete_port_and_broadcast_domain.assert_called_once_with( 

6218 fake.IPSPACES[0]['broadcast-domains'][0], fake.IPSPACES[0]) 

6219 

6220 @ddt.data(('10.10.10.0/24', '10.10.10.1', False), 

6221 ('fc00::/7', 'fe80::1', False), 

6222 ('0.0.0.0/0', '10.10.10.1', True), 

6223 ('::/0', 'fe80::1', True)) 

6224 @ddt.unpack 

6225 def test_create_route(self, subnet, gateway, omit_destination): 

6226 

6227 address = None 

6228 netmask = None 

6229 destination = None if omit_destination else subnet 

6230 if not destination: 

6231 if netutils.is_valid_ipv6(destination): 6231 ↛ 6232line 6231 didn't jump to line 6232 because the condition on line 6231 was never true

6232 destination = '::/0' 

6233 else: 

6234 destination = '0.0.0.0/0' 

6235 

6236 if '/' in destination: 6236 ↛ 6239line 6236 didn't jump to line 6239 because the condition on line 6236 was always true

6237 address, netmask = destination.split('/') 

6238 else: 

6239 address = destination 

6240 

6241 body = { 

6242 'destination.address': address, 

6243 'gateway': gateway, 

6244 } 

6245 

6246 if netmask: 6246 ↛ 6249line 6246 didn't jump to line 6249 because the condition on line 6246 was always true

6247 body['destination.netmask'] = netmask 

6248 

6249 self.mock_object(self.client, 'send_request') 

6250 

6251 self.client.create_route(gateway, destination=destination) 

6252 

6253 self.client.send_request.assert_called_once_with( 

6254 '/network/ip/routes', 'post', body=body) 

6255 

6256 def test_create_route_duplicate(self): 

6257 self.mock_object(client_cmode_rest.LOG, 'debug') 

6258 self.mock_object( 

6259 self.client, 'send_request', 

6260 self._mock_api_error(code=netapp_api.EREST_DUPLICATE_ROUTE)) 

6261 

6262 self.client.create_route(fake.GATEWAY, destination=fake.SUBNET) 

6263 

6264 body = { 

6265 'destination.address': fake.SUBNET[:-3], 

6266 'gateway': fake.GATEWAY, 

6267 'destination.netmask': fake.SUBNET[-2:], 

6268 } 

6269 self.client.send_request.assert_called_once_with( 

6270 '/network/ip/routes', 'post', body=body) 

6271 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count) 

6272 

6273 def test_create_route_api_error(self): 

6274 self.mock_object(client_cmode_rest.LOG, 'debug') 

6275 self.mock_object(self.client, 'send_request', self._mock_api_error()) 

6276 

6277 body = { 

6278 'destination.address': fake.SUBNET[:-3], 

6279 'gateway': fake.GATEWAY, 

6280 'destination.netmask': fake.SUBNET[-2:], 

6281 } 

6282 self.assertRaises(exception.NetAppException, 

6283 self.client.create_route, 

6284 fake.GATEWAY, destination=fake.SUBNET) 

6285 self.client.send_request.assert_called_once_with( 

6286 '/network/ip/routes', 'post', body=body) 

6287 

6288 def test_create_route_without_gateway(self): 

6289 self.mock_object(self.client, 'send_request') 

6290 self.client.create_route(None, destination=fake.SUBNET) 

6291 self.assertFalse(self.client.send_request.called) 

6292 

6293 def test_network_interface_exists(self): 

6294 api_response = fake.GENERIC_NETWORK_INTERFACES_GET_REPONSE 

6295 self.mock_object(self.client, 'send_request', 

6296 mock.Mock(return_value=api_response)) 

6297 result = self.client.network_interface_exists( 

6298 fake.VSERVER_NAME, fake.NODE_NAME, fake.PORT, fake.IP_ADDRESS, 

6299 fake.NETMASK, fake.VLAN) 

6300 query = { 

6301 'ip.address': fake.IP_ADDRESS, 

6302 'location.home_node.name': fake.NODE_NAME, 

6303 'location.home_port.name': f'{fake.PORT}-{fake.VLAN}', 

6304 'ip.netmask': fake.NETMASK, 

6305 'svm.name': fake.VSERVER_NAME, 

6306 'fields': 'name', 

6307 } 

6308 self.client.send_request.assert_called_once_with( 

6309 '/network/ip/interfaces', 'get', query=query) 

6310 self.assertTrue(result) 

6311 

6312 def test_modify_active_directory_security_service(self): 

6313 svm_uuid = fake.FAKE_UUID 

6314 user_records = fake.FAKE_CIFS_LOCAL_USER.get('records')[0] 

6315 sid = user_records.get('sid') 

6316 self.mock_object(self.client, '_get_unique_svm_by_name', 

6317 mock.Mock(return_value=svm_uuid)) 

6318 self.mock_object(self.client, 'send_request', 

6319 mock.Mock(side_effect=[user_records, 

6320 None, None])) 

6321 self.mock_object(self.client, 'remove_preferred_dcs') 

6322 self.mock_object(self.client, 'set_preferred_dc') 

6323 new_security_service = { 

6324 'user': 'new_user', 

6325 'password': 'new_password', 

6326 'server': 'fake_server' 

6327 } 

6328 

6329 current_security_service = { 

6330 'server': 'fake_current_server' 

6331 } 

6332 keys = {'user', 'password', 'server'} 

6333 

6334 self.client.modify_active_directory_security_service( 

6335 fake.VSERVER_NAME, keys, new_security_service, 

6336 current_security_service) 

6337 

6338 self.client.send_request.assert_has_calls([ 

6339 mock.call(f'/protocols/cifs/local-users/{svm_uuid}', 'get'), 

6340 mock.call(f'/protocols/cifs/local-users/{svm_uuid}/{sid}', 'patch', 

6341 query={'password': new_security_service['password']}), 

6342 mock.call(f'/protocols/cifs/local-users/{svm_uuid}/{sid}', 'patch', 

6343 query={'name': new_security_service['user']}) 

6344 ]) 

6345 

6346 @ddt.data(True, False) 

6347 def test__create_vserver(self, logical_space_reporting): 

6348 mock_sr = self.mock_object(self.client, 'send_request') 

6349 self.mock_object(self.client, '_get_unique_svm_by_name', 

6350 mock.Mock(return_value=fake.FAKE_UUID)) 

6351 body_post = { 

6352 'name': fake.VSERVER_NAME, 

6353 'nsswitch.namemap': fake.FAKE_SERVER_SWITCH_NAME, 

6354 'subtype': fake.FAKE_SUBTYPE, 

6355 'ipspace.name': fake.IPSPACE_NAME, 

6356 'aggregates': [{ 

6357 'name': fake.SHARE_AGGREGATE_NAME 

6358 }], 

6359 } 

6360 

6361 if logical_space_reporting: 

6362 body_post.update({ 

6363 'is_space_reporting_logical': 'true', 

6364 'is_space_enforcement_logical': 'true', 

6365 }) 

6366 else: 

6367 body_post.update({ 

6368 'is_space_reporting_logical': 'false', 

6369 'is_space_enforcement_logical': 'false', 

6370 }) 

6371 

6372 body_patch = { 

6373 'retention_period': fake.DELETE_RETENTION_HOURS, 

6374 } 

6375 

6376 self.client._create_vserver( 

6377 fake.VSERVER_NAME, 

6378 [fake.SHARE_AGGREGATE_NAME], 

6379 fake.IPSPACE_NAME, 

6380 fake.DELETE_RETENTION_HOURS, 

6381 fake.FAKE_SERVER_SWITCH_NAME, 

6382 fake.FAKE_SUBTYPE, 

6383 logical_space_reporting=logical_space_reporting) 

6384 

6385 mock_sr.assert_has_calls([ 

6386 mock.call('/svm/svms', 'post', body=body_post), 

6387 mock.call(f'/svm/svms/{fake.FAKE_UUID}', 'patch', body=body_patch) 

6388 ]) 

6389 

6390 @ddt.data(0, 65535, 270000) 

6391 def test__create_vserver_delete_retention_hours(self, 

6392 delete_retention_hours): 

6393 mock_sr = self.mock_object(self.client, 'send_request') 

6394 self.mock_object(self.client, '_get_unique_svm_by_name', 

6395 mock.Mock(return_value=fake.FAKE_UUID)) 

6396 body_post = { 

6397 'name': fake.VSERVER_NAME, 

6398 'nsswitch.namemap': fake.FAKE_SERVER_SWITCH_NAME, 

6399 'subtype': fake.FAKE_SUBTYPE, 

6400 'ipspace.name': fake.IPSPACE_NAME, 

6401 'is_space_reporting_logical': 'false', 

6402 'is_space_enforcement_logical': 'false', 

6403 'aggregates': [{ 

6404 'name': fake.SHARE_AGGREGATE_NAME 

6405 }], 

6406 } 

6407 

6408 body_patch = { 

6409 'retention_period': delete_retention_hours, 

6410 } 

6411 

6412 self.client._create_vserver( 

6413 fake.VSERVER_NAME, 

6414 [fake.SHARE_AGGREGATE_NAME], 

6415 fake.IPSPACE_NAME, 

6416 delete_retention_hours, 

6417 fake.FAKE_SERVER_SWITCH_NAME, 

6418 fake.FAKE_SUBTYPE) 

6419 

6420 mock_sr.assert_has_calls([ 

6421 mock.call('/svm/svms', 'post', body=body_post), 

6422 mock.call(f'/svm/svms/{fake.FAKE_UUID}', 'patch', body=body_patch) 

6423 ]) 

6424 

6425 def test_create_barbican_kms_config_for_specified_vserver(self): 

6426 mock_sr = self.mock_object(self.client, 'send_request') 

6427 body = { 

6428 'svm.name': fake.VSERVER_NAME, 

6429 'configuration.name': fake.FAKE_CONFIG_NAME, 

6430 'key_id': fake.FAKE_KEY_ID, 

6431 'keystone_url': fake.FAKE_KEYSTONE_URL, 

6432 'application_cred_id': fake.FAKE_APPLICATION_CRED_ID, 

6433 'application_cred_secret': fake.FAKE_APPLICATION_CRED_SECRET, 

6434 } 

6435 

6436 self.client.create_barbican_kms_config_for_specified_vserver( 

6437 fake.VSERVER_NAME, 

6438 fake.FAKE_CONFIG_NAME, 

6439 fake.FAKE_KEY_ID, 

6440 fake.FAKE_KEYSTONE_URL, 

6441 fake.FAKE_APPLICATION_CRED_ID, 

6442 fake.FAKE_APPLICATION_CRED_SECRET) 

6443 

6444 mock_sr.assert_called_once_with('/security/barbican-kms', 'post', 

6445 body=body) 

6446 

6447 def test_get_key_store_config_uuid(self): 

6448 fake_query = { 

6449 'configuration.name': fake.FAKE_CONFIG_NAME 

6450 } 

6451 

6452 self.mock_object( 

6453 self.client, 'send_request', mock.Mock( 

6454 return_value=fake.KEYSTORE_SIMPLE_RESPONSE_REST)) 

6455 

6456 actual_result = self.client.get_key_store_config_uuid( 

6457 fake.FAKE_CONFIG_NAME) 

6458 

6459 self.client.send_request.assert_called_once_with( 

6460 '/security/key-stores', 'get', query=fake_query) 

6461 

6462 expected_result = ( 

6463 fake.KEYSTORE_SIMPLE_RESPONSE_REST[ 

6464 'records'][0]['configuration']['uuid']) 

6465 self.assertEqual(expected_result, actual_result) 

6466 

6467 def test_get_key_store_config_uuid_no_response(self): 

6468 

6469 self.mock_object( 

6470 self.client, 'send_request', mock.Mock( 

6471 return_value={})) 

6472 

6473 actual_result = self.client.get_key_store_config_uuid( 

6474 fake.FAKE_CONFIG_NAME) 

6475 

6476 self.assertIsNone(actual_result) 

6477 

6478 def test_enable_key_store_config(self): 

6479 config_uuid = fake.FAKE_CONFIG_UUID 

6480 mock_sr = self.mock_object(self.client, 'send_request') 

6481 self.client.enable_key_store_config(config_uuid) 

6482 body = { 

6483 'enabled': True, 

6484 } 

6485 

6486 mock_sr.assert_called_once_with( 

6487 f'/security/key-stores/{config_uuid}', 'patch', body=body) 

6488 

6489 @ddt.data((f'/name-services/dns/{fake.FAKE_UUID}', 'patch', 

6490 ['fake_domain'], ['fake_ip']), 

6491 (f'/name-services/dns/{fake.FAKE_UUID}', 'delete', [], []), 

6492 ('/name-services/dns', 'post', ['fake_domain'], ['fake_ip'])) 

6493 @ddt.unpack 

6494 def test_update_dns_configuration_all_operations(self, endpoint, 

6495 operation, domains, ips): 

6496 return_value = fake.FAKE_DNS_CONFIG if operation != 'post' else {} 

6497 self.mock_object(self.client, 'get_dns_config', 

6498 mock.Mock(return_value=return_value)) 

6499 self.mock_object(self.client, '_get_unique_svm_by_name', 

6500 mock.Mock(return_value=fake.FAKE_UUID)) 

6501 mock_sr = self.mock_object(self.client, 'send_request') 

6502 body = { 

6503 'domains': domains, 

6504 'servers': ips 

6505 } 

6506 empty_dns_config = (not body['domains'] and not body['servers']) 

6507 if empty_dns_config: 

6508 body = {} 

6509 self.client.update_dns_configuration(ips, domains) 

6510 mock_sr.assert_called_once_with(endpoint, operation, body) 

6511 

6512 @ddt.data(True, False) 

6513 def test_delete_snapshot(self, ignore_owners): 

6514 volume_id = fake.VOLUME.get('uuid') 

6515 self.mock_object(self.client, '_get_volume_by_args', 

6516 mock.Mock(return_value=fake.VOLUME)) 

6517 response = fake.SNAPSHOTS_REST_RESPONSE 

6518 snapshot_id = response.get('records')[0].get('uuid') 

6519 mock_sr = self.mock_object(self.client, 'send_request', 

6520 mock.Mock(return_value=response)) 

6521 self.mock_object(self.client, '_has_records', 

6522 mock.Mock(return_value=True)) 

6523 query = { 

6524 'name': fake.SNAPSHOT_NAME, 

6525 'fields': 'uuid' 

6526 } 

6527 calls = [mock.call(f'/storage/volumes/{volume_id}/snapshots', 'get', 

6528 query=query)] 

6529 if ignore_owners: 

6530 query_cli = { 

6531 'vserver': self.client.vserver, 

6532 'volume': fake.VOLUME_NAMES[0], 

6533 'snapshot': fake.SNAPSHOT_NAME, 

6534 'ignore-owners': 'true' 

6535 } 

6536 calls.append(mock.call('/private/cli/snapshot', 'delete', 

6537 query=query_cli)) 

6538 else: 

6539 calls.append(mock.call(f'/storage/volumes/{volume_id}/' 

6540 f'snapshots/{snapshot_id}', 'delete')) 

6541 

6542 self.client.delete_snapshot(fake.VOLUME_NAMES[0], fake.SNAPSHOT_NAME, 

6543 ignore_owners) 

6544 mock_sr.assert_has_calls(calls) 

6545 

6546 def test_soft_delete_snapshot(self): 

6547 

6548 mock_delete_snapshot = self.mock_object(self.client, 'delete_snapshot') 

6549 mock_rename_snapshot = self.mock_object(self.client, 'rename_snapshot') 

6550 

6551 self.client.soft_delete_snapshot(fake.SHARE_NAME, fake.SNAPSHOT_NAME) 

6552 

6553 mock_delete_snapshot.assert_called_once_with( 

6554 fake.SHARE_NAME, fake.SNAPSHOT_NAME) 

6555 self.assertFalse(mock_rename_snapshot.called) 

6556 

6557 def test_volume_has_luns(self): 

6558 mock_sr = self.mock_object(self.client, 'send_request') 

6559 self.mock_object(self.client, '_has_records', 

6560 mock.Mock(return_value=True)) 

6561 result = self.client.volume_has_luns(fake.VOLUME_NAMES[0]) 

6562 query = { 

6563 'location.volume.name': fake.VOLUME_NAMES[0], 

6564 } 

6565 mock_sr.assert_called_once_with('/storage/luns/', 'get', query=query) 

6566 self.assertTrue(result) 

6567 

6568 @ddt.data(fake.VOLUME_JUNCTION_PATH, '') 

6569 def test_volume_has_junctioned_volumes(self, junction_path): 

6570 mock_sr = self.mock_object(self.client, 'send_request') 

6571 return_records = True if junction_path else False 

6572 self.mock_object(self.client, '_has_records', 

6573 mock.Mock(return_value=return_records)) 

6574 result = self.client.volume_has_junctioned_volumes(junction_path) 

6575 if junction_path: 

6576 query = { 

6577 'nas.path': junction_path + '/*', 

6578 } 

6579 

6580 mock_sr.assert_called_once_with('/storage/volumes/', 'get', 

6581 query=query) 

6582 self.assertTrue(result) 

6583 else: 

6584 self.assertFalse(result) 

6585 

6586 @ddt.data(fake.VOLUME_JUNCTION_PATH, '') 

6587 def test_get_volume_at_junction_path(self, junction_path): 

6588 response = fake.VOLUME_LIST_SIMPLE_RESPONSE_REST 

6589 return_records = True if junction_path else False 

6590 mock_sr = self.mock_object(self.client, 'send_request', 

6591 mock.Mock(return_value=response)) 

6592 self.mock_object(self.client, '_has_records', 

6593 mock.Mock(return_value=return_records)) 

6594 query = { 

6595 'nas.path': junction_path, 

6596 'fields': 'name' 

6597 } 

6598 

6599 result = self.client.get_volume_at_junction_path(junction_path) 

6600 expected = { 

6601 'name': response.get('records')[0].get('name') 

6602 } 

6603 

6604 if junction_path: 

6605 mock_sr.assert_called_once_with('/storage/volumes/', 'get', 

6606 query=query) 

6607 self.assertEqual(expected, result) 

6608 else: 

6609 self.assertIsNone(result) 

6610 

6611 def test_get_aggregate_for_volume(self): 

6612 response = fake.FAKE_SVM_AGGREGATES.get('records')[0] 

6613 mock_sr = self.mock_object(self.client, 'send_request', 

6614 mock.Mock(return_value=response)) 

6615 result = self.client.get_aggregate_for_volume(fake.VOLUME_NAMES[0]) 

6616 expected = fake.SHARE_AGGREGATE_NAMES_LIST 

6617 query = { 

6618 'name': fake.VOLUME_NAMES[0], 

6619 'fields': 'aggregates' 

6620 } 

6621 mock_sr.assert_called_once_with('/storage/volumes/', 'get', 

6622 query=query) 

6623 self.assertEqual(expected, result) 

6624 

6625 def test_get_volume_to_manage(self): 

6626 response = fake.FAKE_VOLUME_MANAGE 

6627 mock_sr = self.mock_object(self.client, 'send_request', 

6628 mock.Mock(return_value=response)) 

6629 self.mock_object(self.client, '_has_records', 

6630 mock.Mock(return_value=True)) 

6631 expected = { 

6632 'aggregate': fake.SHARE_AGGREGATE_NAME, 

6633 'aggr-list': [], 

6634 'junction-path': fake.VOLUME_JUNCTION_PATH, 

6635 'name': fake.VOLUME_NAMES[0], 

6636 'type': 'fake_type', 

6637 'style': 'flex', 

6638 'owning-vserver-name': fake.VSERVER_NAME, 

6639 'size': fake.SHARE_SIZE, 

6640 'qos-policy-group-name': fake.QOS_POLICY_GROUP_NAME 

6641 } 

6642 

6643 result = self.client.get_volume_to_manage(fake.SHARE_AGGREGATE_NAME, 

6644 fake.VOLUME_NAMES[0]) 

6645 query = { 

6646 'name': fake.VOLUME_NAMES[0], 

6647 'fields': 'name,aggregates.name,nas.path,name,type,style,' 

6648 'svm.name,qos.policy.name,space.size', 

6649 'aggregates.name': fake.SHARE_AGGREGATE_NAME 

6650 } 

6651 mock_sr.assert_called_once_with('/storage/volumes', 'get', 

6652 query=query) 

6653 self.assertEqual(expected, result) 

6654 

6655 def test_get_cifs_share_access(self): 

6656 response = fake.FAKE_CIFS_RECORDS 

6657 mock_sr = self.mock_object(self.client, 'send_request', 

6658 mock.Mock(return_value=response)) 

6659 query = { 

6660 'name': fake.SHARE_NAME 

6661 } 

6662 query_acls = { 

6663 'fields': 'user_or_group,permission' 

6664 } 

6665 expected = { 

6666 'Everyone': 'full_control', 

6667 'root': 'no_access' 

6668 } 

6669 result = self.client.get_cifs_share_access(fake.SHARE_NAME) 

6670 svm_uuid = response.get('records')[0].get('svm').get('uuid') 

6671 mock_sr.assert_has_calls([ 

6672 mock.call('/protocols/cifs/shares', 'get', query=query), 

6673 mock.call(f'/protocols/cifs/shares/{svm_uuid}/{fake.SHARE_NAME}/' 

6674 'acls', 'get', query=query_acls) 

6675 ]) 

6676 self.assertEqual(expected, result) 

6677 

6678 @ddt.data((netapp_api.EREST_LICENSE_NOT_INSTALLED, False), 

6679 (netapp_api.EREST_SNAPSHOT_NOT_SPECIFIED, True)) 

6680 @ddt.unpack 

6681 def test_check_snaprestore_license(self, code, expected): 

6682 self.mock_object(self.client, 'send_request', 

6683 mock.Mock(side_effect=self._mock_api_error(code))) 

6684 result = self.client.check_snaprestore_license() 

6685 self.assertEqual(expected, result) 

6686 body = { 

6687 'restore_to.snapshot.name': '' 

6688 } 

6689 query = { 

6690 'name': '*' 

6691 } 

6692 self.client.send_request.assert_called_once_with('/storage/volumes', 

6693 'patch', 

6694 body=body, 

6695 query=query) 

6696 

6697 def test_check_snaprestore_license_error(self): 

6698 self.mock_object(self.client, 'send_request') 

6699 self.assertRaises(exception.NetAppException, 

6700 self.client.check_snaprestore_license) 

6701 

6702 def test__sort_data_ports_by_speed(self): 

6703 ports = fake.FAKE_PORTS 

6704 result = self.client._sort_data_ports_by_speed(ports) 

6705 expected = [{'speed': '4'}, 

6706 {'speed': 'auto'}, 

6707 {'speed': 'undef'}, 

6708 {'speed': 'fake_speed'}, 

6709 {'speed': ''}] 

6710 self.assertEqual(expected, result) 

6711 

6712 def test_create_port_and_broadcast_domain(self): 

6713 self.mock_object(self.client, '_create_vlan') 

6714 self.mock_object(self.client, '_ensure_broadcast_domain_for_port') 

6715 res = self.client.create_port_and_broadcast_domain(fake.NODE_NAME, 

6716 fake.PORT, 

6717 fake.VLAN, 

6718 fake.MTU, 

6719 fake.IPSPACE_NAME) 

6720 expected = f'{fake.PORT}-{fake.VLAN}' 

6721 self.assertEqual(expected, res) 

6722 

6723 @ddt.data(netapp_api.EREST_DUPLICATE_ENTRY, None) 

6724 def test__create_vlan(self, code): 

6725 self.mock_object(self.client, 'send_request', 

6726 mock.Mock(side_effect=self._mock_api_error(code))) 

6727 if not code: 

6728 self.assertRaises(exception.NetAppException, 

6729 self.client._create_vlan, 

6730 fake.NODE_NAME, 

6731 fake.PORT, 

6732 fake.VLAN) 

6733 

6734 else: 

6735 self.client._create_vlan(fake.NODE_NAME, fake.PORT, fake.VLAN) 

6736 body = { 

6737 'vlan.base_port.name': fake.PORT, 

6738 'node.name': fake.NODE_NAME, 

6739 'vlan.tag': fake.VLAN, 

6740 'type': 'vlan' 

6741 } 

6742 self.client.send_request.assert_called_once_with( 

6743 '/network/ethernet/ports', 'post', body=body) 

6744 

6745 @ddt.data(netapp_api.EREST_ENTRY_NOT_FOUND, None) 

6746 def test_delete_fpolicy_event_error_not_found(self, code): 

6747 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

6748 self.mock_object(self.client, '_get_volume_by_args', 

6749 mock.Mock(return_value=volume)) 

6750 self.mock_object(self.client, 'send_request', 

6751 mock.Mock(side_effect=self._mock_api_error(code))) 

6752 if not code: 

6753 self.assertRaises(exception.NetAppException, 

6754 self.client.delete_fpolicy_event, 

6755 fake.SHARE_NAME, 'fake_event') 

6756 else: 

6757 self.client.delete_fpolicy_event(fake.SHARE_NAME, 'fake_event') 

6758 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count) 

6759 

6760 @ddt.data(netapp_api.EREST_ENTRY_NOT_FOUND, None) 

6761 def test_delete_fpolicy_policy_request_error(self, code): 

6762 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

6763 self.mock_object(self.client, '_get_volume_by_args', 

6764 mock.Mock(return_value=volume)) 

6765 self.mock_object(self.client, 'send_request', 

6766 mock.Mock(side_effect=self._mock_api_error(code))) 

6767 if not code: 

6768 self.assertRaises(exception.NetAppException, 

6769 self.client.delete_fpolicy_policy, 

6770 fake.SHARE_NAME, 'fake_policy') 

6771 else: 

6772 self.client.delete_fpolicy_policy(fake.SHARE_NAME, 'fake_policy') 

6773 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count) 

6774 

6775 def test_modify_fpolicy_scope(self): 

6776 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

6777 svm_uuid = volume['svm']['uuid'] 

6778 self.mock_object(self.client, '_get_volume_by_args', 

6779 mock.Mock(return_value=volume)) 

6780 mock_sr = self.mock_object(self.client, 'send_request') 

6781 body = { 

6782 'name': fake.FPOLICY_POLICY_NAME, 

6783 'scope.include_shares': fake.SHARE_NAME, 

6784 'scope.include_extension': 'fake_extension', 

6785 'scope.exclude_extension': 'fake_extension' 

6786 } 

6787 self.client.modify_fpolicy_scope(fake.SHARE_NAME, 

6788 fake.FPOLICY_POLICY_NAME, 

6789 [fake.SHARE_NAME], 

6790 ['fake_extension'], 

6791 ['fake_extension']) 

6792 mock_sr.assert_called_once_with(f'/protocols/fpolicy/{svm_uuid}/' 

6793 'policies/', 'patch', body=body) 

6794 

6795 def test_remove_cifs_share(self): 

6796 response = fake.SVMS_LIST_SIMPLE_RESPONSE_REST 

6797 svm_id = response.get('records')[0]['uuid'] 

6798 mock_sr = self.mock_object(self.client, 'send_request', 

6799 mock.Mock(return_value=response)) 

6800 self.client.remove_cifs_share(fake.SHARE_NAME) 

6801 query = { 

6802 'name': self.client.vserver, 

6803 'fields': 'uuid' 

6804 } 

6805 mock_sr.assert_has_calls([ 

6806 mock.call('/svm/svms', 'get', query=query), 

6807 mock.call(f'/protocols/cifs/shares/{svm_id}' 

6808 f'/{fake.SHARE_NAME}', 'delete')]) 

6809 

6810 def test_qos_policy_group_get_error(self): 

6811 code = netapp_api.EREST_NOT_AUTHORIZED 

6812 self.mock_object(self.client, 'send_request', 

6813 mock.Mock(side_effect=self._mock_api_error(code))) 

6814 self.assertRaises(exception.NetAppException, 

6815 self.client.qos_policy_group_get, 

6816 fake.QOS_POLICY_GROUP_NAME) 

6817 

6818 def test_qos_policy_group_get_not_found(self): 

6819 response = fake.NO_RECORDS_RESPONSE_REST 

6820 self.mock_object(self.client, 'send_request', 

6821 mock.Mock(return_value=response)) 

6822 self.assertRaises(exception.NetAppException, 

6823 self.client.qos_policy_group_get, 

6824 fake.QOS_POLICY_GROUP_NAME) 

6825 

6826 def test_remove_unused_qos_policy_groups_error(self): 

6827 res_list = [fake.QOS_POLICY_GROUP_REST, netapp_api.api.NaApiError] 

6828 self.mock_object(self.client, 'send_request', 

6829 mock.Mock(side_effect=res_list)) 

6830 self.client.remove_unused_qos_policy_groups() 

6831 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count) 

6832 

6833 def test_mount_volume_error(self): 

6834 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

6835 code = netapp_api.EREST_SNAPMIRROR_INITIALIZING 

6836 self.mock_object(self.client, '_get_volume_by_args', 

6837 mock.Mock(return_value=volume)) 

6838 self.mock_object(self.client, 'send_request', 

6839 mock.Mock(side_effect=self._mock_api_error(code))) 

6840 self.assertRaises(netapp_api.api.NaApiError, 

6841 self.client.mount_volume, 

6842 fake.VOLUME_NAMES[0]) 

6843 

6844 def test_get_aggregate_for_volume_empty(self): 

6845 response = fake.NO_RECORDS_RESPONSE_REST 

6846 self.mock_object(self.client, 'send_request', 

6847 mock.Mock(return_value=response)) 

6848 self.assertRaises(exception.NetAppException, 

6849 self.client.get_aggregate_for_volume, 

6850 fake.VOLUME_NAMES[0]) 

6851 

6852 def test_get_nfs_export_policy_for_volume_empty(self): 

6853 response = fake.NO_RECORDS_RESPONSE_REST 

6854 self.mock_object(self.client, 'send_request', 

6855 mock.Mock(return_value=response)) 

6856 self.mock_object(self.client, '_has_records', 

6857 mock.Mock(return_value=False)) 

6858 self.assertRaises(exception.NetAppException, 

6859 self.client.get_nfs_export_policy_for_volume, 

6860 fake.VOLUME_NAMES[0]) 

6861 

6862 def test_get_unique_export_policy_id_empty(self): 

6863 response = fake.NO_RECORDS_RESPONSE_REST 

6864 self.mock_object(self.client, 'send_request', 

6865 mock.Mock(return_value=response)) 

6866 self.mock_object(self.client, '_has_records', 

6867 mock.Mock(return_value=False)) 

6868 self.assertRaises(exception.NetAppException, 

6869 self.client.get_unique_export_policy_id, 

6870 fake.FPOLICY_POLICY_NAME) 

6871 

6872 def test__remove_nfs_export_rules_error(self): 

6873 self.mock_object(self.client, 'get_unique_export_policy_id', 

6874 mock.Mock(return_value=fake.FAKE_UUID)) 

6875 self.mock_object(self.client, 'send_request', 

6876 mock.Mock(side_effect=self._mock_api_error())) 

6877 self.assertRaises(netapp_api.api.NaApiError, 

6878 self.client._remove_nfs_export_rules, 

6879 fake.FPOLICY_POLICY_NAME, 

6880 [1]) 

6881 

6882 def test_get_volume_move_status_error(self): 

6883 response = fake.NO_RECORDS_RESPONSE_REST 

6884 self.mock_object(self.client, 'send_request', 

6885 mock.Mock(return_value=response)) 

6886 self.mock_object(self.client, '_has_records', 

6887 mock.Mock(return_value=False)) 

6888 self.assertRaises(exception.NetAppException, 

6889 self.client.get_volume_move_status, 

6890 fake.VOLUME_NAMES[0], 

6891 fake.VSERVER_NAME) 

6892 

6893 def test__set_snapmirror_state_error(self): 

6894 self.mock_object(self.client, 'get_snapmirrors', 

6895 mock.Mock(return_value=[])) 

6896 self.assertRaises(netapp_utils.NetAppDriverException, 

6897 self.client._set_snapmirror_state, 

6898 'fake_state', 'fake_source_path', 'fake_dest_path', 

6899 'fake_source_vserver', 'fake_source_volume', 

6900 'fake_dest_vserver', 'fake_dest_volume') 

6901 

6902 def test__break_snapmirror_error(self): 

6903 fake_snapmirror = fake.REST_GET_SNAPMIRRORS_RESPONSE 

6904 self.mock_object(self.client, '_get_snapmirrors', 

6905 mock.Mock(return_value=fake_snapmirror)) 

6906 self.mock_object(self.client, 'send_request', 

6907 mock.Mock(side_effect=self._mock_api_error())) 

6908 self.assertRaises(netapp_api.api.NaApiError, 

6909 self.client._break_snapmirror) 

6910 

6911 def test__resync_snapmirror_no_parameter(self): 

6912 mock_snap = self.mock_object(self.client, '_resume_snapmirror') 

6913 self.client._resync_snapmirror() 

6914 mock_snap.assert_called_once_with(None, None, None, None, None, None) 

6915 

6916 def test_add_nfs_export_rule_with_rule_created(self): 

6917 self.mock_object(self.client, '_get_nfs_export_rule_indices', 

6918 mock.Mock(return_value=[1])) 

6919 update = self.mock_object(self.client, '_update_nfs_export_rule') 

6920 remove = self.mock_object(self.client, '_remove_nfs_export_rules') 

6921 self.client.add_nfs_export_rule(fake.FPOLICY_POLICY_NAME, 

6922 'fake_client', 

6923 True, 

6924 'fake_auth') 

6925 update.assert_called_once_with(fake.FPOLICY_POLICY_NAME, 

6926 'fake_client', True, 1, 'fake_auth') 

6927 remove.assert_called_once_with(fake.FPOLICY_POLICY_NAME, []) 

6928 

6929 def test__update_snapmirror_no_snapmirrors(self): 

6930 self.mock_object(self.client, '_get_snapmirrors', 

6931 mock.Mock(return_value=[])) 

6932 self.assertRaises(netapp_utils.NetAppDriverException, 

6933 self.client._update_snapmirror) 

6934 

6935 @ddt.data((netapp_api.EREST_SNAPMIRROR_NOT_INITIALIZED, 

6936 'Another transfer is in progress'), 

6937 (None, 'fake')) 

6938 @ddt.unpack 

6939 def test__update_snapmirror_error(self, code, message): 

6940 snapmirrors = fake.REST_GET_SNAPMIRRORS_RESPONSE 

6941 self.mock_object(self.client, '_get_snapmirrors', 

6942 mock.Mock(return_value=snapmirrors)) 

6943 self.mock_object(self.client, 'send_request', 

6944 mock.Mock(side_effect=self._mock_api_error(code, 

6945 message))) 

6946 self.assertRaises(netapp_api.api.NaApiError, 

6947 self.client._update_snapmirror) 

6948 

6949 @ddt.data(netapp_api.EREST_DUPLICATE_ENTRY, None) 

6950 def test_create_kerberos_realm_error(self, code): 

6951 self.mock_object(self.client, 'send_request', 

6952 mock.Mock(side_effect=self._mock_api_error(code))) 

6953 if code: 

6954 self.client.create_kerberos_realm(fake.KERBEROS_SECURITY_SERVICE) 

6955 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count) 

6956 else: 

6957 self.assertRaises(exception.NetAppException, 

6958 self.client.create_kerberos_realm, 

6959 fake.KERBEROS_SECURITY_SERVICE) 

6960 

6961 def test_configure_kerberos_error(self): 

6962 self.mock_object(self.client, 'configure_dns') 

6963 self.mock_object(self.client, '_get_kerberos_service_principal_name') 

6964 self.mock_object(self.client, 'get_network_interfaces', 

6965 mock.Mock(return_value=[])) 

6966 self.assertRaises(exception.NetAppException, 

6967 self.client.configure_kerberos, 

6968 fake.KERBEROS_SECURITY_SERVICE, 

6969 fake.VSERVER_NAME) 

6970 

6971 def test_configure_ldap(self): 

6972 mock_ldap = self.mock_object(self.client, '_create_ldap_client') 

6973 self.client.configure_ldap(fake.LDAP_AD_SECURITY_SERVICE, 30, 

6974 fake.VSERVER_NAME) 

6975 mock_ldap.assert_called_once_with(fake.LDAP_AD_SECURITY_SERVICE, 

6976 vserver_name=fake.VSERVER_NAME) 

6977 

6978 def test_configure_active_directory_error(self): 

6979 self.mock_object(self.client, 'configure_dns') 

6980 self.mock_object(self.client, 'configure_cifs_aes_encryption') 

6981 self.mock_object(self.client, 'set_preferred_dc') 

6982 self.mock_object(self.client, '_get_cifs_server_name') 

6983 self.mock_object(self.client, 'send_request', 

6984 mock.Mock(side_effect=self._mock_api_error())) 

6985 self.assertRaises(exception.NetAppException, 

6986 self.client.configure_active_directory, 

6987 fake.LDAP_AD_SECURITY_SERVICE, 

6988 fake.VSERVER_NAME, 

6989 False) 

6990 

6991 def test__get_unique_svm_by_name_error(self): 

6992 response = fake.NO_RECORDS_RESPONSE_REST 

6993 self.mock_object(self.client, 'send_request', 

6994 mock.Mock(return_value=response)) 

6995 self.assertRaises(exception.NetAppException, 

6996 self.client._get_unique_svm_by_name, 

6997 fake.VSERVER_NAME) 

6998 

6999 def test_get_ontap_version_scoped(self): 

7000 self.client.get_ontap_version = self.original_get_ontap_version 

7001 e = netapp_api.api.NaApiError(code=netapp_api.EREST_NOT_AUTHORIZED) 

7002 res_list = [e, fake.GET_VERSION_RESPONSE_REST] 

7003 version = fake.GET_VERSION_RESPONSE_REST['records'][0]['version'] 

7004 expected = { 

7005 'version': version['full'], 

7006 'version-tuple': (9, 11, 1) 

7007 } 

7008 self.mock_object(self.client, 'send_request', 

7009 mock.Mock(side_effect=res_list)) 

7010 result = self.client.get_ontap_version(self=self.client, cached=False) 

7011 self.assertEqual(expected, result) 

7012 

7013 def test_get_licenses_error(self): 

7014 self.mock_object(self.client, 'send_request', 

7015 mock.Mock(side_effect=self._mock_api_error())) 

7016 self.assertRaises(netapp_api.api.NaApiError, 

7017 self.client.get_licenses) 

7018 

7019 def test__get_volume_by_args_error(self): 

7020 res = fake.VOLUME_GET_ITER_RESPONSE_REST_PAGE 

7021 self.mock_object(self.client, 'send_request', 

7022 mock.Mock(return_value=res)) 

7023 self.assertRaises(exception.NetAppException, 

7024 self.client._get_volume_by_args, 

7025 is_root=True) 

7026 

7027 def test_get_aggregate_no_name(self): 

7028 expected = {} 

7029 result = self.client.get_aggregate('') 

7030 self.assertEqual(expected, result) 

7031 

7032 def test_get_aggregate_error(self): 

7033 self.mock_object(self.client, '_get_aggregates', 

7034 mock.Mock(side_effect=self._mock_api_error())) 

7035 result = self.client.get_aggregate(fake.SHARE_AGGREGATE_NAME) 

7036 expected = {} 

7037 self.assertEqual(expected, result) 

7038 

7039 def test_get_node_for_aggregate_no_name(self): 

7040 result = self.client.get_node_for_aggregate('') 

7041 self.assertIsNone(result) 

7042 

7043 @ddt.data(netapp_api.EREST_NOT_AUTHORIZED, None) 

7044 def test_get_node_for_aggregate_error(self, code): 

7045 self.mock_object(self.client, '_get_aggregates', 

7046 mock.Mock(side_effect=self._mock_api_error(code))) 

7047 if code: 

7048 r = self.client.get_node_for_aggregate(fake.SHARE_AGGREGATE_NAME) 

7049 self.assertIsNone(r) 

7050 else: 

7051 self.assertRaises(netapp_api.api.NaApiError, 

7052 self.client.get_node_for_aggregate, 

7053 fake.SHARE_AGGREGATE_NAME) 

7054 

7055 def test_get_vserver_aggregate_capabilities_no_response(self): 

7056 response = fake.NO_RECORDS_RESPONSE_REST 

7057 self.mock_object(self.client, 'send_request', 

7058 mock.Mock(return_value=response)) 

7059 self.assertRaises(exception.NetAppException, 

7060 self.client.get_vserver_aggregate_capacities, 

7061 fake.SHARE_AGGREGATE_NAME) 

7062 

7063 def test_get_vserver_aggregate_capacities_no_aggregate(self): 

7064 response = fake.FAKE_AGGREGATES_RESPONSE 

7065 share_name = fake.SHARE_AGGREGATE_NAME 

7066 self.mock_object(self.client, 

7067 'send_request', 

7068 mock.Mock(return_value=response)) 

7069 res = self.client.get_vserver_aggregate_capacities(share_name) 

7070 expected = {} 

7071 self.assertEqual(expected, res) 

7072 

7073 def test_rename_nfs_export_policy_error(self): 

7074 self.mock_object(self.client, 'send_request') 

7075 self.mock_object(self.client, '_has_records', 

7076 mock.Mock(return_value=False)) 

7077 self.assertRaises(exception.NetAppException, 

7078 self.client.rename_nfs_export_policy, 

7079 'fake_policy_name', 

7080 'fake_new_policy_name') 

7081 

7082 @ddt.data((False, exception.StorageResourceNotFound), 

7083 (True, exception.NetAppException)) 

7084 @ddt.unpack 

7085 def test_get_volume_error(self, records, exception): 

7086 res = copy.deepcopy(fake.FAKE_VOLUME_MANAGE) 

7087 res['num_records'] = 2 

7088 self.mock_object(self.client, 'send_request', 

7089 mock.Mock(return_value=res)) 

7090 self.mock_object(self.client, '_has_records', 

7091 mock.Mock(return_value=records)) 

7092 self.assertRaises(exception, 

7093 self.client.get_volume, 

7094 fake.VOLUME_NAMES[0]) 

7095 

7096 def test_get_volume_no_aggregate(self): 

7097 res = copy.deepcopy(fake.FAKE_VOLUME_MANAGE) 

7098 res.get('records')[0]['aggregates'] = [] 

7099 self.mock_object(self.client, 'send_request', 

7100 mock.Mock(return_value=res)) 

7101 fake_volume = res.get('records', [])[0] 

7102 

7103 expected = { 

7104 'aggregate': '', 

7105 'aggr-list': [], 

7106 'junction-path': fake_volume.get('nas', {}).get('path', ''), 

7107 'name': fake_volume.get('name', ''), 

7108 'owning-vserver-name': fake_volume.get('svm', {}).get('name', ''), 

7109 'type': fake_volume.get('type', ''), 

7110 'style': fake_volume.get('style', ''), 

7111 'size': fake_volume.get('space', {}).get('size', ''), 

7112 'size-used': fake_volume.get('space', {}).get('used', ''), 

7113 'qos-policy-group-name': fake_volume.get('qos', {}) 

7114 .get('policy', {}) 

7115 .get('name', ''), 

7116 'style-extended': fake_volume.get('style', ''), 

7117 'snaplock-type': fake_volume.get('snaplock', {}).get('type', '') 

7118 } 

7119 result = self.client.get_volume(fake.VOLUME_NAMES[0]) 

7120 self.assertEqual(expected, result) 

7121 

7122 def test_get_job_state_error(self): 

7123 response = { 

7124 'records': [fake.JOB_SUCCESSFUL_REST, 

7125 fake.JOB_SUCCESSFUL_REST] 

7126 } 

7127 self.mock_object(self.client, 'send_request', 

7128 mock.Mock(return_value=response)) 

7129 self.mock_object(self.client, '_has_records', 

7130 mock.Mock(return_value=True)) 

7131 self.assertRaises(exception.NetAppException, 

7132 self.client.get_job_state, 

7133 fake.JOB_ID) 

7134 

7135 def test_get_volume_efficiency_status_error(self): 

7136 self.mock_object(self.client, 'send_request', 

7137 mock.Mock(side_effect=self._mock_api_error())) 

7138 self.client.get_volume_efficiency_status(fake.VOLUME_NAMES[0]) 

7139 self.assertEqual(1, client_cmode_rest.LOG.error.call_count) 

7140 

7141 def test_get_fpolicy_scopes_not_found(self): 

7142 self.mock_object(self.client, '_get_volume_by_args', 

7143 mock.Mock(side_effect=exception.NetAppException)) 

7144 result = self.client.get_fpolicy_scopes(fake.SHARE_NAME) 

7145 expected = [] 

7146 self.assertEqual(expected, result) 

7147 

7148 def test_delete_fpolicy_policy_error(self): 

7149 self.mock_object(self.client, '_get_volume_by_args', 

7150 mock.Mock(side_effect=exception.NetAppException)) 

7151 self.mock_object(self.client, 'send_request') 

7152 res = self.client.delete_fpolicy_policy(fake.SHARE_NAME, 

7153 fake.FPOLICY_POLICY_NAME) 

7154 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count) 

7155 self.assertIsNone(res) 

7156 

7157 def test_delete_fpolicy_event_error(self): 

7158 self.mock_object(self.client, '_get_volume_by_args', 

7159 mock.Mock(side_effect=exception.NetAppException)) 

7160 self.mock_object(self.client, 'send_request') 

7161 res = self.client.delete_fpolicy_event(fake.SHARE_NAME, 

7162 fake.FPOLICY_EVENT_NAME) 

7163 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count) 

7164 self.assertIsNone(res) 

7165 

7166 def test_delete_nfs_export_policy_no_records(self): 

7167 response = fake.NO_RECORDS_RESPONSE_REST 

7168 self.mock_object(self.client, 'send_request', 

7169 mock.Mock(return_value=response)) 

7170 res = self.client.delete_nfs_export_policy(fake.FPOLICY_POLICY_NAME) 

7171 self.assertIsNone(res) 

7172 

7173 def test_remove_cifs_share_not_found(self): 

7174 response = fake.NO_RECORDS_RESPONSE_REST 

7175 self.mock_object(self.client, 'send_request', 

7176 mock.Mock(return_value=response)) 

7177 self.assertRaises(exception.NetAppException, 

7178 self.client.remove_cifs_share, 

7179 fake.SHARE_NAME) 

7180 

7181 @ddt.data(netapp_api.EREST_ENTRY_NOT_FOUND, None) 

7182 def test_remove_cifs_share_error(self, code): 

7183 responses = [fake.SVMS_LIST_SIMPLE_RESPONSE_REST, 

7184 netapp_api.api.NaApiError(code=code)] 

7185 self.mock_object(self.client, 'send_request', 

7186 mock.Mock(side_effect=responses)) 

7187 if not code: 

7188 self.assertRaises(netapp_api.api.NaApiError, 

7189 self.client.remove_cifs_share, 

7190 fake.SHARE_NAME) 

7191 else: 

7192 result = self.client.remove_cifs_share(fake.SHARE_NAME) 

7193 self.assertIsNone(result) 

7194 

7195 def test_qos_policy_group_does_not_exists(self): 

7196 self.mock_object(self.client, 'qos_policy_group_get', 

7197 mock.Mock(side_effect=exception.NetAppException)) 

7198 result = self.client.qos_policy_group_exists(fake.QOS_POLICY_GROUP) 

7199 self.assertFalse(result) 

7200 

7201 def test_qos_policy_group_rename_error(self): 

7202 response = fake.NO_RECORDS_RESPONSE_REST 

7203 self.mock_object(self.client, 'send_request', 

7204 mock.Mock(return_value=response)) 

7205 self.assertRaises(exception.NetAppException, 

7206 self.client.qos_policy_group_rename, 

7207 fake.QOS_POLICY_GROUP_NAME, 

7208 'fake_new_qos_policy_group_name') 

7209 

7210 def test_qos_policy_group_rename_same_name(self): 

7211 res = self.client.qos_policy_group_rename(fake.QOS_POLICY_GROUP_NAME, 

7212 fake.QOS_POLICY_GROUP_NAME) 

7213 self.assertIsNone(res) 

7214 

7215 def test_qos_policy_group_modify_error(self): 

7216 response = fake.NO_RECORDS_RESPONSE_REST 

7217 self.mock_object(self.client, 'send_request', 

7218 mock.Mock(return_value=response)) 

7219 self.assertRaises(exception.NetAppException, 

7220 self.client.qos_policy_group_modify, 

7221 fake.QOS_POLICY_GROUP_NAME, 

7222 fake.QOS_MAX_THROUGHPUT) 

7223 

7224 def test_update_kerberos_realm_error(self): 

7225 self.mock_object(self.client, 

7226 '_get_unique_svm_by_name', 

7227 mock.Mock(return_value=fake.FAKE_UUID)) 

7228 self.mock_object(self.client, 'send_request', 

7229 mock.Mock(side_effect=self._mock_api_error())) 

7230 self.assertRaises(exception.NetAppException, 

7231 self.client.update_kerberos_realm, 

7232 fake.KERBEROS_SECURITY_SERVICE) 

7233 

7234 @ddt.data(('fake_domain', 'fake_server'), (None, None)) 

7235 @ddt.unpack 

7236 def test_modify_ldap_error(self, domain, server): 

7237 security_service = { 

7238 'domain': domain, 

7239 'server': server, 

7240 'user': 'fake_user', 

7241 'ou': 'fake_ou', 

7242 'dns_ip': 'fake_ip', 

7243 'password': 'fake_password' 

7244 } 

7245 self.mock_object(self.client, '_get_unique_svm_by_name', 

7246 mock.Mock(return_value=fake.FAKE_UUID)) 

7247 self.mock_object(self.client, 'send_request') 

7248 self.assertRaises(exception.NetAppException, 

7249 self.client.modify_ldap, 

7250 security_service, 

7251 fake.LDAP_AD_SECURITY_SERVICE) 

7252 

7253 def test_update_dns_configuration_error(self): 

7254 self.mock_object(self.client, '_get_unique_svm_by_name', 

7255 mock.Mock(return_value=fake.FAKE_UUID)) 

7256 dns_config = { 

7257 'domains': [fake.KERBEROS_SECURITY_SERVICE['domain']], 

7258 'dns-ips': [fake.KERBEROS_SECURITY_SERVICE['dns_ip']], 

7259 } 

7260 self.mock_object(self.client, 'get_dns_config', 

7261 mock.Mock(return_value=dns_config)) 

7262 self.mock_object(self.client, 'send_request', 

7263 mock.Mock(side_effect=self._mock_api_error())) 

7264 self.assertRaises(exception.NetAppException, 

7265 self.client.update_dns_configuration, 

7266 ['fake_ips'], ['fake_domain']) 

7267 

7268 def test_remove_preferred_dcs_error(self): 

7269 fake_response = [fake.PREFERRED_DC_REST, 

7270 netapp_api.api.NaApiError] 

7271 self.mock_object(self.client, 'send_request', 

7272 mock.Mock(side_effect=fake_response)) 

7273 self.assertRaises(exception.NetAppException, 

7274 self.client.remove_preferred_dcs, 

7275 fake.LDAP_AD_SECURITY_SERVICE, 

7276 fake.FAKE_UUID) 

7277 

7278 def test_set_preferred_dc_error(self): 

7279 security = copy.deepcopy(fake.LDAP_AD_SECURITY_SERVICE) 

7280 security['server'] = 'fake_server' 

7281 self.mock_object(self.client, '_get_unique_svm_by_name', 

7282 mock.Mock(return_value=fake.FAKE_UUID)) 

7283 self.mock_object(self.client, 'send_request', 

7284 mock.Mock(side_effect=self._mock_api_error())) 

7285 self.assertRaises(exception.NetAppException, 

7286 self.client.set_preferred_dc, 

7287 security, 

7288 fake.VSERVER_NAME) 

7289 

7290 def test_set_preferred_dc_no_server(self): 

7291 result = self.client.set_preferred_dc(fake.LDAP_AD_SECURITY_SERVICE, 

7292 fake.VSERVER_NAME) 

7293 self.assertIsNone(result) 

7294 

7295 def test__get_svm_peer_uuid_error(self): 

7296 response = fake.NO_RECORDS_RESPONSE_REST 

7297 self.mock_object(self.client, 'send_request', 

7298 mock.Mock(return_value=response)) 

7299 self.assertRaises(exception.NetAppException, 

7300 self.client._get_svm_peer_uuid, 

7301 fake.VSERVER_NAME, 

7302 fake.VSERVER_PEER_NAME) 

7303 

7304 def test_create_vserver_dp_destination(self): 

7305 mock_vserver = self.mock_object(self.client, '_create_vserver') 

7306 self.client.create_vserver_dp_destination(fake.VSERVER_NAME, 

7307 fake.FAKE_AGGR_LIST, 

7308 fake.IPSPACE_NAME, 

7309 fake.DELETE_RETENTION_HOURS) 

7310 mock_vserver.assert_called_once_with(fake.VSERVER_NAME, 

7311 fake.FAKE_AGGR_LIST, 

7312 fake.IPSPACE_NAME, 

7313 fake.DELETE_RETENTION_HOURS, 

7314 subtype='dp_destination') 

7315 

7316 @ddt.data(':', '.') 

7317 def test_create_route_no_destination(self, gateway): 

7318 mock_sr = self.mock_object(self.client, 'send_request') 

7319 body = { 

7320 'gateway': gateway, 

7321 'destination.address': ('::' if netutils.is_valid_ipv6(gateway) 

7322 else '0.0.0.0'), 

7323 'destination.netmask': '0' 

7324 } 

7325 self.client.create_route(gateway) 

7326 mock_sr.assert_called_once_with('/network/ip/routes', 'post', 

7327 body=body) 

7328 

7329 def test_list_root_aggregates(self): 

7330 return_value = fake.FAKE_ROOT_AGGREGATES_RESPONSE 

7331 self.mock_object(self.client, 'send_request', 

7332 mock.Mock(return_value=return_value)) 

7333 

7334 result = self.client.list_root_aggregates() 

7335 

7336 expected = [fake.SHARE_AGGREGATE_NAME] 

7337 self.assertEqual(expected, result) 

7338 

7339 @ddt.data(("fake_server", "fake_domain"), (None, None)) 

7340 @ddt.unpack 

7341 def test__create_ldap_client_error(self, server, domain): 

7342 security_service = { 

7343 'server': server, 

7344 'domain': domain, 

7345 'user': 'fake_user', 

7346 'ou': 'fake_ou', 

7347 'dns_ip': 'fake_ip', 

7348 'password': 'fake_password' 

7349 } 

7350 

7351 self.assertRaises(exception.NetAppException, 

7352 self.client._create_ldap_client, 

7353 security_service) 

7354 

7355 @ddt.data(["password"], ["user"]) 

7356 def test__modify_active_directory_security_service_error(self, keys): 

7357 svm_uuid = fake.FAKE_UUID 

7358 user_records = fake.FAKE_CIFS_LOCAL_USER.get('records')[0] 

7359 self.mock_object(self.client, '_get_unique_svm_by_name', 

7360 mock.Mock(return_value=svm_uuid)) 

7361 self.mock_object(self.client, 'send_request', 

7362 mock.Mock(side_effect=[user_records, 

7363 netapp_api.api.NaApiError])) 

7364 self.mock_object(self.client, 'remove_preferred_dcs') 

7365 self.mock_object(self.client, 'set_preferred_dc') 

7366 new_security_service = { 

7367 'user': 'new_user', 

7368 'password': 'new_password', 

7369 'server': 'fake_server' 

7370 } 

7371 

7372 current_security_service = { 

7373 'server': 'fake_current_server' 

7374 } 

7375 

7376 self.assertRaises( 

7377 exception.NetAppException, 

7378 self.client.modify_active_directory_security_service, 

7379 fake.VSERVER_NAME, 

7380 keys, 

7381 new_security_service, 

7382 current_security_service) 

7383 

7384 def test_disable_kerberos_error(self): 

7385 fake_api_response = fake.NFS_LIFS_REST 

7386 api_error = self._mock_api_error() 

7387 self.mock_object(self.client, 'get_network_interfaces', 

7388 mock.Mock(return_value=fake_api_response)) 

7389 self.mock_object( 

7390 self.client, 'send_request', 

7391 mock.Mock(side_effect=api_error)) 

7392 

7393 self.assertRaises(exception.NetAppException, 

7394 self.client.disable_kerberos, 

7395 fake.LDAP_AD_SECURITY_SERVICE) 

7396 

7397 def test_set_volume_snapdir_access_exception(self): 

7398 fake_hide_snapdir = 'fake-snapdir' 

7399 

7400 self.mock_object(self.client, '_get_volume_by_args', 

7401 mock.Mock(side_effect=exception.NetAppException)) 

7402 self.assertRaises(exception.SnapshotResourceNotFound, 

7403 self.client.set_volume_snapdir_access, 

7404 fake.VOLUME_NAMES[0], 

7405 fake_hide_snapdir) 

7406 

7407 def test__get_broadcast_domain_for_port_exception(self): 

7408 fake_response_empty = { 

7409 "records": [{}] 

7410 } 

7411 self.mock_object(self.client, 'send_request', mock.Mock( 

7412 return_value=fake_response_empty)) 

7413 

7414 self.assertRaises(exception.NetAppException, 

7415 self.client._get_broadcast_domain_for_port, 

7416 fake.NODE_NAME, 

7417 fake.PORT) 

7418 

7419 def test__configure_nfs_exception(self): 

7420 fake_nfs = { 

7421 'udp-max-xfer-size': 10000, 

7422 'tcp-max-xfer-size': 10000, 

7423 } 

7424 self.assertRaises(exception.NetAppException, 

7425 self.client._configure_nfs, 

7426 fake_nfs, 

7427 fake.FAKE_UUID) 

7428 

7429 def test_get_snapshot_exception(self): 

7430 self.mock_object(self.client, '_get_volume_by_args', 

7431 mock.Mock(side_effect=exception.NetAppException)) 

7432 self.assertRaises(exception.SnapshotResourceNotFound, 

7433 self.client.get_snapshot, 

7434 fake.VOLUME_NAMES[0], 

7435 fake.SNAPSHOT_NAME) 

7436 

7437 def test_delete_snapshot_exception(self): 

7438 self.mock_object(self.client, 

7439 '_get_volume_by_args', 

7440 mock.Mock(side_effect=exception.NetAppException)) 

7441 self.client.delete_snapshot(fake.VOLUME_NAMES[0], fake.SNAPSHOT_NAME, 

7442 True) 

7443 

7444 self.assertEqual(1, client_cmode_rest.LOG.warning.call_count) 

7445 

7446 def test_set_nfs_export_policy_for_volume_exception(self): 

7447 return_code = netapp_api.EREST_CANNOT_MODITY_OFFLINE_VOLUME 

7448 self.mock_object(self.client, 

7449 'send_request', 

7450 mock.Mock(side_effect=self._mock_api_error( 

7451 code=return_code))) 

7452 self.client.set_nfs_export_policy_for_volume( 

7453 fake.VOLUME_NAMES[0], fake.EXPORT_POLICY_NAME) 

7454 

7455 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count) 

7456 

7457 def test__break_snapmirror_exception(self): 

7458 fake_snapmirror = copy.deepcopy(fake.REST_GET_SNAPMIRRORS_RESPONSE) 

7459 fake_snapmirror[0]['transferring-state'] = 'error' 

7460 

7461 self.mock_object( 

7462 self.client, '_get_snapmirrors', 

7463 mock.Mock(return_value=fake_snapmirror)) 

7464 

7465 self.assertRaises(netapp_utils.NetAppDriverException, 

7466 self.client._break_snapmirror) 

7467 

7468 def test_get_svm_volumes_total_size(self): 

7469 expected = 1 

7470 

7471 fake_query = { 

7472 'svm.name': fake.VSERVER_NAME, 

7473 'fields': 'size' 

7474 } 

7475 

7476 self.mock_object(self.client, 'send_request', 

7477 mock.Mock(return_value=fake.FAKE_GET_VOLUME)) 

7478 

7479 result = self.client.get_svm_volumes_total_size(fake.VSERVER_NAME) 

7480 

7481 self.client.send_request.assert_called_once_with( 

7482 '/storage/volumes/', 'get', query=fake_query) 

7483 

7484 self.assertEqual(expected, result) 

7485 

7486 @ddt.data(fake.CIFS_SECURITY_SERVICE, fake.CIFS_SECURITY_SERVICE_3) 

7487 def test_configure_active_directory_credential_error(self, 

7488 security_service): 

7489 msg = "could not authenticate" 

7490 fake_security = copy.deepcopy(security_service) 

7491 

7492 self.mock_object(self.client, 'configure_dns') 

7493 self.mock_object(self.client, 'set_preferred_dc') 

7494 self.mock_object(self.client, 'configure_cifs_aes_encryption') 

7495 self.mock_object(self.client, '_get_cifs_server_name') 

7496 self.mock_object(self.client, 'send_request', 

7497 self._mock_api_error(code=netapp_api.api.EAPIERROR, 

7498 message=msg)) 

7499 self.assertRaises(exception.SecurityServiceFailedAuth, 

7500 self.client.configure_active_directory, 

7501 fake_security, 

7502 fake.VSERVER_NAME, 

7503 False) 

7504 

7505 @ddt.data(fake.CIFS_SECURITY_SERVICE, fake.CIFS_SECURITY_SERVICE_3) 

7506 def test_configure_active_directory_user_privilege_error(self, 

7507 security_service): 

7508 msg = "insufficient access" 

7509 fake_security = copy.deepcopy(security_service) 

7510 

7511 self.mock_object(self.client, 'configure_dns') 

7512 self.mock_object(self.client, 'set_preferred_dc') 

7513 self.mock_object(self.client, 'configure_cifs_aes_encryption') 

7514 self.mock_object(self.client, '_get_cifs_server_name') 

7515 self.mock_object(self.client, 'send_request', 

7516 self._mock_api_error(code=netapp_api.api.EAPIERROR, 

7517 message=msg)) 

7518 self.assertRaises(exception.SecurityServiceFailedAuth, 

7519 self.client.configure_active_directory, 

7520 fake_security, 

7521 fake.VSERVER_NAME, 

7522 False) 

7523 

7524 def test_snapmirror_restore_vol(self): 

7525 uuid = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST["uuid"] 

7526 body = { 

7527 "destination": {"path": fake.SM_DEST_PATH, 

7528 "cluster": {"name": fake.CLUSTER_NAME}}, 

7529 "source_snapshot": fake.SNAPSHOT_NAME 

7530 } 

7531 snapmirror_info = [{'destination-vserver': "fake_des_vserver", 

7532 'destination-volume': "fake_des_vol", 

7533 'relationship-status': "idle", 

7534 'uuid': uuid}] 

7535 

7536 self.mock_object(self.client, 'get_snapmirrors', 

7537 mock.Mock(return_value=snapmirror_info)) 

7538 self.mock_object(self.client, 'send_request') 

7539 self.client.snapmirror_restore_vol(source_path=fake.SM_SOURCE_PATH, 

7540 dest_path=fake.SM_DEST_PATH, 

7541 source_snapshot=fake.SNAPSHOT_NAME, 

7542 des_cluster=fake.CLUSTER_NAME) 

7543 self.client.send_request.assert_called_once_with( 

7544 f'/snapmirror/relationships/{uuid}/restore', 'post', body=body) 

7545 

7546 @ddt.data({'snapmirror_label': None, 'newer_than': '2345'}, 

7547 {'snapmirror_label': "fake_backup", 'newer_than': None}) 

7548 @ddt.unpack 

7549 def test_list_volume_snapshots(self, snapmirror_label, newer_than): 

7550 fake_response = fake.SNAPSHOTS_REST_RESPONSE 

7551 api_response = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST 

7552 self.mock_object(self.client, 

7553 '_get_volume_by_args', 

7554 mock.Mock(return_value=api_response)) 

7555 mock_request = self.mock_object(self.client, 'send_request', 

7556 mock.Mock(return_value=fake_response)) 

7557 self.client.list_volume_snapshots(fake.SHARE_NAME, 

7558 snapmirror_label=snapmirror_label, 

7559 newer_than=newer_than) 

7560 uuid = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST["uuid"] 

7561 query = {} 

7562 if snapmirror_label: 

7563 query = { 

7564 'snapmirror_label': snapmirror_label, 

7565 } 

7566 if newer_than: 

7567 query['create_time'] = '>' + newer_than 

7568 

7569 mock_request.assert_called_once_with( 

7570 f'/storage/volumes/{uuid}/snapshots/', 

7571 'get', query=query) 

7572 

7573 @ddt.data(('vault', False, True), (None, False, False)) 

7574 @ddt.unpack 

7575 def test_create_snapmirror_policy_rest(self, policy_type, 

7576 discard_network_info, 

7577 preserve_snapshots): 

7578 fake_response = fake.SNAPSHOTS_REST_RESPONSE 

7579 self.mock_object(self.client, 'send_request', 

7580 mock.Mock(return_value=fake_response)) 

7581 policy_name = fake.SNAPMIRROR_POLICY_NAME 

7582 self.client.create_snapmirror_policy( 

7583 policy_name, policy_type=policy_type, 

7584 discard_network_info=discard_network_info, 

7585 preserve_snapshots=preserve_snapshots, 

7586 snapmirror_label='backup', 

7587 keep=30) 

7588 if policy_type == "vault": 

7589 body = {"name": policy_name, "type": "async", 

7590 "create_snapshot_on_source": False} 

7591 else: 

7592 body = {"name": policy_name, "type": policy_type} 

7593 if discard_network_info: 7593 ↛ 7594line 7593 didn't jump to line 7594 because the condition on line 7593 was never true

7594 body["exclude_network_config"] = {'svmdr-config-obj': 'network'} 

7595 if preserve_snapshots: 

7596 body["retention"] = [{"label": 'backup', "count": 30}] 

7597 self.client.send_request.assert_called_once_with( 

7598 '/snapmirror/policies/', 'post', body=body) 

7599 

7600 def test_is_snaplock_compliance_clock_configured(self): 

7601 self.mock_object(self.client, 

7602 '_get_cluster_node_uuid', 

7603 mock.Mock(return_value="uuid")) 

7604 api_response = {'time': 'Thu Aug 08 00:51:30 EDT 2024 -04:00'} 

7605 self.mock_object(self.client, 

7606 'send_request', 

7607 mock.Mock(return_value=api_response)) 

7608 result = self.client.is_snaplock_compliance_clock_configured( 

7609 "test_node" 

7610 ) 

7611 self.assertIs(True, result) 

7612 

7613 def test_is_snaplock_compliance_clock_configured_negative(self): 

7614 self.mock_object(self.client, 

7615 '_get_cluster_node_uuid', 

7616 mock.Mock(return_value="uuid")) 

7617 api_response = {'time': None} 

7618 self.mock_object(self.client, 

7619 'send_request', 

7620 mock.Mock(return_value=api_response)) 

7621 result = self.client.is_snaplock_compliance_clock_configured( 

7622 "test_node" 

7623 ) 

7624 self.assertIs(False, result) 

7625 

7626 @ddt.data({'options': {'snaplock_autocommit_period': "4hours", 

7627 'snaplock_min_retention_period': "6days", 

7628 'snaplock_max_retention_period': "8months", 

7629 'snaplock_default_retention_period': "8days"}, 

7630 }, 

7631 {'options': {'snaplock_autocommit_period': "4hours", 

7632 'snaplock_min_retention_period': "6days", 

7633 'snaplock_max_retention_period': "8months", 

7634 'snaplock_default_retention_period': "min"}, 

7635 }, 

7636 {'options': {'snaplock_autocommit_period': "4hours", 

7637 'snaplock_min_retention_period': "6days", 

7638 'snaplock_max_retention_period': "8months", 

7639 'snaplock_default_retention_period': "max"}, 

7640 }, 

7641 ) 

7642 @ddt.unpack 

7643 def test_set_snaplock_attributes(self, options): 

7644 self.mock_object(self.client, 'send_request') 

7645 

7646 body = { 

7647 'snaplock.autocommit_period': 

7648 utils.convert_time_duration_to_iso_format( 

7649 options.get('snaplock_autocommit_period')), 

7650 'snaplock.retention.minimum': 

7651 utils.convert_time_duration_to_iso_format( 

7652 options.get('snaplock_min_retention_period')), 

7653 'snaplock.retention.maximum': 

7654 utils.convert_time_duration_to_iso_format( 

7655 options.get('snaplock_max_retention_period')), 

7656 } 

7657 if options.get('snaplock_default_retention_period') == "min": 

7658 body['snaplock.retention.default'] = ( 

7659 utils.convert_time_duration_to_iso_format( 

7660 options.get('snaplock_min_retention_period')) 

7661 ) 

7662 elif options.get('snaplock_default_retention_period') == 'max': 

7663 body['snaplock.retention.default'] = ( 

7664 utils.convert_time_duration_to_iso_format( 

7665 options.get('snaplock_max_retention_period')) 

7666 ) 

7667 else: 

7668 body['snaplock.retention.default'] = ( 

7669 utils.convert_time_duration_to_iso_format( 

7670 options.get('snaplock_default_retention_period')) 

7671 ) 

7672 

7673 self.mock_object(self.client, 

7674 '_get_volume_by_args', 

7675 mock.Mock(return_value={'uuid': fake.FAKE_UUID})) 

7676 self.client.set_snaplock_attributes(fake.SHARE_NAME, **options) 

7677 

7678 vol_uid = fake.FAKE_UUID 

7679 self.client.send_request.assert_called_once_with( 

7680 f'/storage/volumes/{vol_uid}', 'patch', body=body) 

7681 

7682 def test_set_snaplock_attributes_none(self): 

7683 self.mock_object(self.client, 'send_request') 

7684 self.mock_object(self.client, 

7685 '_get_volume_by_args', 

7686 mock.Mock(return_value={'uuid': fake.FAKE_UUID})) 

7687 options = {'snaplock_autocommit_period': None, 

7688 'snaplock_min_retention_period': None, 

7689 'snaplock_max_retention_period': None, 

7690 'snaplock_default_retention_period': None, 

7691 } 

7692 self.client.set_snaplock_attributes(fake.SHARE_NAME, **options) 

7693 self.client.send_request.assert_not_called() 

7694 

7695 def test__get_cluster_node_uuid(self): 

7696 response = {'records': [{'uuid': fake.FAKE_UUID}]} 

7697 self.mock_object(self.client, 

7698 'send_request', 

7699 mock.Mock(return_value=response)) 

7700 

7701 result = self.client._get_cluster_node_uuid("fake_node") 

7702 self.assertEqual(result, fake.FAKE_UUID) 

7703 

7704 @ddt.data("compliance", "enterprise") 

7705 def test__is_snaplock_enabled_volume_true(self, snaplock_type): 

7706 vol_attr = {'snaplock-type': snaplock_type} 

7707 self.mock_object(self.client, 

7708 'get_volume', 

7709 mock.Mock(return_value=vol_attr)) 

7710 result = self.client._is_snaplock_enabled_volume( 

7711 fake.SHARE_AGGREGATE_NAMES 

7712 ) 

7713 self.assertIs(True, result) 

7714 

7715 def test__is_snaplock_enabled_volume_false(self): 

7716 vol_attr = {'snaplock-type': "non-snaplock"} 

7717 self.mock_object(self.client, 

7718 'get_volume', 

7719 mock.Mock(return_value=vol_attr)) 

7720 result = self.client._is_snaplock_enabled_volume( 

7721 fake.SHARE_AGGREGATE_NAMES 

7722 ) 

7723 self.assertIs(False, result) 

7724 

7725 def test_get_storage_failover_partner(self): 

7726 self.mock_object(self.client, 

7727 '_get_cluster_node_uuid', 

7728 mock.Mock(return_value=fake.FAKE_UUID)) 

7729 response = {'ha': {'partners': [{'name': 'partner_node'}]}} 

7730 self.mock_object(self.client, 

7731 'send_request', 

7732 mock.Mock(return_value=response)) 

7733 result = self.client.get_storage_failover_partner("fake_node") 

7734 self.assertEqual(result, "partner_node") 

7735 

7736 def test_get_migratable_data_lif_for_node(self): 

7737 api_response = fake.GENERIC_NETWORK_INTERFACES_GET_REPONSE 

7738 expected_result = [fake.LIF_NAME] 

7739 

7740 self.mock_object(self.client, '_has_records', 

7741 mock.Mock(return_value=True)) 

7742 self.mock_object( 

7743 self.client, 

7744 'send_request', 

7745 mock.Mock(side_effect=self._send_request_side_effect) 

7746 ) 

7747 uuid = api_response['records'][0]['uuid'] 

7748 result = self.client.get_migratable_data_lif_for_node("fake_node") 

7749 self.client.send_request.assert_any_call( 

7750 '/network/ip/interfaces', 'get', 

7751 query={ 

7752 'services': 'data_nfs|data_cifs', 

7753 'location.home_node.name': 'fake_node', 

7754 'fields': 'name', 

7755 } 

7756 ) 

7757 self.client.send_request.assert_any_call( 

7758 f'/network/ip/interfaces/{uuid}', 'get' 

7759 ) 

7760 self.assertEqual(expected_result, result) 

7761 

7762 def _send_request_side_effect(self, endpoint, method, query=None): 

7763 if (endpoint == '/network/ip/interfaces' and method == 'get' 

7764 and query is not None): 

7765 return {"records": [{"uuid": "fake_uuid", "name": fake.LIF_NAME}]} 

7766 elif (endpoint.startswith('/network/ip/interfaces/') 7766 ↛ 7769line 7766 didn't jump to line 7769 because the condition on line 7766 was always true

7767 and method == 'get'): 

7768 return {'location': {'failover': 'sfo_partners_only'}} 

7769 return {}