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

3465 statements  

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

1# Copyright (c) 2014 Alex Meade. All rights reserved. 

2# Copyright (c) 2015 Clinton Knight. All rights reserved. 

3# Copyright (c) 2015 Tom Barron. All rights reserved. 

4# 

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

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

7# a copy of the License at 

8# 

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

10# 

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

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

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

14# License for the specific language governing permissions and limitations 

15# under the License. 

16 

17import copy 

18import hashlib 

19import time 

20from unittest import mock 

21 

22import ddt 

23from oslo_log import log 

24 

25from manila import exception 

26from manila.share.drivers.netapp.dataontap.client import api as netapp_api 

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

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

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

30from manila import test 

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

32 

33 

34@ddt.ddt 

35class NetAppClientCmodeTestCase(test.TestCase): 

36 

37 def setUp(self): 

38 super(NetAppClientCmodeTestCase, self).setUp() 

39 

40 # Mock loggers as themselves to allow logger arg validation 

41 mock_logger = log.getLogger('mock_logger') 

42 self.mock_object(client_cmode.LOG, 

43 'error', 

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

45 self.mock_object(client_cmode.LOG, 

46 'warning', 

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

48 self.mock_object(client_cmode.LOG, 

49 'debug', 

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

51 

52 self.mock_object(client_base.NetAppBaseClient, 

53 'get_ontapi_version', 

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

55 

56 self.mock_object(client_base.NetAppBaseClient, 

57 'get_system_version', 

58 mock.Mock(return_value={ 

59 'version-tuple': (8, 3, 0), 

60 'version': fake.VERSION, 

61 })) 

62 

63 self.client = client_cmode.NetAppCmodeClient(**fake.CONNECTION_INFO) 

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

65 

66 self.vserver_client = client_cmode.NetAppCmodeClient( 

67 **fake.CONNECTION_INFO) 

68 self.vserver_client.set_vserver(fake.VSERVER_NAME) 

69 self.vserver_client.connection = mock.MagicMock() 

70 

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

72 self.sleep_patcher.start() 

73 self.addCleanup(self.sleep_patcher.stop) 

74 

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

76 return mock.Mock(side_effect=netapp_api.NaApiError(code=code, 

77 message=message)) 

78 

79 def test_init_features_ontapi_1_21(self): 

80 

81 self.mock_object(client_base.NetAppBaseClient, 

82 'get_ontapi_version', 

83 mock.Mock(return_value=(1, 21))) 

84 

85 self.client._init_features() 

86 

87 self.assertFalse(self.client.features.BROADCAST_DOMAINS) 

88 self.assertFalse(self.client.features.IPSPACES) 

89 self.assertFalse(self.client.features.SUBNETS) 

90 self.assertFalse(self.client.features.FLEXVOL_ENCRYPTION) 

91 

92 @ddt.data((1, 30), (1, 40), (2, 0)) 

93 def test_init_features_ontapi_1_30(self, ontapi_version): 

94 

95 self.mock_object(client_base.NetAppBaseClient, 

96 'get_ontapi_version', 

97 mock.Mock(return_value=ontapi_version)) 

98 

99 self.client._init_features() 

100 

101 self.assertTrue(self.client.features.BROADCAST_DOMAINS) 

102 self.assertTrue(self.client.features.IPSPACES) 

103 self.assertTrue(self.client.features.SUBNETS) 

104 

105 @ddt.data((1, 110), (2, 0)) 

106 def test_init_features_ontap_1_110(self, ontapi_version): 

107 

108 self.mock_object(client_base.NetAppBaseClient, 

109 'get_ontapi_version', 

110 mock.Mock(return_value=ontapi_version)) 

111 

112 self.client._init_features() 

113 

114 self.assertTrue(self.client.features.BROADCAST_DOMAINS) 

115 self.assertTrue(self.client.features.IPSPACES) 

116 self.assertTrue(self.client.features.SUBNETS) 

117 self.assertTrue(self.client.features.FLEXVOL_ENCRYPTION) 

118 

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

120 @ddt.unpack 

121 def test_is_nve_supported_unsupported_release_or_platform(self, gen, ver): 

122 

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

124 self.mock_object(client_base.NetAppBaseClient, 

125 'get_system_version', 

126 mock.Mock(return_value=system_version)) 

127 self.mock_object(self.client, 

128 'get_security_key_manager_nve_support', 

129 mock.Mock(return_value=True)) 

130 self.mock_object(self.client, 

131 'list_cluster_nodes', 

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

133 

134 result = self.client.is_nve_supported() 

135 

136 self.assertFalse(result) 

137 

138 def test_is_nve_supported_valid_platform_and_supported_release(self): 

139 

140 system_version = { 

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

142 'version': fake.VERSION, 

143 } 

144 self.mock_object(client_base.NetAppBaseClient, 

145 'get_system_version', 

146 mock.Mock(return_value=system_version)) 

147 self.mock_object(self.client, 

148 'get_security_key_manager_nve_support', 

149 mock.Mock(return_value=True)) 

150 self.mock_object(self.client, 

151 'list_cluster_nodes', 

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

153 

154 result = self.client.is_nve_supported() 

155 self.assertTrue(result) 

156 

157 def test_is_nve_supported_key_manager_not_enabled(self): 

158 

159 system_version = { 

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

161 'version': fake.VERSION, 

162 } 

163 self.mock_object(client_base.NetAppBaseClient, 

164 'get_system_version', 

165 mock.Mock(return_value=system_version)) 

166 self.mock_object(self.client, 

167 'get_security_key_manager_nve_support', 

168 mock.Mock(return_value=False)) 

169 self.mock_object(self.client, 

170 'list_cluster_nodes', 

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

172 

173 result = self.client.is_nve_supported() 

174 

175 self.assertFalse(result) 

176 

177 def test_get_security_key_manager_nve_support_enabled(self): 

178 api_response = netapp_api.NaElement( 

179 fake.SECUTITY_KEY_MANAGER_NVE_SUPPORT_RESPONSE_TRUE) 

180 self.mock_object(self.client, 

181 'send_request', 

182 mock.Mock(return_value=api_response)) 

183 

184 result = self.client.get_security_key_manager_nve_support( 

185 fake.NODE_NAME) 

186 

187 self.assertTrue(result) 

188 api_args = {'node': fake.NODE_NAME} 

189 self.client.send_request.assert_has_calls([ 

190 mock.call('security-key-manager-volume-encryption-supported', 

191 api_args)]) 

192 

193 def test_get_security_key_manager_nve_support_disabled(self): 

194 api_response = netapp_api.NaElement( 

195 fake.SECUTITY_KEY_MANAGER_NVE_SUPPORT_RESPONSE_FALSE) 

196 self.mock_object(self.client, 

197 'send_request', 

198 mock.Mock(return_value=api_response)) 

199 

200 result = self.client.get_security_key_manager_nve_support( 

201 fake.NODE_NAME) 

202 

203 self.assertFalse(result) 

204 api_args = {'node': fake.NODE_NAME} 

205 self.client.send_request.assert_has_calls([ 

206 mock.call('security-key-manager-volume-encryption-supported', 

207 api_args)]) 

208 

209 def test_get_security_key_manager_nve_support_disabled_no_license(self): 

210 self.mock_object(self.client, 

211 'send_request', 

212 self._mock_api_error()) 

213 

214 result = self.client.get_security_key_manager_nve_support( 

215 fake.NODE_NAME) 

216 

217 self.assertFalse(result) 

218 

219 api_args = {'node': fake.NODE_NAME} 

220 self.client.send_request.assert_has_calls([ 

221 mock.call('security-key-manager-volume-encryption-supported', 

222 api_args)]) 

223 

224 @ddt.data((True, True, True), (False, None, False)) 

225 @ddt.unpack 

226 def test_send_volume_move_request_success(self, validation_only, 

227 encrypt_dst, fv_encryption): 

228 self.mock_object(self.client, 'features', 

229 mock.Mock(FLEXVOL_ENCRYPTION=fv_encryption)) 

230 self.client._send_volume_move_request(fake.ROOT_VOLUME_NAME, 

231 fake.NODE_VSERVER_NAME, 

232 fake.SHARE_AGGREGATE_NAME, 

233 validation_only=validation_only, 

234 encrypt_destination=encrypt_dst) 

235 

236 @ddt.data((True, True, False)) 

237 @ddt.unpack 

238 def test_send_volume_move_request_failure(self, validation_only, 

239 encrypt_dst, fv_encrypt): 

240 self.mock_object(self.client, 'features', 

241 mock.Mock(FLEXVOL_ENCRYPTION=fv_encrypt)) 

242 self.assertRaises(exception.NetAppException, 

243 self.client._send_volume_move_request, 

244 fake.ROOT_VOLUME_NAME, 

245 fake.NODE_VSERVER_NAME, 

246 fake.SHARE_AGGREGATE_NAME, 

247 validation_only=validation_only, 

248 encrypt_destination=encrypt_dst) 

249 

250 def test_invoke_vserver_api(self): 

251 

252 self.client._invoke_vserver_api('fake-api', 'fake_vserver') 

253 

254 self.client.connection.set_vserver.assert_has_calls( 

255 [mock.call('fake_vserver')]) 

256 self.client.connection.invoke_successfully.assert_has_calls( 

257 [mock.call('fake-api', True)]) 

258 

259 def test_has_records(self): 

260 self.assertTrue(self.client._has_records( 

261 netapp_api.NaElement(fake.VSERVER_GET_ITER_RESPONSE))) 

262 

263 def test_has_records_not_found(self): 

264 self.assertFalse(self.client._has_records( 

265 netapp_api.NaElement(fake.NO_RECORDS_RESPONSE))) 

266 

267 @ddt.data((fake.VSERVER_GET_ITER_RESPONSE, 1), 

268 (fake.NO_RECORDS_RESPONSE, 0)) 

269 @ddt.unpack 

270 def test_get_record_count(self, response, expected): 

271 

272 api_response = netapp_api.NaElement(response) 

273 

274 result = self.client._get_record_count(api_response) 

275 

276 self.assertEqual(expected, result) 

277 

278 def test_get_records_count_invalid(self): 

279 

280 api_response = netapp_api.NaElement( 

281 fake.INVALID_GET_ITER_RESPONSE_NO_RECORDS) 

282 

283 self.assertRaises(exception.NetAppException, 

284 self.client._get_record_count, 

285 api_response) 

286 

287 def test_send_iter_request(self): 

288 

289 api_responses = [ 

290 netapp_api.NaElement(fake.STORAGE_DISK_GET_ITER_RESPONSE_PAGE_1), 

291 netapp_api.NaElement(fake.STORAGE_DISK_GET_ITER_RESPONSE_PAGE_2), 

292 netapp_api.NaElement(fake.STORAGE_DISK_GET_ITER_RESPONSE_PAGE_3), 

293 ] 

294 mock_send_request = self.mock_object( 

295 self.client, 'send_request', 

296 mock.Mock(side_effect=api_responses)) 

297 

298 storage_disk_get_iter_args = { 

299 'desired-attributes': { 

300 'storage-disk-info': { 

301 'disk-name': None, 

302 } 

303 } 

304 } 

305 result = self.client.send_iter_request( 

306 'storage-disk-get-iter', api_args=storage_disk_get_iter_args, 

307 max_page_length=10) 

308 

309 num_records = result.get_child_content('num-records') 

310 self.assertEqual('28', num_records) 

311 next_tag = result.get_child_content('next-tag') 

312 self.assertEqual('', next_tag) 

313 

314 args1 = copy.deepcopy(storage_disk_get_iter_args) 

315 args1['max-records'] = 10 

316 args2 = copy.deepcopy(storage_disk_get_iter_args) 

317 args2['max-records'] = 10 

318 args2['tag'] = 'next_tag_1' 

319 args3 = copy.deepcopy(storage_disk_get_iter_args) 

320 args3['max-records'] = 10 

321 args3['tag'] = 'next_tag_2' 

322 

323 mock_send_request.assert_has_calls([ 

324 mock.call('storage-disk-get-iter', args1, enable_tunneling=True), 

325 mock.call('storage-disk-get-iter', args2, enable_tunneling=True), 

326 mock.call('storage-disk-get-iter', args3, enable_tunneling=True), 

327 ]) 

328 

329 def test_send_iter_request_single_page(self): 

330 

331 api_response = netapp_api.NaElement( 

332 fake.STORAGE_DISK_GET_ITER_RESPONSE) 

333 mock_send_request = self.mock_object( 

334 self.client, 'send_request', 

335 mock.Mock(return_value=api_response)) 

336 

337 storage_disk_get_iter_args = { 

338 'desired-attributes': { 

339 'storage-disk-info': { 

340 'disk-name': None, 

341 } 

342 } 

343 } 

344 result = self.client.send_iter_request( 

345 'storage-disk-get-iter', api_args=storage_disk_get_iter_args, 

346 max_page_length=10) 

347 

348 num_records = result.get_child_content('num-records') 

349 self.assertEqual('4', num_records) 

350 

351 args = copy.deepcopy(storage_disk_get_iter_args) 

352 args['max-records'] = 10 

353 

354 mock_send_request.assert_has_calls([ 

355 mock.call('storage-disk-get-iter', args, enable_tunneling=True), 

356 ]) 

357 

358 def test_send_iter_request_not_found(self): 

359 

360 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

361 mock_send_request = self.mock_object( 

362 self.client, 'send_request', 

363 mock.Mock(return_value=api_response)) 

364 

365 result = self.client.send_iter_request('storage-disk-get-iter') 

366 

367 num_records = result.get_child_content('num-records') 

368 self.assertEqual('0', num_records) 

369 

370 args = {'max-records': client_cmode.DEFAULT_MAX_PAGE_LENGTH} 

371 

372 mock_send_request.assert_has_calls([ 

373 mock.call('storage-disk-get-iter', args, enable_tunneling=True), 

374 ]) 

375 

376 @ddt.data(fake.INVALID_GET_ITER_RESPONSE_NO_ATTRIBUTES, 

377 fake.INVALID_GET_ITER_RESPONSE_NO_RECORDS) 

378 def test_send_iter_request_invalid(self, fake_response): 

379 

380 api_response = netapp_api.NaElement(fake_response) 

381 self.mock_object(self.client, 

382 'send_request', 

383 mock.Mock(return_value=api_response)) 

384 

385 self.assertRaises(exception.NetAppException, 

386 self.client.send_iter_request, 

387 'storage-disk-get-iter') 

388 

389 def test_set_vserver(self): 

390 self.client.set_vserver(fake.VSERVER_NAME) 

391 self.client.connection.set_vserver.assert_has_calls( 

392 [mock.call('fake_vserver')]) 

393 

394 def test_vserver_exists(self): 

395 

396 api_response = netapp_api.NaElement(fake.VSERVER_GET_ITER_RESPONSE) 

397 self.mock_object(self.client, 

398 'send_iter_request', 

399 mock.Mock(return_value=api_response)) 

400 

401 vserver_get_args = { 

402 'query': {'vserver-info': {'vserver-name': fake.VSERVER_NAME}}, 

403 'desired-attributes': {'vserver-info': {'vserver-name': None}} 

404 } 

405 

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

407 

408 self.client.send_iter_request.assert_has_calls([ 

409 mock.call('vserver-get-iter', vserver_get_args, 

410 enable_tunneling=False)]) 

411 self.assertTrue(result) 

412 

413 def test_vserver_exists_not_found(self): 

414 

415 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

416 self.mock_object(self.client, 

417 'send_request', 

418 mock.Mock(return_value=api_response)) 

419 

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

421 

422 self.assertFalse(result) 

423 

424 @ddt.data(0, 65535, 270000) 

425 def test_create_vserver_delete_retention_hours(self, 

426 delete_retention_hours): 

427 

428 self.client.features.add_feature('DELETE_RETENTION_HOURS') 

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

430 self.mock_object(self.client, 

431 '_modify_security_cert', 

432 mock.Mock()) 

433 

434 vserver_create_args = { 

435 'vserver-name': fake.VSERVER_NAME, 

436 'root-volume-security-style': 'unix', 

437 'root-volume-aggregate': fake.ROOT_VOLUME_AGGREGATE_NAME, 

438 'root-volume': fake.ROOT_VOLUME_NAME, 

439 'name-server-switch': {'nsswitch': 'file'}, 

440 'is-space-reporting-logical': 'false', 

441 'is-space-enforcement-logical': 'false' 

442 } 

443 vserver_modify_args = { 

444 'aggr-list': [{'aggr-name': aggr_name} for aggr_name 

445 in fake.SHARE_AGGREGATE_NAMES], 

446 'vserver-name': fake.VSERVER_NAME, 

447 'volume-delete-retention-hours': str(delete_retention_hours), 

448 } 

449 

450 self.client.create_vserver(fake.VSERVER_NAME, 

451 fake.ROOT_VOLUME_AGGREGATE_NAME, 

452 fake.ROOT_VOLUME_NAME, 

453 fake.SHARE_AGGREGATE_NAMES, 

454 None, 

455 fake.SECURITY_CERT_LARGE_EXPIRE_DAYS, 

456 delete_retention_hours, 

457 False) 

458 

459 self.client.send_request.assert_has_calls([ 

460 mock.call('vserver-create', vserver_create_args), 

461 mock.call('vserver-modify', vserver_modify_args)]) 

462 self.client._modify_security_cert.assert_called_with( 

463 fake.VSERVER_NAME, fake.SECURITY_CERT_LARGE_EXPIRE_DAYS) 

464 

465 def test_create_vserver_no_ipspace(self): 

466 

467 self.client.features.add_feature('DELETE_RETENTION_HOURS') 

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

469 self.mock_object(self.client, 

470 '_modify_security_cert', 

471 mock.Mock()) 

472 

473 vserver_create_args = { 

474 'vserver-name': fake.VSERVER_NAME, 

475 'root-volume-security-style': 'unix', 

476 'root-volume-aggregate': fake.ROOT_VOLUME_AGGREGATE_NAME, 

477 'root-volume': fake.ROOT_VOLUME_NAME, 

478 'name-server-switch': {'nsswitch': 'file'}, 

479 'is-space-reporting-logical': 'false', 

480 'is-space-enforcement-logical': 'false' 

481 } 

482 vserver_modify_args = { 

483 'aggr-list': [{'aggr-name': aggr_name} for aggr_name 

484 in fake.SHARE_AGGREGATE_NAMES], 

485 'vserver-name': fake.VSERVER_NAME, 

486 'volume-delete-retention-hours': '16', 

487 } 

488 

489 self.client.create_vserver(fake.VSERVER_NAME, 

490 fake.ROOT_VOLUME_AGGREGATE_NAME, 

491 fake.ROOT_VOLUME_NAME, 

492 fake.SHARE_AGGREGATE_NAMES, 

493 None, 

494 fake.SECURITY_CERT_LARGE_EXPIRE_DAYS, 

495 16, 

496 False) 

497 

498 self.client.send_request.assert_has_calls([ 

499 mock.call('vserver-create', vserver_create_args), 

500 mock.call('vserver-modify', vserver_modify_args)]) 

501 self.client._modify_security_cert.assert_called_with( 

502 fake.VSERVER_NAME, fake.SECURITY_CERT_LARGE_EXPIRE_DAYS) 

503 

504 def test_create_vserver_with_ipspace(self): 

505 

506 self.client.features.add_feature('IPSPACES') 

507 self.client.features.add_feature('DELETE_RETENTION_HOURS') 

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

509 self.mock_object(self.client, 

510 '_modify_security_cert', 

511 mock.Mock()) 

512 

513 vserver_create_args = { 

514 'vserver-name': fake.VSERVER_NAME, 

515 'root-volume-security-style': 'unix', 

516 'root-volume-aggregate': fake.ROOT_VOLUME_AGGREGATE_NAME, 

517 'root-volume': fake.ROOT_VOLUME_NAME, 

518 'name-server-switch': {'nsswitch': 'file'}, 

519 'ipspace': fake.IPSPACE_NAME, 

520 'is-space-reporting-logical': 'false', 

521 'is-space-enforcement-logical': 'false' 

522 } 

523 vserver_modify_args = { 

524 'aggr-list': [{'aggr-name': aggr_name} for aggr_name 

525 in fake.SHARE_AGGREGATE_NAMES], 

526 'volume-delete-retention-hours': '24', 

527 'vserver-name': fake.VSERVER_NAME 

528 } 

529 

530 self.client.create_vserver(fake.VSERVER_NAME, 

531 fake.ROOT_VOLUME_AGGREGATE_NAME, 

532 fake.ROOT_VOLUME_NAME, 

533 fake.SHARE_AGGREGATE_NAMES, 

534 fake.IPSPACE_NAME, 

535 fake.SECURITY_CERT_LARGE_EXPIRE_DAYS, 

536 24, 

537 False) 

538 

539 self.client.send_request.assert_has_calls([ 

540 mock.call('vserver-create', vserver_create_args), 

541 mock.call('vserver-modify', vserver_modify_args)]) 

542 self.client._modify_security_cert.assert_called_with( 

543 fake.VSERVER_NAME, fake.SECURITY_CERT_LARGE_EXPIRE_DAYS) 

544 

545 def test__modify_security_cert(self): 

546 

547 certificate_create_args = { 

548 'vserver': fake.VSERVER_NAME, 

549 'common-name': fake.VSERVER_NAME, 

550 'type': 'server', 

551 'expire-days': fake.SECURITY_CERT_LARGE_EXPIRE_DAYS, 

552 } 

553 

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

555 api_response = netapp_api.NaElement(fake.SECURITY_CERT_GET_RESPONSE) 

556 self.mock_object(self.client, 

557 'send_iter_request', 

558 mock.Mock(return_value=api_response)) 

559 certificate_get_args = { 

560 'query': { 

561 'certificate-info': { 

562 'vserver': fake.VSERVER_NAME, 

563 'common-name': fake.VSERVER_NAME, 

564 'certificate-authority': fake.VSERVER_NAME, 

565 'type': 'server', 

566 }, 

567 }, 

568 'desired-attributes': { 

569 'certificate-info': { 

570 'serial-number': None, 

571 }, 

572 }, 

573 } 

574 

575 certificate_delete_args = { 

576 'certificate-authority': fake.VSERVER_NAME, 

577 'common-name': fake.VSERVER_NAME, 

578 'serial-number': '12345', 

579 'type': 'server', 

580 'vserver': fake.VSERVER_NAME, 

581 } 

582 

583 self.client._modify_security_cert( 

584 fake.VSERVER_NAME, 

585 fake.SECURITY_CERT_LARGE_EXPIRE_DAYS) 

586 

587 self.client.send_request.assert_has_calls([ 

588 mock.call( 

589 'security-certificate-create', certificate_create_args), 

590 mock.call( 

591 'security-certificate-delete', certificate_delete_args)]) 

592 

593 self.client.send_iter_request.assert_has_calls([ 

594 mock.call('security-certificate-get-iter', certificate_get_args)]) 

595 

596 def test_create_vserver_dp_destination(self): 

597 

598 self.client.features.add_feature('IPSPACES') 

599 self.client.features.add_feature('DELETE_RETENTION_HOURS') 

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

601 

602 vserver_create_args = { 

603 'vserver-name': fake.VSERVER_NAME, 

604 'ipspace': fake.IPSPACE_NAME, 

605 'vserver-subtype': fake.VSERVER_TYPE_DP_DEST, 

606 'is-space-reporting-logical': 'false', 

607 'is-space-enforcement-logical': 'false' 

608 } 

609 vserver_modify_args = { 

610 'aggr-list': [{'aggr-name': aggr_name} for aggr_name 

611 in fake.SHARE_AGGREGATE_NAMES], 

612 'volume-delete-retention-hours': '18', 

613 'vserver-name': fake.VSERVER_NAME 

614 } 

615 

616 self.client.create_vserver_dp_destination( 

617 fake.VSERVER_NAME, 

618 fake.SHARE_AGGREGATE_NAMES, 

619 fake.IPSPACE_NAME, 

620 18, 

621 False) 

622 

623 self.client.send_request.assert_has_calls([ 

624 mock.call('vserver-create', vserver_create_args), 

625 mock.call('vserver-modify', vserver_modify_args)]) 

626 

627 def test_create_vserver_ipspaces_not_supported(self): 

628 

629 self.assertRaises(exception.NetAppException, 

630 self.client.create_vserver, 

631 fake.VSERVER_NAME, 

632 fake.ROOT_VOLUME_AGGREGATE_NAME, 

633 fake.ROOT_VOLUME_NAME, 

634 fake.SHARE_AGGREGATE_NAMES, 

635 fake.IPSPACE_NAME, 

636 fake.SECURITY_CERT_LARGE_EXPIRE_DAYS, 

637 10, 

638 False) 

639 

640 def test_get_vserver_root_volume_name(self): 

641 

642 api_response = netapp_api.NaElement( 

643 fake.VSERVER_GET_ROOT_VOLUME_NAME_RESPONSE) 

644 self.mock_object(self.client, 

645 'send_iter_request', 

646 mock.Mock(return_value=api_response)) 

647 

648 vserver_get_args = { 

649 'query': {'vserver-info': {'vserver-name': fake.VSERVER_NAME}}, 

650 'desired-attributes': {'vserver-info': {'root-volume': None}} 

651 } 

652 

653 result = self.client.get_vserver_root_volume_name(fake.VSERVER_NAME) 

654 

655 self.client.send_iter_request.assert_has_calls([ 

656 mock.call('vserver-get-iter', vserver_get_args)]) 

657 self.assertEqual(fake.ROOT_VOLUME_NAME, result) 

658 

659 def test_get_vserver_root_volume_name_not_found(self): 

660 

661 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

662 self.mock_object(self.client, 

663 'send_iter_request', 

664 mock.Mock(return_value=api_response)) 

665 

666 self.assertRaises(exception.NetAppException, 

667 self.client.get_vserver_root_volume_name, 

668 fake.VSERVER_NAME) 

669 

670 def test_get_vserver_ipspace(self): 

671 

672 self.client.features.add_feature('IPSPACES') 

673 api_response = netapp_api.NaElement( 

674 fake.VSERVER_GET_IPSPACE_NAME_RESPONSE) 

675 self.mock_object(self.client, 

676 'send_iter_request', 

677 mock.Mock(return_value=api_response)) 

678 

679 result = self.client.get_vserver_ipspace(fake.VSERVER_NAME) 

680 

681 vserver_get_iter_args = { 

682 'query': { 

683 'vserver-info': { 

684 'vserver-name': fake.VSERVER_NAME, 

685 }, 

686 }, 

687 'desired-attributes': { 

688 'vserver-info': { 

689 'ipspace': None, 

690 }, 

691 }, 

692 } 

693 self.client.send_iter_request.assert_has_calls([ 

694 mock.call('vserver-get-iter', vserver_get_iter_args)]) 

695 self.assertEqual(fake.IPSPACE_NAME, result) 

696 

697 def test_get_vserver_ipspace_not_supported(self): 

698 

699 result = self.client.get_vserver_ipspace(fake.IPSPACE_NAME) 

700 

701 self.assertIsNone(result) 

702 

703 def test_get_vserver_ipspace_not_found(self): 

704 

705 self.client.features.add_feature('IPSPACES') 

706 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

707 self.mock_object(self.client, 

708 'send_iter_request', 

709 mock.Mock(return_value=api_response)) 

710 

711 self.assertRaises(exception.NetAppException, 

712 self.client.get_vserver_ipspace, 

713 fake.IPSPACE_NAME) 

714 

715 def test_ipspace_has_data_vservers(self): 

716 

717 self.client.features.add_feature('IPSPACES') 

718 api_response = netapp_api.NaElement(fake.VSERVER_GET_ITER_RESPONSE) 

719 self.mock_object(self.client, 

720 'send_iter_request', 

721 mock.Mock(return_value=api_response)) 

722 

723 result = self.client.ipspace_has_data_vservers(fake.IPSPACE_NAME) 

724 

725 vserver_get_iter_args = { 

726 'query': { 

727 'vserver-info': { 

728 'ipspace': fake.IPSPACE_NAME, 

729 'vserver-type': 'data' 

730 }, 

731 }, 

732 'desired-attributes': { 

733 'vserver-info': { 

734 'vserver-name': None, 

735 }, 

736 }, 

737 } 

738 self.client.send_iter_request.assert_has_calls([ 

739 mock.call('vserver-get-iter', vserver_get_iter_args)]) 

740 self.assertTrue(result) 

741 

742 def test_ipspace_has_data_vservers_not_supported(self): 

743 

744 result = self.client.ipspace_has_data_vservers(fake.IPSPACE_NAME) 

745 

746 self.assertFalse(result) 

747 

748 def test_ipspace_has_data_vservers_not_found(self): 

749 

750 self.client.features.add_feature('IPSPACES') 

751 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

752 self.mock_object(self.client, 

753 'send_request', 

754 mock.Mock(return_value=api_response)) 

755 

756 result = self.client.ipspace_has_data_vservers(fake.IPSPACE_NAME) 

757 

758 self.assertFalse(result) 

759 

760 def test_list_vservers(self): 

761 

762 api_response = netapp_api.NaElement( 

763 fake.VSERVER_DATA_LIST_RESPONSE) 

764 self.mock_object(self.client, 

765 'send_iter_request', 

766 mock.Mock(return_value=api_response)) 

767 

768 result = self.client.list_vservers() 

769 

770 vserver_get_iter_args = { 

771 'query': { 

772 'vserver-info': { 

773 'vserver-type': 'data' 

774 } 

775 }, 

776 'desired-attributes': { 

777 'vserver-info': { 

778 'vserver-name': None 

779 } 

780 } 

781 } 

782 self.client.send_iter_request.assert_has_calls([ 

783 mock.call('vserver-get-iter', vserver_get_iter_args)]) 

784 self.assertListEqual([fake.VSERVER_NAME], result) 

785 

786 def test_list_vservers_node_type(self): 

787 

788 api_response = netapp_api.NaElement( 

789 fake.VSERVER_DATA_LIST_RESPONSE) 

790 self.mock_object(self.client, 

791 'send_iter_request', 

792 mock.Mock(return_value=api_response)) 

793 

794 result = self.client.list_vservers(vserver_type='node') 

795 

796 vserver_get_iter_args = { 

797 'query': { 

798 'vserver-info': { 

799 'vserver-type': 'node' 

800 } 

801 }, 

802 'desired-attributes': { 

803 'vserver-info': { 

804 'vserver-name': None 

805 } 

806 } 

807 } 

808 self.client.send_iter_request.assert_has_calls([ 

809 mock.call('vserver-get-iter', vserver_get_iter_args)]) 

810 self.assertListEqual([fake.VSERVER_NAME], result) 

811 

812 def test_list_vservers_not_found(self): 

813 

814 api_response = netapp_api.NaElement( 

815 fake.NO_RECORDS_RESPONSE) 

816 self.mock_object(self.client, 

817 'send_request', 

818 mock.Mock(return_value=api_response)) 

819 

820 result = self.client.list_vservers(vserver_type='data') 

821 

822 self.assertListEqual([], result) 

823 

824 def test_get_vserver_volume_count(self): 

825 

826 api_response = netapp_api.NaElement(fake.VOLUME_COUNT_RESPONSE) 

827 self.mock_object(self.client, 

828 'send_iter_request', 

829 mock.Mock(return_value=api_response)) 

830 

831 result = self.client.get_vserver_volume_count() 

832 

833 self.assertEqual(2, result) 

834 

835 def test_delete_vserver_no_volumes(self): 

836 

837 self.mock_object(self.client, 

838 'get_vserver_info', 

839 mock.Mock(return_value=fake.VSERVER_INFO)) 

840 self.mock_object(self.client, 

841 'get_vserver_root_volume_name', 

842 mock.Mock(return_value=fake.ROOT_VOLUME_NAME)) 

843 self.mock_object(self.vserver_client, 

844 'get_vserver_volume_count', 

845 mock.Mock(return_value=0)) 

846 self.mock_object(self.client, '_terminate_vserver_services') 

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

848 

849 self.client.delete_vserver( 

850 fake.VSERVER_NAME, 

851 self.vserver_client, 

852 security_services=[fake.CIFS_SECURITY_SERVICE]) 

853 

854 self.client._terminate_vserver_services.assert_called_with( 

855 fake.VSERVER_NAME, self.vserver_client, 

856 [fake.CIFS_SECURITY_SERVICE]) 

857 

858 vserver_destroy_args = {'vserver-name': fake.VSERVER_NAME} 

859 self.client.send_request.assert_has_calls([ 

860 mock.call('vserver-destroy', vserver_destroy_args)]) 

861 

862 def test_delete_vserver_one_volume(self): 

863 

864 self.mock_object(self.client, 

865 'get_vserver_info', 

866 mock.Mock(return_value=fake.VSERVER_INFO)) 

867 self.mock_object(self.client, 

868 'get_vserver_root_volume_name', 

869 mock.Mock(return_value=fake.ROOT_VOLUME_NAME)) 

870 self.mock_object(self.vserver_client, 

871 'get_vserver_volume_count', 

872 mock.Mock(return_value=1)) 

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

874 self.mock_object(self.vserver_client, 'offline_volume') 

875 self.mock_object(self.vserver_client, 'delete_volume') 

876 

877 self.client.delete_vserver(fake.VSERVER_NAME, 

878 self.vserver_client) 

879 

880 self.vserver_client.offline_volume.assert_called_with( 

881 fake.ROOT_VOLUME_NAME) 

882 self.vserver_client.delete_volume.assert_called_with( 

883 fake.ROOT_VOLUME_NAME) 

884 

885 vserver_destroy_args = {'vserver-name': fake.VSERVER_NAME} 

886 self.client.send_request.assert_has_calls([ 

887 mock.call('vserver-destroy', vserver_destroy_args)]) 

888 

889 def test_delete_vserver_one_volume_already_offline(self): 

890 

891 self.mock_object(self.client, 

892 'get_vserver_info', 

893 mock.Mock(return_value=fake.VSERVER_INFO)) 

894 self.mock_object(self.client, 

895 'get_vserver_root_volume_name', 

896 mock.Mock(return_value=fake.ROOT_VOLUME_NAME)) 

897 self.mock_object(self.vserver_client, 

898 'get_vserver_volume_count', 

899 mock.Mock(return_value=1)) 

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

901 self.mock_object(self.vserver_client, 

902 'offline_volume', 

903 self._mock_api_error(code=netapp_api.EVOLUMEOFFLINE)) 

904 

905 self.mock_object(self.vserver_client, 'delete_volume') 

906 

907 self.client.delete_vserver(fake.VSERVER_NAME, 

908 self.vserver_client) 

909 

910 self.vserver_client.offline_volume.assert_called_with( 

911 fake.ROOT_VOLUME_NAME) 

912 self.vserver_client.delete_volume.assert_called_with( 

913 fake.ROOT_VOLUME_NAME) 

914 

915 vserver_destroy_args = {'vserver-name': fake.VSERVER_NAME} 

916 self.client.send_request.assert_has_calls([ 

917 mock.call('vserver-destroy', vserver_destroy_args)]) 

918 self.assertEqual(1, client_cmode.LOG.error.call_count) 

919 

920 def test_delete_vserver_one_volume_api_error(self): 

921 

922 self.mock_object(self.client, 

923 'get_vserver_info', 

924 mock.Mock(return_value=fake.VSERVER_INFO)) 

925 self.mock_object(self.client, 

926 'get_vserver_root_volume_name', 

927 mock.Mock(return_value=fake.ROOT_VOLUME_NAME)) 

928 self.mock_object(self.vserver_client, 

929 'get_vserver_volume_count', 

930 mock.Mock(return_value=1)) 

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

932 self.mock_object(self.vserver_client, 

933 'offline_volume', 

934 self._mock_api_error()) 

935 self.mock_object(self.vserver_client, 'delete_volume') 

936 

937 self.assertRaises(netapp_api.NaApiError, 

938 self.client.delete_vserver, 

939 fake.VSERVER_NAME, 

940 self.vserver_client) 

941 

942 def test_delete_vserver_multiple_volumes(self): 

943 

944 self.mock_object(self.client, 

945 'get_vserver_info', 

946 mock.Mock(return_value=fake.VSERVER_INFO)) 

947 self.mock_object(self.client, 

948 'get_vserver_root_volume_name', 

949 mock.Mock(return_value=fake.ROOT_VOLUME_NAME)) 

950 self.mock_object(self.vserver_client, 

951 'get_vserver_volume_count', 

952 mock.Mock(return_value=2)) 

953 

954 self.assertRaises(exception.NetAppException, 

955 self.client.delete_vserver, 

956 fake.VSERVER_NAME, 

957 self.vserver_client) 

958 

959 def test_delete_vserver_not_found(self): 

960 

961 self.mock_object(self.client, 

962 'get_vserver_info', 

963 mock.Mock(return_value=None)) 

964 

965 self.client.delete_vserver(fake.VSERVER_NAME, 

966 self.vserver_client) 

967 

968 self.assertEqual(1, client_cmode.LOG.error.call_count) 

969 

970 def test_terminate_vserver_services(self): 

971 

972 self.mock_object(self.vserver_client, 'send_request') 

973 

974 self.client._terminate_vserver_services(fake.VSERVER_NAME, 

975 self.vserver_client, 

976 [fake.CIFS_SECURITY_SERVICE]) 

977 

978 cifs_server_delete_args = { 

979 'admin-password': fake.CIFS_SECURITY_SERVICE['password'], 

980 'admin-username': fake.CIFS_SECURITY_SERVICE['user'], 

981 } 

982 self.vserver_client.send_request.assert_has_calls([ 

983 mock.call('cifs-server-delete', cifs_server_delete_args)]) 

984 

985 def test_terminate_vserver_services_cifs_not_found(self): 

986 

987 self.mock_object(self.vserver_client, 

988 'send_request', 

989 self._mock_api_error( 

990 code=netapp_api.EOBJECTNOTFOUND)) 

991 

992 self.client._terminate_vserver_services(fake.VSERVER_NAME, 

993 self.vserver_client, 

994 [fake.CIFS_SECURITY_SERVICE]) 

995 

996 cifs_server_delete_args = { 

997 'admin-password': fake.CIFS_SECURITY_SERVICE['password'], 

998 'admin-username': fake.CIFS_SECURITY_SERVICE['user'], 

999 } 

1000 self.vserver_client.send_request.assert_has_calls([ 

1001 mock.call('cifs-server-delete', cifs_server_delete_args)]) 

1002 self.assertEqual(1, client_cmode.LOG.error.call_count) 

1003 

1004 def test_terminate_vserver_services_api_error(self): 

1005 

1006 side_effects = [netapp_api.NaApiError(code='fake'), None] 

1007 self.mock_object(self.vserver_client, 

1008 'send_request', 

1009 mock.Mock(side_effect=side_effects)) 

1010 

1011 self.client._terminate_vserver_services(fake.VSERVER_NAME, 

1012 self.vserver_client, 

1013 [fake.CIFS_SECURITY_SERVICE]) 

1014 

1015 cifs_server_delete_args = { 

1016 'admin-password': fake.CIFS_SECURITY_SERVICE['password'], 

1017 'admin-username': fake.CIFS_SECURITY_SERVICE['user'], 

1018 } 

1019 cifs_server_delete_force_args = { 

1020 'force-account-delete': 'true', 

1021 } 

1022 self.vserver_client.send_request.assert_has_calls([ 

1023 mock.call('cifs-server-delete', cifs_server_delete_args), 

1024 mock.call('cifs-server-delete', cifs_server_delete_force_args)]) 

1025 self.assertEqual(0, client_cmode.LOG.error.call_count) 

1026 

1027 def test_list_cluster_nodes(self): 

1028 

1029 api_response = netapp_api.NaElement( 

1030 fake.SYSTEM_NODE_GET_ITER_RESPONSE) 

1031 self.mock_object(self.client, 

1032 'send_request', 

1033 mock.Mock(return_value=api_response)) 

1034 

1035 result = self.client.list_cluster_nodes() 

1036 

1037 self.assertListEqual([fake.NODE_NAME], result) 

1038 

1039 def test_list_cluster_nodes_not_found(self): 

1040 

1041 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

1042 self.mock_object(self.client, 

1043 'send_request', 

1044 mock.Mock(return_value=api_response)) 

1045 

1046 result = self.client.list_cluster_nodes() 

1047 

1048 self.assertListEqual([], result) 

1049 

1050 def test_list_node_data_ports(self): 

1051 

1052 self.mock_object(self.client, 

1053 'get_node_data_ports', 

1054 mock.Mock(return_value=fake.SPEED_SORTED_PORTS)) 

1055 

1056 result = self.client.list_node_data_ports(fake.NODE_NAME) 

1057 

1058 self.assertSequenceEqual(fake.SPEED_SORTED_PORT_NAMES, result) 

1059 

1060 def test_get_node_data_ports(self): 

1061 

1062 api_response = netapp_api.NaElement(fake.NET_PORT_GET_ITER_RESPONSE) 

1063 self.mock_object(self.client, 

1064 'send_iter_request', 

1065 mock.Mock(return_value=api_response)) 

1066 

1067 result = self.client.get_node_data_ports(fake.NODE_NAME) 

1068 

1069 net_port_get_iter_args = { 

1070 'query': { 

1071 'net-port-info': { 

1072 'node': fake.NODE_NAME, 

1073 'link-status': 'up', 

1074 'port-type': 'physical|if_group', 

1075 'role': 'data', 

1076 }, 

1077 }, 

1078 'desired-attributes': { 

1079 'net-port-info': { 

1080 'port': None, 

1081 'node': None, 

1082 'operational-speed': None, 

1083 'ifgrp-port': None, 

1084 }, 

1085 }, 

1086 } 

1087 

1088 self.assertSequenceEqual(fake.SPEED_SORTED_PORTS, result) 

1089 self.client.send_iter_request.assert_has_calls([ 

1090 mock.call('net-port-get-iter', net_port_get_iter_args)]) 

1091 

1092 def test_get_node_data_ports_not_found(self): 

1093 

1094 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

1095 self.mock_object(self.client, 

1096 'send_iter_request', 

1097 mock.Mock(return_value=api_response)) 

1098 

1099 result = self.client.get_node_data_ports(fake.NODE_NAME) 

1100 

1101 self.assertSequenceEqual([], result) 

1102 

1103 def test_sort_data_ports_by_speed(self): 

1104 

1105 result = self.client._sort_data_ports_by_speed( 

1106 fake.UNSORTED_PORTS_ALL_SPEEDS) 

1107 

1108 self.assertSequenceEqual(fake.SORTED_PORTS_ALL_SPEEDS, result) 

1109 

1110 def test_list_root_aggregates(self): 

1111 

1112 api_response = netapp_api.NaElement( 

1113 fake.AGGR_GET_ITER_ROOT_AGGR_RESPONSE) 

1114 self.mock_object(self.client, 

1115 'send_iter_request', 

1116 mock.Mock(return_value=api_response)) 

1117 

1118 result = self.client.list_root_aggregates() 

1119 

1120 aggr_get_iter_args = { 

1121 'desired-attributes': { 

1122 'aggr-attributes': { 

1123 'aggregate-name': None, 

1124 'aggr-raid-attributes': { 

1125 'has-local-root': None, 

1126 'has-partner-root': None, 

1127 }, 

1128 }, 

1129 } 

1130 } 

1131 self.assertSequenceEqual(fake.ROOT_AGGREGATE_NAMES, result) 

1132 self.client.send_iter_request.assert_has_calls([ 

1133 mock.call('aggr-get-iter', aggr_get_iter_args)]) 

1134 

1135 def test_list_non_root_aggregates(self): 

1136 

1137 api_response = netapp_api.NaElement( 

1138 fake.AGGR_GET_ITER_NON_ROOT_AGGR_RESPONSE) 

1139 self.mock_object(self.client, 

1140 'send_iter_request', 

1141 mock.Mock(return_value=api_response)) 

1142 

1143 result = self.client.list_non_root_aggregates() 

1144 

1145 aggr_get_iter_args = { 

1146 'query': { 

1147 'aggr-attributes': { 

1148 'aggr-raid-attributes': { 

1149 'has-local-root': 'false', 

1150 'has-partner-root': 'false', 

1151 } 

1152 }, 

1153 }, 

1154 'desired-attributes': { 

1155 'aggr-attributes': { 

1156 'aggregate-name': None, 

1157 }, 

1158 }, 

1159 } 

1160 self.assertSequenceEqual(fake.SHARE_AGGREGATE_NAMES, result) 

1161 self.client.send_iter_request.assert_has_calls([ 

1162 mock.call('aggr-get-iter', aggr_get_iter_args)]) 

1163 

1164 def test_list_aggregates(self): 

1165 

1166 api_response = netapp_api.NaElement(fake.AGGR_GET_NAMES_RESPONSE) 

1167 self.mock_object(self.client, 

1168 'send_iter_request', 

1169 mock.Mock(return_value=api_response)) 

1170 

1171 result = self.client._list_aggregates() 

1172 

1173 aggr_get_iter_args = { 

1174 'desired-attributes': { 

1175 'aggr-attributes': { 

1176 'aggregate-name': None, 

1177 }, 

1178 }, 

1179 } 

1180 self.assertSequenceEqual( 

1181 fake.ROOT_AGGREGATE_NAMES + fake.SHARE_AGGREGATE_NAMES, result) 

1182 self.client.send_iter_request.assert_has_calls([ 

1183 mock.call('aggr-get-iter', aggr_get_iter_args)]) 

1184 

1185 def test_list_aggregates_not_found(self): 

1186 

1187 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

1188 self.mock_object(self.client, 

1189 'send_request', 

1190 mock.Mock(return_value=api_response)) 

1191 

1192 self.assertRaises(exception.NetAppException, 

1193 self.client._list_aggregates) 

1194 

1195 def test_list_vserver_aggregates(self): 

1196 

1197 self.mock_object(self.vserver_client, 

1198 'get_vserver_aggregate_capacities', 

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

1200 

1201 result = self.vserver_client.list_vserver_aggregates() 

1202 

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

1204 

1205 def test_list_vserver_aggregates_none_found(self): 

1206 

1207 self.mock_object(self.vserver_client, 

1208 'get_vserver_aggregate_capacities', 

1209 mock.Mock(return_value={})) 

1210 

1211 result = self.vserver_client.list_vserver_aggregates() 

1212 

1213 self.assertListEqual([], result) 

1214 

1215 def test_create_network_interface(self): 

1216 

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

1218 

1219 lif_create_args = { 

1220 'address': fake.IP_ADDRESS, 

1221 'administrative-status': 'up', 

1222 'data-protocols': [ 

1223 {'data-protocol': 'nfs'}, 

1224 {'data-protocol': 'cifs'} 

1225 ], 

1226 'home-node': fake.NODE_NAME, 

1227 'home-port': fake.VLAN_PORT, 

1228 'netmask': fake.NETMASK, 

1229 'interface-name': fake.LIF_NAME, 

1230 'role': 'data', 

1231 'vserver': fake.VSERVER_NAME, 

1232 } 

1233 self.client.create_network_interface(fake.IP_ADDRESS, 

1234 fake.NETMASK, 

1235 fake.NODE_NAME, 

1236 fake.VLAN_PORT, 

1237 fake.VSERVER_NAME, 

1238 fake.LIF_NAME) 

1239 

1240 self.client.send_request.assert_called_once_with( 

1241 'net-interface-create', lif_create_args) 

1242 

1243 @ddt.data((None, True), (fake.VLAN, True), (None, False), 

1244 (fake.VLAN, False)) 

1245 @ddt.unpack 

1246 def test_create_port_and_broadcast_domain(self, fake_vlan, 

1247 broadcast_domains_supported): 

1248 

1249 self.client.features.add_feature( 

1250 'BROADCAST_DOMAINS', broadcast_domains_supported) 

1251 

1252 mock_create_vlan = self.mock_object( 

1253 self.client, '_create_vlan') 

1254 mock_ensure_broadcast = self.mock_object( 

1255 self.client, '_ensure_broadcast_domain_for_port') 

1256 

1257 result = self.client.create_port_and_broadcast_domain( 

1258 fake.NODE_NAME, fake.PORT, fake_vlan, fake.MTU, fake.IPSPACE_NAME) 

1259 

1260 if fake_vlan: 

1261 mock_create_vlan.assert_called_once_with( 

1262 fake.NODE_NAME, fake.PORT, fake_vlan) 

1263 

1264 fake_home_port_name = ( 

1265 f'{fake.PORT}-{fake_vlan}' if fake_vlan else fake.PORT) 

1266 if broadcast_domains_supported: 

1267 mock_ensure_broadcast.assert_called_once_with( 

1268 fake.NODE_NAME, fake_home_port_name, fake.MTU, 

1269 ipspace=fake.IPSPACE_NAME) 

1270 

1271 self.assertEqual(fake_home_port_name, result) 

1272 

1273 def test_create_vlan(self): 

1274 

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

1276 

1277 vlan_create_args = { 

1278 'vlan-info': { 

1279 'parent-interface': fake.PORT, 

1280 'node': fake.NODE_NAME, 

1281 'vlanid': fake.VLAN 

1282 } 

1283 } 

1284 self.client._create_vlan(fake.NODE_NAME, fake.PORT, fake.VLAN) 

1285 

1286 self.client.send_request.assert_has_calls([ 

1287 mock.call('net-vlan-create', vlan_create_args)]) 

1288 

1289 def test_create_vlan_already_present(self): 

1290 

1291 self.mock_object(self.client, 

1292 'send_request', 

1293 self._mock_api_error(code=netapp_api.EDUPLICATEENTRY)) 

1294 

1295 vlan_create_args = { 

1296 'vlan-info': { 

1297 'parent-interface': fake.PORT, 

1298 'node': fake.NODE_NAME, 

1299 'vlanid': fake.VLAN 

1300 } 

1301 } 

1302 self.client._create_vlan(fake.NODE_NAME, fake.PORT, fake.VLAN) 

1303 

1304 self.client.send_request.assert_has_calls([ 

1305 mock.call('net-vlan-create', vlan_create_args)]) 

1306 self.assertEqual(1, client_cmode.LOG.debug.call_count) 

1307 

1308 def test_create_vlan_api_error(self): 

1309 

1310 self.mock_object(self.client, 'send_request', self._mock_api_error()) 

1311 

1312 self.assertRaises(exception.NetAppException, 

1313 self.client._create_vlan, 

1314 fake.NODE_NAME, 

1315 fake.PORT, 

1316 fake.VLAN) 

1317 

1318 def test_delete_vlan(self): 

1319 

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

1321 

1322 vlan_delete_args = { 

1323 'vlan-info': { 

1324 'parent-interface': fake.PORT, 

1325 'node': fake.NODE_NAME, 

1326 'vlanid': fake.VLAN 

1327 } 

1328 } 

1329 self.client.delete_vlan(fake.NODE_NAME, fake.PORT, fake.VLAN) 

1330 

1331 self.client.send_request.assert_has_calls([ 

1332 mock.call('net-vlan-delete', vlan_delete_args)]) 

1333 

1334 def test_delete_vlan_still_used(self): 

1335 

1336 self.mock_object(self.client, 

1337 'send_request', 

1338 self._mock_api_error(code=netapp_api.EAPIERROR, 

1339 message='Port already has a ' 

1340 'lif bound. ')) 

1341 

1342 vlan_delete_args = { 

1343 'vlan-info': { 

1344 'parent-interface': fake.PORT, 

1345 'node': fake.NODE_NAME, 

1346 'vlanid': fake.VLAN 

1347 } 

1348 } 

1349 self.client.delete_vlan(fake.NODE_NAME, fake.PORT, fake.VLAN) 

1350 

1351 self.client.send_request.assert_has_calls([ 

1352 mock.call('net-vlan-delete', vlan_delete_args)]) 

1353 self.assertEqual(1, client_cmode.LOG.debug.call_count) 

1354 

1355 def test_delete_vlan_api_error(self): 

1356 

1357 self.mock_object(self.client, 'send_request', self._mock_api_error()) 

1358 

1359 self.assertRaises(exception.NetAppException, 

1360 self.client.delete_vlan, 

1361 fake.NODE_NAME, 

1362 fake.PORT, 

1363 fake.VLAN) 

1364 

1365 @ddt.data(('10.10.10.0/24', '10.10.10.1', False), 

1366 ('fc00::/7', 'fe80::1', False), 

1367 ('0.0.0.0/0', '10.10.10.1', True), 

1368 ('::/0', 'fe80::1', True)) 

1369 @ddt.unpack 

1370 def test_create_route(self, subnet, gateway, omit_destination): 

1371 api_response = netapp_api.NaElement( 

1372 fake.NET_ROUTES_CREATE_RESPONSE) 

1373 expected_api_args = { 

1374 'destination': subnet, 

1375 'gateway': gateway, 

1376 'return-record': 'true', 

1377 } 

1378 self.mock_object( 

1379 self.client, 'send_request', mock.Mock(return_value=api_response)) 

1380 

1381 destination = None if omit_destination else subnet 

1382 self.client.create_route(gateway, destination=destination) 

1383 

1384 self.client.send_request.assert_called_once_with( 

1385 'net-routes-create', expected_api_args) 

1386 

1387 def test_create_route_duplicate(self): 

1388 self.mock_object(client_cmode.LOG, 'debug') 

1389 expected_api_args = { 

1390 'destination': fake.SUBNET, 

1391 'gateway': fake.GATEWAY, 

1392 'return-record': 'true', 

1393 } 

1394 self.mock_object( 

1395 self.client, 'send_request', 

1396 mock.Mock(side_effect=self._mock_api_error( 

1397 code=netapp_api.EAPIERROR, message='Duplicate route exists.'))) 

1398 

1399 self.client.create_route(fake.GATEWAY, destination=fake.SUBNET) 

1400 

1401 self.client.send_request.assert_called_once_with( 

1402 'net-routes-create', expected_api_args) 

1403 self.assertEqual(1, client_cmode.LOG.debug.call_count) 

1404 

1405 def test_create_route_api_error(self): 

1406 expected_api_args = { 

1407 'destination': fake.SUBNET, 

1408 'gateway': fake.GATEWAY, 

1409 'return-record': 'true', 

1410 } 

1411 self.mock_object( 

1412 self.client, 'send_request', 

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

1414 

1415 self.assertRaises(exception.NetAppException, 

1416 self.client.create_route, 

1417 fake.GATEWAY, destination=fake.SUBNET) 

1418 

1419 self.client.send_request.assert_called_once_with( 

1420 'net-routes-create', expected_api_args) 

1421 

1422 def test_create_route_without_gateway(self): 

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

1424 self.client.create_route(None, destination=fake.SUBNET) 

1425 self.assertFalse(self.client.send_request.called) 

1426 

1427 def test_ensure_broadcast_domain_for_port_domain_match(self): 

1428 

1429 port_info = { 

1430 'ipspace': fake.IPSPACE_NAME, 

1431 'broadcast-domain': fake.BROADCAST_DOMAIN, 

1432 } 

1433 self.mock_object(self.client, 

1434 '_get_broadcast_domain_for_port', 

1435 mock.Mock(return_value=port_info)) 

1436 self.mock_object(self.client, 

1437 '_broadcast_domain_exists', 

1438 mock.Mock(return_value=True)) 

1439 self.mock_object(self.client, '_create_broadcast_domain') 

1440 self.mock_object(self.client, '_modify_broadcast_domain') 

1441 self.mock_object(self.client, '_add_port_to_broadcast_domain') 

1442 

1443 self.client._ensure_broadcast_domain_for_port( 

1444 fake.NODE_NAME, fake.PORT, fake.MTU, ipspace=fake.IPSPACE_NAME) 

1445 

1446 self.client._get_broadcast_domain_for_port.assert_called_once_with( 

1447 fake.NODE_NAME, fake.PORT) 

1448 self.client._modify_broadcast_domain.assert_called_once_with( 

1449 fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME, fake.MTU) 

1450 self.assertFalse(self.client._broadcast_domain_exists.called) 

1451 self.assertFalse(self.client._create_broadcast_domain.called) 

1452 self.assertFalse(self.client._add_port_to_broadcast_domain.called) 

1453 

1454 @ddt.data(fake.IPSPACE_NAME, client_cmode.DEFAULT_IPSPACE) 

1455 def test_ensure_broadcast_domain_for_port_other_domain(self, ipspace): 

1456 

1457 port_info = { 

1458 'ipspace': ipspace, 

1459 'broadcast-domain': 'other_domain', 

1460 } 

1461 self.mock_object(self.client, 

1462 '_get_broadcast_domain_for_port', 

1463 mock.Mock(return_value=port_info)) 

1464 self.mock_object(self.client, 

1465 '_broadcast_domain_exists', 

1466 mock.Mock(return_value=True)) 

1467 self.mock_object(self.client, '_create_broadcast_domain') 

1468 self.mock_object(self.client, '_modify_broadcast_domain') 

1469 self.mock_object(self.client, '_remove_port_from_broadcast_domain') 

1470 self.mock_object(self.client, '_add_port_to_broadcast_domain') 

1471 

1472 self.client._ensure_broadcast_domain_for_port( 

1473 fake.NODE_NAME, fake.PORT, ipspace=fake.IPSPACE_NAME, mtu=fake.MTU) 

1474 

1475 self.client._get_broadcast_domain_for_port.assert_called_once_with( 

1476 fake.NODE_NAME, fake.PORT) 

1477 self.client._remove_port_from_broadcast_domain.assert_called_once_with( 

1478 fake.NODE_NAME, fake.PORT, 'other_domain', ipspace) 

1479 self.client._broadcast_domain_exists.assert_called_once_with( 

1480 fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME) 

1481 self.assertFalse(self.client._create_broadcast_domain.called) 

1482 self.client._modify_broadcast_domain.assert_called_once_with( 

1483 fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME, fake.MTU) 

1484 self.client._add_port_to_broadcast_domain.assert_called_once_with( 

1485 fake.NODE_NAME, fake.PORT, fake.BROADCAST_DOMAIN, 

1486 fake.IPSPACE_NAME) 

1487 

1488 def test_ensure_broadcast_domain_for_port_no_domain(self): 

1489 

1490 port_info = { 

1491 'ipspace': fake.IPSPACE_NAME, 

1492 'broadcast-domain': None, 

1493 } 

1494 self.mock_object(self.client, 

1495 '_get_broadcast_domain_for_port', 

1496 mock.Mock(return_value=port_info)) 

1497 self.mock_object(self.client, 

1498 '_broadcast_domain_exists', 

1499 mock.Mock(return_value=False)) 

1500 self.mock_object(self.client, '_create_broadcast_domain') 

1501 self.mock_object(self.client, '_modify_broadcast_domain') 

1502 self.mock_object(self.client, '_remove_port_from_broadcast_domain') 

1503 self.mock_object(self.client, '_add_port_to_broadcast_domain') 

1504 

1505 self.client._ensure_broadcast_domain_for_port( 

1506 fake.NODE_NAME, fake.PORT, ipspace=fake.IPSPACE_NAME, mtu=fake.MTU) 

1507 

1508 self.client._get_broadcast_domain_for_port.assert_called_once_with( 

1509 fake.NODE_NAME, fake.PORT) 

1510 self.assertFalse(self.client._remove_port_from_broadcast_domain.called) 

1511 self.client._broadcast_domain_exists.assert_called_once_with( 

1512 fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME) 

1513 self.client._create_broadcast_domain.assert_called_once_with( 

1514 fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME, fake.MTU) 

1515 self.assertFalse(self.client._modify_broadcast_domain.called) 

1516 self.client._add_port_to_broadcast_domain.assert_called_once_with( 

1517 fake.NODE_NAME, fake.PORT, fake.BROADCAST_DOMAIN, 

1518 fake.IPSPACE_NAME) 

1519 

1520 def test_get_broadcast_domain_for_port(self): 

1521 

1522 api_response = netapp_api.NaElement( 

1523 fake.NET_PORT_GET_ITER_BROADCAST_DOMAIN_RESPONSE) 

1524 self.mock_object(self.client, 

1525 'send_iter_request', 

1526 mock.Mock(return_value=api_response)) 

1527 

1528 net_port_get_iter_args = { 

1529 'query': { 

1530 'net-port-info': { 

1531 'node': fake.NODE_NAME, 

1532 'port': fake.PORT, 

1533 }, 

1534 }, 

1535 'desired-attributes': { 

1536 'net-port-info': { 

1537 'broadcast-domain': None, 

1538 'ipspace': None, 

1539 }, 

1540 }, 

1541 } 

1542 result = self.client._get_broadcast_domain_for_port(fake.NODE_NAME, 

1543 fake.PORT) 

1544 

1545 expected = { 

1546 'broadcast-domain': fake.BROADCAST_DOMAIN, 

1547 'ipspace': fake.IPSPACE_NAME, 

1548 } 

1549 self.client.send_iter_request.assert_has_calls([ 

1550 mock.call('net-port-get-iter', net_port_get_iter_args)]) 

1551 self.assertEqual(expected, result) 

1552 

1553 def test_get_broadcast_domain_for_port_port_not_found(self): 

1554 

1555 api_response = netapp_api.NaElement( 

1556 fake.NO_RECORDS_RESPONSE) 

1557 self.mock_object(self.client, 

1558 'send_iter_request', 

1559 mock.Mock(return_value=api_response)) 

1560 

1561 self.assertRaises(exception.NetAppException, 

1562 self.client._get_broadcast_domain_for_port, 

1563 fake.NODE_NAME, 

1564 fake.PORT) 

1565 

1566 def test_get_broadcast_domain_for_port_domain_not_found(self): 

1567 

1568 api_response = netapp_api.NaElement( 

1569 fake.NET_PORT_GET_ITER_BROADCAST_DOMAIN_MISSING_RESPONSE) 

1570 self.mock_object(self.client, 

1571 'send_iter_request', 

1572 mock.Mock(return_value=api_response)) 

1573 

1574 result = self.client._get_broadcast_domain_for_port(fake.NODE_NAME, 

1575 fake.PORT) 

1576 

1577 expected = { 

1578 'broadcast-domain': None, 

1579 'ipspace': fake.IPSPACE_NAME, 

1580 } 

1581 self.assertEqual(expected, result) 

1582 

1583 def test_broadcast_domain_exists(self): 

1584 

1585 api_response = netapp_api.NaElement( 

1586 fake.NET_PORT_BROADCAST_DOMAIN_GET_ITER_RESPONSE) 

1587 self.mock_object(self.client, 

1588 'send_iter_request', 

1589 mock.Mock(return_value=api_response)) 

1590 

1591 result = self.client._broadcast_domain_exists(fake.BROADCAST_DOMAIN, 

1592 fake.IPSPACE_NAME) 

1593 

1594 net_port_broadcast_domain_get_iter_args = { 

1595 'query': { 

1596 'net-port-broadcast-domain-info': { 

1597 'ipspace': fake.IPSPACE_NAME, 

1598 'broadcast-domain': fake.BROADCAST_DOMAIN, 

1599 }, 

1600 }, 

1601 'desired-attributes': { 

1602 'net-port-broadcast-domain-info': None, 

1603 }, 

1604 } 

1605 self.client.send_iter_request.assert_has_calls([ 

1606 mock.call('net-port-broadcast-domain-get-iter', 

1607 net_port_broadcast_domain_get_iter_args)]) 

1608 self.assertTrue(result) 

1609 

1610 def test_broadcast_domain_exists_not_found(self): 

1611 

1612 api_response = netapp_api.NaElement( 

1613 fake.NO_RECORDS_RESPONSE) 

1614 self.mock_object(self.client, 

1615 'send_request', 

1616 mock.Mock(return_value=api_response)) 

1617 

1618 result = self.client._broadcast_domain_exists(fake.BROADCAST_DOMAIN, 

1619 fake.IPSPACE_NAME) 

1620 

1621 self.assertFalse(result) 

1622 

1623 def test_create_broadcast_domain(self): 

1624 

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

1626 

1627 result = self.client._create_broadcast_domain(fake.BROADCAST_DOMAIN, 

1628 fake.IPSPACE_NAME, 

1629 fake.MTU) 

1630 

1631 net_port_broadcast_domain_create_args = { 

1632 'ipspace': fake.IPSPACE_NAME, 

1633 'broadcast-domain': fake.BROADCAST_DOMAIN, 

1634 'mtu': fake.MTU, 

1635 } 

1636 self.assertIsNone(result) 

1637 self.client.send_request.assert_has_calls([ 

1638 mock.call('net-port-broadcast-domain-create', 

1639 net_port_broadcast_domain_create_args)]) 

1640 

1641 def test_modify_broadcast_domain(self): 

1642 

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

1644 

1645 result = self.client._modify_broadcast_domain(fake.BROADCAST_DOMAIN, 

1646 fake.IPSPACE_NAME, 

1647 fake.MTU) 

1648 

1649 net_port_broadcast_domain_modify_args = { 

1650 'ipspace': fake.IPSPACE_NAME, 

1651 'broadcast-domain': fake.BROADCAST_DOMAIN, 

1652 'mtu': fake.MTU, 

1653 } 

1654 self.assertIsNone(result) 

1655 self.client.send_request.assert_called_once_with( 

1656 'net-port-broadcast-domain-modify', 

1657 net_port_broadcast_domain_modify_args) 

1658 

1659 def test_delete_broadcast_domain(self): 

1660 

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

1662 

1663 result = self.client._delete_broadcast_domain(fake.BROADCAST_DOMAIN, 

1664 fake.IPSPACE_NAME) 

1665 

1666 net_port_broadcast_domain_delete_args = { 

1667 'ipspace': fake.IPSPACE_NAME, 

1668 'broadcast-domain': fake.BROADCAST_DOMAIN, 

1669 } 

1670 self.assertIsNone(result) 

1671 self.client.send_request.assert_has_calls([ 

1672 mock.call('net-port-broadcast-domain-destroy', 

1673 net_port_broadcast_domain_delete_args)]) 

1674 

1675 def test_delete_broadcast_domains_for_ipspace_not_found(self): 

1676 

1677 self.mock_object(self.client, 

1678 'get_ipspaces', 

1679 mock.Mock(return_value=[])) 

1680 self.mock_object(self.client, '_delete_broadcast_domain') 

1681 

1682 self.client._delete_broadcast_domains_for_ipspace(fake.IPSPACE_NAME) 

1683 

1684 self.client.get_ipspaces.assert_called_once_with( 

1685 ipspace_name=fake.IPSPACE_NAME) 

1686 self.assertFalse(self.client._delete_broadcast_domain.called) 

1687 

1688 def test_delete_broadcast_domains_for_ipspace(self): 

1689 

1690 self.mock_object(self.client, 

1691 'get_ipspaces', 

1692 mock.Mock(return_value=fake.IPSPACES)) 

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

1694 

1695 self.client._delete_broadcast_domains_for_ipspace(fake.IPSPACE_NAME) 

1696 

1697 self.client.get_ipspaces.assert_called_once_with( 

1698 ipspace_name=fake.IPSPACE_NAME) 

1699 self.client._delete_broadcast_domain.assert_called_once_with( 

1700 fake.IPSPACES[0]['broadcast-domains'][0], fake.IPSPACE_NAME) 

1701 

1702 def test_add_port_to_broadcast_domain(self): 

1703 

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

1705 

1706 add_port_to_broadcast_domain_args = { 

1707 'ipspace': fake.IPSPACE_NAME, 

1708 'broadcast-domain': fake.BROADCAST_DOMAIN, 

1709 'ports': { 

1710 'net-qualified-port-name': ':'.join([fake.NODE_NAME, 

1711 fake.VLAN_PORT]) 

1712 } 

1713 } 

1714 result = self.client._add_port_to_broadcast_domain( 

1715 fake.NODE_NAME, fake.VLAN_PORT, fake.BROADCAST_DOMAIN, 

1716 fake.IPSPACE_NAME) 

1717 

1718 self.assertIsNone(result) 

1719 self.client.send_request.assert_has_calls([ 

1720 mock.call('net-port-broadcast-domain-add-ports', 

1721 add_port_to_broadcast_domain_args)]) 

1722 

1723 def test_add_port_to_broadcast_domain_already_present(self): 

1724 

1725 self.mock_object(self.client, 'send_request', self._mock_api_error( 

1726 code=netapp_api. 

1727 E_VIFMGR_PORT_ALREADY_ASSIGNED_TO_BROADCAST_DOMAIN)) 

1728 

1729 result = self.client._add_port_to_broadcast_domain( 

1730 fake.NODE_NAME, fake.VLAN_PORT, fake.BROADCAST_DOMAIN, 

1731 fake.IPSPACE_NAME) 

1732 

1733 self.assertIsNone(result) 

1734 

1735 def test_add_port_to_broadcast_domain_api_error(self): 

1736 

1737 self.mock_object(self.client, 'send_request', self._mock_api_error()) 

1738 

1739 self.assertRaises(exception.NetAppException, 

1740 self.client._add_port_to_broadcast_domain, 

1741 fake.NODE_NAME, 

1742 fake.VLAN_PORT, 

1743 fake.BROADCAST_DOMAIN, 

1744 fake.IPSPACE_NAME) 

1745 

1746 def test_remove_port_from_broadcast_domain(self): 

1747 

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

1749 

1750 result = self.client._remove_port_from_broadcast_domain( 

1751 fake.NODE_NAME, fake.VLAN_PORT, fake.BROADCAST_DOMAIN, 

1752 fake.IPSPACE_NAME) 

1753 

1754 net_port_broadcast_domain_remove_ports_args = { 

1755 'ipspace': fake.IPSPACE_NAME, 

1756 'broadcast-domain': fake.BROADCAST_DOMAIN, 

1757 'ports': { 

1758 'net-qualified-port-name': ':'.join([fake.NODE_NAME, 

1759 fake.VLAN_PORT]) 

1760 } 

1761 } 

1762 self.assertIsNone(result) 

1763 self.client.send_request.assert_has_calls([ 

1764 mock.call('net-port-broadcast-domain-remove-ports', 

1765 net_port_broadcast_domain_remove_ports_args)]) 

1766 

1767 def test_network_interface_exists(self): 

1768 

1769 api_response = netapp_api.NaElement( 

1770 fake.NET_INTERFACE_GET_ONE_RESPONSE) 

1771 self.mock_object(self.client, 

1772 'send_iter_request', 

1773 mock.Mock(return_value=api_response)) 

1774 

1775 net_interface_get_args = { 

1776 'query': { 

1777 'net-interface-info': { 

1778 'address': fake.IP_ADDRESS, 

1779 'home-node': fake.NODE_NAME, 

1780 'home-port': fake.VLAN_PORT, 

1781 'netmask': fake.NETMASK, 

1782 'vserver': fake.VSERVER_NAME} 

1783 }, 

1784 'desired-attributes': { 

1785 'net-interface-info': { 

1786 'interface-name': None, 

1787 } 

1788 } 

1789 } 

1790 result = self.client.network_interface_exists( 

1791 fake.VSERVER_NAME, fake.NODE_NAME, fake.PORT, fake.IP_ADDRESS, 

1792 fake.NETMASK, fake.VLAN) 

1793 

1794 self.client.send_iter_request.assert_has_calls([ 

1795 mock.call('net-interface-get-iter', net_interface_get_args)]) 

1796 self.assertTrue(result) 

1797 

1798 def test_network_interface_exists_not_found(self): 

1799 

1800 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

1801 self.mock_object(self.client, 

1802 'send_iter_request', 

1803 mock.Mock(return_value=api_response)) 

1804 

1805 net_interface_get_args = { 

1806 'query': { 

1807 'net-interface-info': { 

1808 'address': fake.IP_ADDRESS, 

1809 'home-node': fake.NODE_NAME, 

1810 'home-port': fake.PORT, 

1811 'netmask': fake.NETMASK, 

1812 'vserver': fake.VSERVER_NAME} 

1813 }, 

1814 'desired-attributes': { 

1815 'net-interface-info': { 

1816 'interface-name': None, 

1817 } 

1818 } 

1819 } 

1820 result = self.client.network_interface_exists( 

1821 fake.VSERVER_NAME, fake.NODE_NAME, fake.PORT, fake.IP_ADDRESS, 

1822 fake.NETMASK, None) 

1823 self.client.send_iter_request.assert_has_calls([ 

1824 mock.call('net-interface-get-iter', net_interface_get_args)]) 

1825 self.assertFalse(result) 

1826 

1827 def test_list_network_interfaces(self): 

1828 

1829 api_response = netapp_api.NaElement( 

1830 fake.NET_INTERFACE_GET_ITER_RESPONSE) 

1831 self.mock_object(self.client, 

1832 'send_iter_request', 

1833 mock.Mock(return_value=api_response)) 

1834 

1835 net_interface_get_args = { 

1836 'desired-attributes': { 

1837 'net-interface-info': { 

1838 'interface-name': None, 

1839 } 

1840 } 

1841 } 

1842 

1843 result = self.client.list_network_interfaces() 

1844 

1845 self.client.send_iter_request.assert_has_calls([ 

1846 mock.call('net-interface-get-iter', net_interface_get_args)]) 

1847 self.assertSequenceEqual(fake.LIF_NAMES, result) 

1848 

1849 def test_list_network_interfaces_not_found(self): 

1850 

1851 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

1852 self.mock_object(self.client, 

1853 'send_request', 

1854 mock.Mock(return_value=api_response)) 

1855 

1856 result = self.client.list_network_interfaces() 

1857 

1858 self.assertListEqual([], result) 

1859 

1860 def test_get_network_interfaces(self): 

1861 

1862 api_response = netapp_api.NaElement( 

1863 fake.NET_INTERFACE_GET_ITER_RESPONSE) 

1864 self.mock_object(self.client, 

1865 'send_iter_request', 

1866 mock.Mock(return_value=api_response)) 

1867 

1868 result = self.client.get_network_interfaces() 

1869 

1870 self.client.send_iter_request.assert_has_calls([ 

1871 mock.call('net-interface-get-iter', None)]) 

1872 self.assertSequenceEqual(fake.LIFS, result) 

1873 

1874 def test_get_network_interfaces_filtered_by_protocol(self): 

1875 

1876 api_response = netapp_api.NaElement( 

1877 fake.NET_INTERFACE_GET_ITER_RESPONSE_NFS) 

1878 self.mock_object(self.client, 

1879 'send_iter_request', 

1880 mock.Mock(return_value=api_response)) 

1881 

1882 result = self.client.get_network_interfaces(protocols=['NFS']) 

1883 

1884 net_interface_get_args = { 

1885 'query': { 

1886 'net-interface-info': { 

1887 'data-protocols': { 

1888 'data-protocol': 'nfs', 

1889 } 

1890 } 

1891 } 

1892 } 

1893 

1894 self.client.send_iter_request.assert_has_calls([ 

1895 mock.call('net-interface-get-iter', net_interface_get_args)]) 

1896 self.assertListEqual(fake.NFS_LIFS, result) 

1897 

1898 def test_get_network_interfaces_not_found(self): 

1899 

1900 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

1901 self.mock_object(self.client, 

1902 'send_iter_request', 

1903 mock.Mock(return_value=api_response)) 

1904 

1905 result = self.client.get_network_interfaces() 

1906 

1907 self.client.send_iter_request.assert_has_calls([ 

1908 mock.call('net-interface-get-iter', None)]) 

1909 self.assertListEqual([], result) 

1910 

1911 def test_disable_network_interface(self): 

1912 interface_name = fake.NETWORK_INTERFACES[0]['interface-name'] 

1913 vserver_name = fake.VSERVER_NAME 

1914 expected_api_args = { 

1915 'administrative-status': 'down', 

1916 'interface-name': interface_name, 

1917 'vserver': vserver_name, 

1918 } 

1919 

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

1921 

1922 self.client.disable_network_interface(vserver_name, interface_name) 

1923 

1924 self.client.send_request.assert_called_once_with( 

1925 'net-interface-modify', expected_api_args) 

1926 

1927 def test_delete_network_interface(self): 

1928 interface_name = fake.NETWORK_INTERFACES[0]['interface-name'] 

1929 vserver_name = fake.VSERVER_NAME 

1930 expected_api_args = { 

1931 'interface-name': interface_name, 

1932 'vserver': vserver_name, 

1933 } 

1934 

1935 self.mock_object(self.client, 'disable_network_interface') 

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

1937 

1938 self.client.delete_network_interface(vserver_name, interface_name) 

1939 

1940 self.client.disable_network_interface.assert_called_once_with( 

1941 vserver_name, interface_name) 

1942 self.client.send_request.assert_called_once_with( 

1943 'net-interface-delete', expected_api_args) 

1944 

1945 def test_get_ipspaces(self): 

1946 

1947 self.client.features.add_feature('IPSPACES') 

1948 api_response = netapp_api.NaElement( 

1949 fake.NET_IPSPACES_GET_ITER_RESPONSE) 

1950 self.mock_object(self.client, 

1951 'send_iter_request', 

1952 mock.Mock(return_value=api_response)) 

1953 

1954 result = self.client.get_ipspaces(ipspace_name=fake.IPSPACE_NAME) 

1955 

1956 net_ipspaces_get_iter_args = { 

1957 'query': { 

1958 'net-ipspaces-info': { 

1959 'ipspace': fake.IPSPACE_NAME, 

1960 }, 

1961 }, 

1962 } 

1963 self.client.send_iter_request.assert_has_calls([ 

1964 mock.call('net-ipspaces-get-iter', net_ipspaces_get_iter_args)]) 

1965 self.assertEqual(fake.IPSPACES, result) 

1966 

1967 def test_get_ipspaces_not_found(self): 

1968 

1969 self.client.features.add_feature('IPSPACES') 

1970 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

1971 self.mock_object(self.client, 

1972 'send_iter_request', 

1973 mock.Mock(return_value=api_response)) 

1974 

1975 result = self.client.get_ipspaces() 

1976 

1977 net_ipspaces_get_iter_args = {} 

1978 self.client.send_iter_request.assert_has_calls([ 

1979 mock.call('net-ipspaces-get-iter', net_ipspaces_get_iter_args)]) 

1980 self.assertEqual([], result) 

1981 

1982 def test_get_ipspaces_not_supported(self): 

1983 

1984 self.mock_object(self.client, 'send_iter_request') 

1985 

1986 result = self.client.get_ipspaces() 

1987 

1988 self.assertFalse(self.client.send_iter_request.called) 

1989 self.assertEqual([], result) 

1990 

1991 @ddt.data((fake.NET_IPSPACES_GET_ITER_RESPONSE, True), 

1992 (fake.NO_RECORDS_RESPONSE, False)) 

1993 @ddt.unpack 

1994 def test_ipspace_exists(self, api_response, expected): 

1995 

1996 self.client.features.add_feature('IPSPACES') 

1997 api_response = netapp_api.NaElement(api_response) 

1998 self.mock_object(self.client, 

1999 'send_iter_request', 

2000 mock.Mock(return_value=api_response)) 

2001 

2002 result = self.client.ipspace_exists(fake.IPSPACE_NAME) 

2003 

2004 net_ipspaces_get_iter_args = { 

2005 'query': { 

2006 'net-ipspaces-info': { 

2007 'ipspace': fake.IPSPACE_NAME, 

2008 }, 

2009 }, 

2010 'desired-attributes': { 

2011 'net-ipspaces-info': { 

2012 'ipspace': None, 

2013 }, 

2014 }, 

2015 } 

2016 self.client.send_iter_request.assert_has_calls([ 

2017 mock.call('net-ipspaces-get-iter', net_ipspaces_get_iter_args)]) 

2018 self.assertEqual(expected, result) 

2019 

2020 def test_ipspace_exists_not_supported(self): 

2021 

2022 result = self.client.ipspace_exists(fake.IPSPACE_NAME) 

2023 

2024 self.assertFalse(result) 

2025 

2026 def test_create_ipspace(self): 

2027 

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

2029 

2030 self.client.create_ipspace(fake.IPSPACE_NAME) 

2031 

2032 net_ipspaces_create_args = {'ipspace': fake.IPSPACE_NAME} 

2033 self.client.send_request.assert_has_calls([ 

2034 mock.call('net-ipspaces-create', net_ipspaces_create_args)]) 

2035 

2036 def test_delete_ipspace(self): 

2037 

2038 self.client.features.add_feature('IPSPACES') 

2039 mock_ipspace_has_data_vservers = self.mock_object( 

2040 self.client, 'ipspace_has_data_vservers', 

2041 mock.Mock(return_value=False)) 

2042 

2043 mock_delete_broadcast_domains_for_ipspace = self.mock_object( 

2044 self.client, '_delete_broadcast_domains_for_ipspace') 

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

2046 

2047 self.client.delete_ipspace(fake.IPSPACE_NAME) 

2048 

2049 net_ipspaces_destroy_args = {'ipspace': fake.IPSPACE_NAME} 

2050 mock_ipspace_has_data_vservers.assert_called_once_with( 

2051 fake.IPSPACE_NAME) 

2052 mock_delete_broadcast_domains_for_ipspace.assert_called_once_with( 

2053 fake.IPSPACE_NAME) 

2054 self.client.send_request.assert_has_calls([ 

2055 mock.call('net-ipspaces-destroy', net_ipspaces_destroy_args)]) 

2056 

2057 def test_get_ipspace_name_for_vlan_port(self): 

2058 self.client.features.add_feature('IPSPACES') 

2059 api_response = netapp_api.NaElement(fake.NET_PORT_GET_RESPONSE) 

2060 self.mock_object(self.client, 

2061 'send_request', 

2062 mock.Mock(return_value=api_response)) 

2063 

2064 ipspace = self.client.get_ipspace_name_for_vlan_port( 

2065 fake.NODE_NAME, fake.PORT, fake.VLAN) 

2066 

2067 port = '%(port)s-%(id)s' % {'port': fake.PORT, 'id': fake.VLAN} 

2068 self.client.send_request.assert_called_once_with( 

2069 'net-port-get', 

2070 {'node': fake.NODE_NAME, 'port': port}) 

2071 self.assertEqual(fake.IPSPACE_NAME, ipspace) 

2072 

2073 def test_get_ipspace_name_for_vlan_port_no_ipspace_feature(self): 

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

2075 

2076 ipspace = self.client.get_ipspace_name_for_vlan_port( 

2077 fake.NODE_NAME, fake.PORT, fake.VLAN) 

2078 

2079 self.client.send_request.assert_not_called() 

2080 self.assertIsNone(ipspace) 

2081 

2082 def test_get_ipspace_name_for_vlan_port_no_ipspace_found(self): 

2083 self.client.features.add_feature('IPSPACES') 

2084 self.mock_object( 

2085 self.client, 

2086 'send_request', 

2087 self._mock_api_error(code=netapp_api.EOBJECTNOTFOUND)) 

2088 

2089 ipspace = self.client.get_ipspace_name_for_vlan_port( 

2090 fake.NODE_NAME, fake.PORT, fake.VLAN) 

2091 

2092 self.assertIsNone(ipspace) 

2093 

2094 def test_get_ipspace_name_for_vlan_port_no_vlan(self): 

2095 self.client.features.add_feature('IPSPACES') 

2096 api_response = netapp_api.NaElement(fake.NET_PORT_GET_RESPONSE_NO_VLAN) 

2097 self.mock_object(self.client, 

2098 'send_request', 

2099 mock.Mock(return_value=api_response)) 

2100 

2101 ipspace = self.client.get_ipspace_name_for_vlan_port( 

2102 fake.NODE_NAME, fake.PORT, None) 

2103 

2104 self.client.send_request.assert_called_once_with( 

2105 'net-port-get', 

2106 {'node': fake.NODE_NAME, 'port': fake.PORT}) 

2107 self.assertEqual(fake.IPSPACE_NAME, ipspace) 

2108 

2109 def test_get_ipspace_name_for_vlan_port_raises_api_error(self): 

2110 self.client.features.add_feature('IPSPACES') 

2111 self.mock_object(self.client, 

2112 'send_request', 

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

2114 

2115 self.assertRaises(netapp_api.NaApiError, 

2116 self.client.get_ipspace_name_for_vlan_port, 

2117 fake.NODE_NAME, fake.VLAN_PORT, None) 

2118 

2119 def test_add_vserver_to_ipspace(self): 

2120 

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

2122 

2123 self.client.add_vserver_to_ipspace(fake.IPSPACE_NAME, 

2124 fake.VSERVER_NAME) 

2125 

2126 net_ipspaces_assign_vserver_args = { 

2127 'ipspace': fake.IPSPACE_NAME, 

2128 'vserver': fake.VSERVER_NAME 

2129 } 

2130 self.client.send_request.assert_has_calls([ 

2131 mock.call('net-ipspaces-assign-vserver', 

2132 net_ipspaces_assign_vserver_args)]) 

2133 

2134 def test_get_node_for_aggregate(self): 

2135 

2136 api_response = netapp_api.NaElement( 

2137 fake.AGGR_GET_NODE_RESPONSE).get_child_by_name( 

2138 'attributes-list').get_children() 

2139 self.mock_object(self.client, 

2140 '_get_aggregates', 

2141 mock.Mock(return_value=api_response)) 

2142 

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

2144 

2145 desired_attributes = { 

2146 'aggr-attributes': { 

2147 'aggregate-name': None, 

2148 'aggr-ownership-attributes': { 

2149 'home-name': None, 

2150 }, 

2151 }, 

2152 } 

2153 

2154 self.client._get_aggregates.assert_has_calls([ 

2155 mock.call( 

2156 aggregate_names=[fake.SHARE_AGGREGATE_NAME], 

2157 desired_attributes=desired_attributes)]) 

2158 

2159 self.assertEqual(fake.NODE_NAME, result) 

2160 

2161 def test_get_node_for_aggregate_none_requested(self): 

2162 

2163 result = self.client.get_node_for_aggregate(None) 

2164 

2165 self.assertIsNone(result) 

2166 

2167 def test_get_node_for_aggregate_api_not_found(self): 

2168 

2169 self.mock_object(self.client, 

2170 'send_iter_request', 

2171 mock.Mock(side_effect=self._mock_api_error( 

2172 netapp_api.EAPINOTFOUND))) 

2173 

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

2175 

2176 self.assertIsNone(result) 

2177 

2178 def test_get_node_for_aggregate_api_error(self): 

2179 

2180 self.mock_object(self.client, 

2181 'send_iter_request', 

2182 self._mock_api_error()) 

2183 

2184 self.assertRaises(netapp_api.NaApiError, 

2185 self.client.get_node_for_aggregate, 

2186 fake.SHARE_AGGREGATE_NAME) 

2187 

2188 def test_get_node_for_aggregate_not_found(self): 

2189 

2190 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

2191 self.mock_object(self.client, 

2192 'send_iter_request', 

2193 mock.Mock(return_value=api_response)) 

2194 

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

2196 

2197 self.assertIsNone(result) 

2198 

2199 def test_get_cluster_aggregate_capacities(self): 

2200 

2201 api_response = netapp_api.NaElement( 

2202 fake.AGGR_GET_SPACE_RESPONSE).get_child_by_name( 

2203 'attributes-list').get_children() 

2204 self.mock_object(self.client, 

2205 '_get_aggregates', 

2206 mock.Mock(return_value=api_response)) 

2207 

2208 result = self.client.get_cluster_aggregate_capacities( 

2209 fake.SHARE_AGGREGATE_NAMES) 

2210 

2211 desired_attributes = { 

2212 'aggr-attributes': { 

2213 'aggregate-name': None, 

2214 'aggr-space-attributes': { 

2215 'size-available': None, 

2216 'size-total': None, 

2217 'size-used': None, 

2218 } 

2219 } 

2220 } 

2221 

2222 self.client._get_aggregates.assert_has_calls([ 

2223 mock.call( 

2224 aggregate_names=fake.SHARE_AGGREGATE_NAMES, 

2225 desired_attributes=desired_attributes)]) 

2226 

2227 expected = { 

2228 fake.SHARE_AGGREGATE_NAMES[0]: { 

2229 'available': 45670400, 

2230 'total': 943718400, 

2231 'used': 898048000, 

2232 }, 

2233 fake.SHARE_AGGREGATE_NAMES[1]: { 

2234 'available': 4267659264, 

2235 'total': 7549747200, 

2236 'used': 3282087936, 

2237 }, 

2238 } 

2239 self.assertDictEqual(expected, result) 

2240 

2241 def test_get_cluster_aggregate_capacities_not_found(self): 

2242 

2243 api_response = netapp_api.NaElement('none').get_children() 

2244 self.mock_object(self.client, 

2245 '_get_aggregates', 

2246 mock.Mock(return_value=api_response)) 

2247 

2248 result = self.client.get_cluster_aggregate_capacities( 

2249 fake.SHARE_AGGREGATE_NAMES) 

2250 

2251 self.assertEqual({}, result) 

2252 

2253 def test_get_cluster_aggregate_capacities_none_requested(self): 

2254 

2255 result = self.client.get_cluster_aggregate_capacities([]) 

2256 

2257 self.assertEqual({}, result) 

2258 

2259 def test_get_vserver_aggregate_capacities(self): 

2260 

2261 api_response = netapp_api.NaElement(fake.VSERVER_GET_RESPONSE) 

2262 self.mock_object(self.vserver_client, 

2263 'send_request', 

2264 mock.Mock(return_value=api_response)) 

2265 

2266 result = self.vserver_client.get_vserver_aggregate_capacities() 

2267 

2268 vserver_args = { 

2269 'desired-attributes': { 

2270 'vserver-info': { 

2271 'vserver-name': None, 

2272 'vserver-aggr-info-list': { 

2273 'vserver-aggr-info': { 

2274 'aggr-name': None, 

2275 'aggr-availsize': None 

2276 } 

2277 } 

2278 } 

2279 } 

2280 } 

2281 

2282 self.vserver_client.send_request.assert_has_calls([ 

2283 mock.call('vserver-get', vserver_args)]) 

2284 self.assertDictEqual(fake.VSERVER_AGGREGATES, result) 

2285 

2286 def test_get_vserver_aggregate_capacities_partial_request(self): 

2287 

2288 api_response = netapp_api.NaElement(fake.VSERVER_GET_RESPONSE) 

2289 self.mock_object(self.vserver_client, 

2290 'send_request', 

2291 mock.Mock(return_value=api_response)) 

2292 

2293 result = self.vserver_client.get_vserver_aggregate_capacities( 

2294 fake.SHARE_AGGREGATE_NAMES[0]) 

2295 

2296 expected = {fake.SHARE_AGGREGATE_NAMES[0]: 

2297 fake.VSERVER_AGGREGATES[fake.SHARE_AGGREGATE_NAMES[0]]} 

2298 self.assertDictEqual(expected, result) 

2299 

2300 def test_get_vserver_aggregate_capacities_aggregate_not_found(self): 

2301 

2302 api_response = netapp_api.NaElement( 

2303 fake.VSERVER_GET_RESPONSE_NO_AGGREGATES) 

2304 self.mock_object(self.vserver_client, 

2305 'send_request', 

2306 mock.Mock(return_value=api_response)) 

2307 

2308 result = self.vserver_client.get_vserver_aggregate_capacities() 

2309 

2310 self.assertDictEqual({}, result) 

2311 self.assertEqual(1, client_cmode.LOG.warning.call_count) 

2312 

2313 def test_get_vserver_aggregate_capacities_vserver_not_found(self): 

2314 

2315 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

2316 self.mock_object(self.vserver_client, 

2317 'send_request', 

2318 mock.Mock(return_value=api_response)) 

2319 

2320 self.assertRaises(exception.NetAppException, 

2321 self.vserver_client.get_vserver_aggregate_capacities) 

2322 

2323 def test_get_vserver_aggregate_capacities_none_requested(self): 

2324 

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

2326 

2327 self.assertEqual({}, result) 

2328 

2329 def test_get_aggregates(self): 

2330 

2331 api_response = netapp_api.NaElement(fake.AGGR_GET_ITER_RESPONSE) 

2332 self.mock_object(self.client, 

2333 'send_iter_request', 

2334 mock.Mock(return_value=api_response)) 

2335 

2336 result = self.client._get_aggregates() 

2337 

2338 self.client.send_iter_request.assert_has_calls([ 

2339 mock.call('aggr-get-iter', {})]) 

2340 self.assertListEqual( 

2341 [aggr.to_string() for aggr in api_response.get_child_by_name( 

2342 'attributes-list').get_children()], 

2343 [aggr.to_string() for aggr in result]) 

2344 

2345 def test_get_aggregates_with_filters(self): 

2346 

2347 api_response = netapp_api.NaElement(fake.AGGR_GET_SPACE_RESPONSE) 

2348 self.mock_object(self.client, 

2349 'send_iter_request', 

2350 mock.Mock(return_value=api_response)) 

2351 

2352 desired_attributes = { 

2353 'aggr-attributes': { 

2354 'aggregate-name': None, 

2355 'aggr-space-attributes': { 

2356 'size-total': None, 

2357 'size-available': None, 

2358 } 

2359 } 

2360 } 

2361 

2362 result = self.client._get_aggregates( 

2363 aggregate_names=fake.SHARE_AGGREGATE_NAMES, 

2364 desired_attributes=desired_attributes) 

2365 

2366 aggr_get_iter_args = { 

2367 'query': { 

2368 'aggr-attributes': { 

2369 'aggregate-name': '|'.join(fake.SHARE_AGGREGATE_NAMES), 

2370 } 

2371 }, 

2372 'desired-attributes': desired_attributes 

2373 } 

2374 

2375 self.client.send_iter_request.assert_has_calls([ 

2376 mock.call('aggr-get-iter', aggr_get_iter_args)]) 

2377 self.assertListEqual( 

2378 [aggr.to_string() for aggr in api_response.get_child_by_name( 

2379 'attributes-list').get_children()], 

2380 [aggr.to_string() for aggr in result]) 

2381 

2382 def test_get_aggregates_not_found(self): 

2383 

2384 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

2385 self.mock_object(self.client, 

2386 'send_iter_request', 

2387 mock.Mock(return_value=api_response)) 

2388 

2389 result = self.client._get_aggregates() 

2390 

2391 self.client.send_iter_request.assert_has_calls([ 

2392 mock.call('aggr-get-iter', {})]) 

2393 self.assertListEqual([], result) 

2394 

2395 def test_get_performance_instance_uuids(self): 

2396 

2397 api_response = netapp_api.NaElement( 

2398 fake.PERF_OBJECT_INSTANCE_LIST_INFO_ITER_RESPONSE) 

2399 self.mock_object(self.client, 

2400 'send_request', 

2401 mock.Mock(return_value=api_response)) 

2402 

2403 result = self.client.get_performance_instance_uuids( 

2404 'system', fake.NODE_NAME) 

2405 

2406 expected = [fake.NODE_NAME + ':kernel:system'] 

2407 self.assertEqual(expected, result) 

2408 

2409 perf_object_instance_list_info_iter_args = { 

2410 'objectname': 'system', 

2411 'query': { 

2412 'instance-info': { 

2413 'uuid': fake.NODE_NAME + ':*', 

2414 } 

2415 } 

2416 } 

2417 self.client.send_request.assert_called_once_with( 

2418 'perf-object-instance-list-info-iter', 

2419 perf_object_instance_list_info_iter_args) 

2420 

2421 def test_get_performance_counter_info(self): 

2422 

2423 api_response = netapp_api.NaElement( 

2424 fake.PERF_OBJECT_COUNTER_LIST_INFO_WAFL_RESPONSE) 

2425 self.mock_object(self.client, 

2426 'send_request', 

2427 mock.Mock(return_value=api_response)) 

2428 

2429 result = self.client.get_performance_counter_info('wafl', 

2430 'cp_phase_times') 

2431 

2432 expected = { 

2433 'name': 'cp_phase_times', 

2434 'base-counter': 'total_cp_msecs', 

2435 'labels': fake.PERF_OBJECT_COUNTER_TOTAL_CP_MSECS_LABELS, 

2436 } 

2437 self.assertEqual(expected, result) 

2438 

2439 perf_object_counter_list_info_args = {'objectname': 'wafl'} 

2440 self.client.send_request.assert_called_once_with( 

2441 'perf-object-counter-list-info', 

2442 perf_object_counter_list_info_args) 

2443 

2444 def test_get_performance_counter_info_not_found(self): 

2445 

2446 api_response = netapp_api.NaElement( 

2447 fake.PERF_OBJECT_COUNTER_LIST_INFO_WAFL_RESPONSE) 

2448 self.mock_object(self.client, 

2449 'send_request', 

2450 mock.Mock(return_value=api_response)) 

2451 

2452 self.assertRaises(exception.NotFound, 

2453 self.client.get_performance_counter_info, 

2454 'wafl', 

2455 'invalid') 

2456 

2457 def test_get_performance_counters(self): 

2458 

2459 api_response = netapp_api.NaElement( 

2460 fake.PERF_OBJECT_GET_INSTANCES_SYSTEM_RESPONSE_CMODE) 

2461 self.mock_object(self.client, 

2462 'send_request', 

2463 mock.Mock(return_value=api_response)) 

2464 

2465 instance_uuids = [ 

2466 fake.NODE_NAMES[0] + ':kernel:system', 

2467 fake.NODE_NAMES[1] + ':kernel:system', 

2468 ] 

2469 counter_names = ['avg_processor_busy'] 

2470 result = self.client.get_performance_counters('system', 

2471 instance_uuids, 

2472 counter_names) 

2473 

2474 expected = [ 

2475 { 

2476 'avg_processor_busy': '5674745133134', 

2477 'instance-name': 'system', 

2478 'instance-uuid': instance_uuids[0], 

2479 'node-name': fake.NODE_NAMES[0], 

2480 'timestamp': '1453412013', 

2481 }, { 

2482 'avg_processor_busy': '4077649009234', 

2483 'instance-name': 'system', 

2484 'instance-uuid': instance_uuids[1], 

2485 'node-name': fake.NODE_NAMES[1], 

2486 'timestamp': '1453412013' 

2487 }, 

2488 ] 

2489 self.assertEqual(expected, result) 

2490 

2491 perf_object_get_instances_args = { 

2492 'objectname': 'system', 

2493 'instance-uuids': [ 

2494 {'instance-uuid': instance_uuid} 

2495 for instance_uuid in instance_uuids 

2496 ], 

2497 'counters': [ 

2498 {'counter': counter} for counter in counter_names 

2499 ], 

2500 } 

2501 self.client.send_request.assert_called_once_with( 

2502 'perf-object-get-instances', perf_object_get_instances_args) 

2503 

2504 def test_setup_security_services_ldap(self): 

2505 

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

2507 self.mock_object(self.vserver_client, 'configure_ldap') 

2508 

2509 self.client.setup_security_services([fake.LDAP_LINUX_SECURITY_SERVICE], 

2510 self.vserver_client, 

2511 fake.VSERVER_NAME, 

2512 False) 

2513 

2514 vserver_modify_args = { 

2515 'name-mapping-switch': [ 

2516 {'nmswitch': 'ldap'}, 

2517 {'nmswitch': 'file'}, 

2518 ], 

2519 'name-server-switch': [ 

2520 {'nsswitch': 'ldap'}, 

2521 {'nsswitch': 'file'}, 

2522 ], 

2523 'vserver-name': fake.VSERVER_NAME 

2524 } 

2525 self.client.send_request.assert_has_calls([ 

2526 mock.call('vserver-modify', vserver_modify_args)]) 

2527 self.vserver_client.configure_ldap.assert_has_calls([ 

2528 mock.call(fake.LDAP_LINUX_SECURITY_SERVICE, timeout=30)]) 

2529 

2530 def test_setup_security_services_active_directory(self): 

2531 

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

2533 self.mock_object(self.vserver_client, 'configure_active_directory') 

2534 self.mock_object(self.vserver_client, 'configure_cifs_options') 

2535 

2536 self.client.setup_security_services([fake.CIFS_SECURITY_SERVICE], 

2537 self.vserver_client, 

2538 fake.VSERVER_NAME, 

2539 False) 

2540 

2541 vserver_modify_args = { 

2542 'name-mapping-switch': [ 

2543 {'nmswitch': 'ldap'}, 

2544 {'nmswitch': 'file'}, 

2545 ], 

2546 'name-server-switch': [ 

2547 {'nsswitch': 'ldap'}, 

2548 {'nsswitch': 'file'}, 

2549 ], 

2550 'vserver-name': fake.VSERVER_NAME 

2551 } 

2552 self.client.send_request.assert_has_calls([ 

2553 mock.call('vserver-modify', vserver_modify_args)]) 

2554 self.vserver_client.configure_active_directory.assert_has_calls([ 

2555 mock.call(fake.CIFS_SECURITY_SERVICE, fake.VSERVER_NAME, False)]) 

2556 self.vserver_client.configure_cifs_options.assert_has_calls([ 

2557 mock.call(fake.CIFS_SECURITY_SERVICE)]) 

2558 

2559 def test_setup_security_services_kerberos(self): 

2560 

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

2562 self.mock_object(self.vserver_client, 'create_kerberos_realm') 

2563 self.mock_object(self.vserver_client, 'configure_kerberos') 

2564 

2565 self.client.setup_security_services([fake.KERBEROS_SECURITY_SERVICE], 

2566 self.vserver_client, 

2567 fake.VSERVER_NAME, 

2568 False) 

2569 

2570 vserver_modify_args = { 

2571 'name-mapping-switch': [ 

2572 {'nmswitch': 'ldap'}, 

2573 {'nmswitch': 'file'}, 

2574 ], 

2575 'name-server-switch': [ 

2576 {'nsswitch': 'ldap'}, 

2577 {'nsswitch': 'file'}, 

2578 ], 

2579 'vserver-name': fake.VSERVER_NAME 

2580 } 

2581 self.client.send_request.assert_has_calls([ 

2582 mock.call('vserver-modify', vserver_modify_args)]) 

2583 self.vserver_client.create_kerberos_realm.assert_has_calls([ 

2584 mock.call(fake.KERBEROS_SECURITY_SERVICE)]) 

2585 self.vserver_client.configure_kerberos.assert_has_calls([ 

2586 mock.call(fake.KERBEROS_SECURITY_SERVICE, fake.VSERVER_NAME)]) 

2587 

2588 def test_setup_security_services_invalid(self): 

2589 

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

2591 

2592 self.assertRaises(exception.NetAppException, 

2593 self.client.setup_security_services, 

2594 [fake.INVALID_SECURITY_SERVICE], 

2595 self.vserver_client, 

2596 fake.VSERVER_NAME, 

2597 False) 

2598 

2599 vserver_modify_args = { 

2600 'name-mapping-switch': [ 

2601 {'nmswitch': 'ldap'}, 

2602 {'nmswitch': 'file'}, 

2603 ], 

2604 'name-server-switch': [ 

2605 {'nsswitch': 'ldap'}, 

2606 {'nsswitch': 'file'}, 

2607 ], 

2608 'vserver-name': fake.VSERVER_NAME 

2609 } 

2610 self.client.send_request.assert_has_calls([ 

2611 mock.call('vserver-modify', vserver_modify_args)]) 

2612 

2613 def test_update_showmount(self): 

2614 

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

2616 

2617 fake_showmount = 'true' 

2618 self.client.update_showmount(fake_showmount) 

2619 

2620 nfs_service_modify_args = { 

2621 'showmount': fake_showmount, 

2622 } 

2623 self.client.send_request.assert_called_once_with( 

2624 'nfs-service-modify', nfs_service_modify_args) 

2625 

2626 @ddt.data({'tcp-max-xfer-size': 10000}, {}, None) 

2627 def test_enable_nfs(self, nfs_config): 

2628 

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

2630 self.mock_object(self.client, '_enable_nfs_protocols') 

2631 self.mock_object(self.client, '_create_default_nfs_export_rules') 

2632 self.mock_object(self.client, '_configure_nfs') 

2633 

2634 self.client.enable_nfs(fake.NFS_VERSIONS, nfs_config) 

2635 

2636 self.client.send_request.assert_called_once_with('nfs-enable') 

2637 self.client._enable_nfs_protocols.assert_called_once_with( 

2638 fake.NFS_VERSIONS) 

2639 self.client._create_default_nfs_export_rules.assert_called_once_with() 

2640 if nfs_config: 

2641 self.client._configure_nfs.assert_called_once_with(nfs_config) 

2642 else: 

2643 self.client._configure_nfs.assert_not_called() 

2644 

2645 @ddt.data((True, True, True), (True, False, False), (False, True, True)) 

2646 @ddt.unpack 

2647 def test_enable_nfs_protocols(self, v3, v40, v41): 

2648 

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

2650 

2651 versions = [] 

2652 if v3: 

2653 versions.append('nfs3') 

2654 if v40: 

2655 versions.append('nfs4.0') 

2656 if v41: 

2657 versions.append('nfs4.1') 

2658 

2659 self.client._enable_nfs_protocols(versions) 

2660 

2661 nfs_service_modify_args = { 

2662 'is-nfsv3-enabled': 'true' if v3 else 'false', 

2663 'is-nfsv40-enabled': 'true' if v40 else 'false', 

2664 'is-nfsv41-enabled': 'true' if v41 else 'false', 

2665 'showmount': 'true', 

2666 'is-v3-ms-dos-client-enabled': 'true', 

2667 'is-nfsv3-connection-drop-enabled': 'false', 

2668 'enable-ejukebox': 'false', 

2669 } 

2670 self.client.send_request.assert_called_once_with( 

2671 'nfs-service-modify', nfs_service_modify_args) 

2672 

2673 def test_configure_nfs(self): 

2674 fake_nfs = { 

2675 'tcp-max-xfer-size': 10000, 

2676 } 

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

2678 

2679 self.client._configure_nfs(fake_nfs) 

2680 

2681 self.client.send_request.assert_called_once_with( 

2682 'nfs-service-modify', fake_nfs) 

2683 

2684 def test_create_default_nfs_export_rules(self): 

2685 

2686 class CopyingMock(mock.Mock): 

2687 def __call__(self, *args, **kwargs): 

2688 args = copy.deepcopy(args) 

2689 kwargs = copy.deepcopy(kwargs) 

2690 return super(CopyingMock, self).__call__(*args, **kwargs) 

2691 

2692 self.mock_object(self.client, 'send_request', CopyingMock()) 

2693 

2694 self.client._create_default_nfs_export_rules() 

2695 

2696 export_rule_create_args = { 

2697 'client-match': '0.0.0.0/0', 

2698 'policy-name': 'default', 

2699 'ro-rule': { 

2700 'security-flavor': 'any' 

2701 }, 

2702 'rw-rule': { 

2703 'security-flavor': 'never' 

2704 } 

2705 } 

2706 export_rule_create_args2 = export_rule_create_args.copy() 

2707 export_rule_create_args2['client-match'] = '::/0' 

2708 self.client.send_request.assert_has_calls([ 

2709 mock.call('export-rule-create', export_rule_create_args), 

2710 mock.call('export-rule-create', export_rule_create_args2)]) 

2711 

2712 @ddt.data(fake.LDAP_LINUX_SECURITY_SERVICE, fake.LDAP_AD_SECURITY_SERVICE) 

2713 def test_configure_ldap(self, sec_service): 

2714 self.client.features.add_feature('LDAP_LDAP_SERVERS') 

2715 

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

2717 self.mock_object(self.client, 'configure_dns') 

2718 

2719 self.client.configure_ldap(sec_service) 

2720 

2721 config_name = hashlib.md5( 

2722 sec_service['id'].encode("latin-1")).hexdigest() 

2723 

2724 ldap_client_create_args = { 

2725 'ldap-client-config': config_name, 

2726 'tcp-port': '389', 

2727 'bind-password': sec_service['password'], 

2728 } 

2729 

2730 if sec_service.get('domain'): 

2731 ldap_client_create_args['schema'] = 'MS-AD-BIS' 

2732 ldap_client_create_args['bind-dn'] = ( 

2733 sec_service['user'] + '@' + sec_service['domain']) 

2734 ldap_client_create_args['ad-domain'] = sec_service['domain'] 

2735 else: 

2736 ldap_client_create_args['schema'] = 'RFC-2307' 

2737 ldap_client_create_args['bind-dn'] = sec_service['user'] 

2738 ldap_client_create_args['ldap-servers'] = [{ 

2739 'string': sec_service['server'] 

2740 }] 

2741 

2742 if sec_service.get('ou'): 2742 ↛ 2745line 2742 didn't jump to line 2745 because the condition on line 2742 was always true

2743 ldap_client_create_args['base-dn'] = sec_service['ou'] 

2744 

2745 ldap_config_create_args = { 

2746 'client-config': config_name, 

2747 'client-enabled': 'true' 

2748 } 

2749 

2750 self.client.send_request.assert_has_calls([ 

2751 mock.call('ldap-client-create', ldap_client_create_args), 

2752 mock.call('ldap-config-create', ldap_config_create_args)]) 

2753 

2754 @ddt.data({'server': None, 'domain': None}, 

2755 {'server': 'fake_server', 'domain': 'fake_domain'}) 

2756 @ddt.unpack 

2757 def test_configure_ldap_invalid_parameters(self, server, domain): 

2758 fake_ldap_sec_service = copy.deepcopy(fake.LDAP_AD_SECURITY_SERVICE) 

2759 fake_ldap_sec_service['server'] = server 

2760 fake_ldap_sec_service['domain'] = domain 

2761 

2762 self.assertRaises(exception.NetAppException, 

2763 self.client.configure_ldap, 

2764 fake_ldap_sec_service) 

2765 

2766 def test__enable_ldap_client_timeout(self): 

2767 mock_warning_log = self.mock_object(client_cmode.LOG, 'warning') 

2768 na_api_error = netapp_api.NaApiError(code=netapp_api.EAPIERROR) 

2769 mock_send_request = self.mock_object( 

2770 self.client, 'send_request', mock.Mock(side_effect=na_api_error)) 

2771 

2772 self.assertRaises(exception.NetAppException, 

2773 self.client._enable_ldap_client, 

2774 'fake_config_name', 

2775 timeout=6) 

2776 

2777 self.assertEqual(2, mock_send_request.call_count) 

2778 self.assertEqual(2, mock_warning_log.call_count) 

2779 

2780 def test_configure_active_directory(self): 

2781 

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

2783 self.mock_object(self.client, 'configure_dns') 

2784 self.mock_object(self.client, 'configure_cifs_aes_encryption') 

2785 self.mock_object(self.client, 'set_preferred_dc') 

2786 

2787 self.client.configure_active_directory(fake.CIFS_SECURITY_SERVICE, 

2788 fake.VSERVER_NAME, 

2789 False) 

2790 

2791 cifs_server = (fake.VSERVER_NAME[0:8] + 

2792 '-' + 

2793 fake.VSERVER_NAME[-6:]).replace('_', '-').upper() 

2794 

2795 cifs_server_create_args = { 

2796 'admin-username': fake.CIFS_SECURITY_SERVICE['user'], 

2797 'admin-password': fake.CIFS_SECURITY_SERVICE['password'], 

2798 'force-account-overwrite': 'true', 

2799 'cifs-server': cifs_server, 

2800 'organizational-unit': fake.CIFS_SECURITY_SERVICE['ou'], 

2801 'domain': fake.CIFS_SECURITY_SERVICE['domain'], 

2802 } 

2803 

2804 self.client.configure_dns.assert_called_with( 

2805 fake.CIFS_SECURITY_SERVICE) 

2806 self.client.configure_cifs_aes_encryption.assert_called_with(False) 

2807 self.client.set_preferred_dc.assert_called_with( 

2808 fake.CIFS_SECURITY_SERVICE) 

2809 self.client.send_request.assert_has_calls([ 

2810 mock.call('cifs-server-create', cifs_server_create_args)]) 

2811 

2812 def test_configure_active_directory_with_ad_site(self): 

2813 

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

2815 self.mock_object(self.client, 'configure_dns') 

2816 self.mock_object(self.client, 'configure_cifs_aes_encryption') 

2817 self.mock_object(self.client, 'set_preferred_dc') 

2818 

2819 self.client.configure_active_directory(fake.CIFS_SECURITY_SERVICE_3, 

2820 fake.VSERVER_NAME, False) 

2821 

2822 cifs_server = (fake.VSERVER_NAME[0:8] + 

2823 '-' + 

2824 fake.VSERVER_NAME[-6:]).replace('_', '-').upper() 

2825 

2826 cifs_server_create_args = { 

2827 'admin-username': fake.CIFS_SECURITY_SERVICE_3['user'], 

2828 'admin-password': fake.CIFS_SECURITY_SERVICE_3['password'], 

2829 'force-account-overwrite': 'true', 

2830 'cifs-server': cifs_server, 

2831 'organizational-unit': fake.CIFS_SECURITY_SERVICE_3['ou'], 

2832 'domain': fake.CIFS_SECURITY_SERVICE_3['domain'], 

2833 'default-site': fake.CIFS_SECURITY_SERVICE_3['default_ad_site'], 

2834 } 

2835 

2836 self.client.configure_dns.assert_called_with( 

2837 fake.CIFS_SECURITY_SERVICE_3) 

2838 self.client.configure_cifs_aes_encryption.assert_called_with(False) 

2839 self.client.set_preferred_dc.assert_called_with( 

2840 fake.CIFS_SECURITY_SERVICE_3) 

2841 self.client.send_request.assert_has_calls([ 

2842 mock.call('cifs-server-create', cifs_server_create_args)]) 

2843 

2844 def test_configure_active_directory_api_error(self): 

2845 

2846 self.mock_object(self.client, 'send_request', self._mock_api_error()) 

2847 self.mock_object(self.client, 'configure_dns') 

2848 

2849 self.assertRaises(exception.NetAppException, 

2850 self.client.configure_active_directory, 

2851 fake.CIFS_SECURITY_SERVICE, 

2852 fake.VSERVER_NAME, 

2853 False) 

2854 

2855 def test_create_kerberos_realm(self): 

2856 self.client.features.add_feature('KERBEROS_VSERVER') 

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

2858 

2859 self.client.create_kerberos_realm(fake.KERBEROS_SECURITY_SERVICE) 

2860 

2861 kerberos_realm_create_args = { 

2862 'admin-server-ip': fake.KERBEROS_SECURITY_SERVICE['server'], 

2863 'admin-server-port': '749', 

2864 'clock-skew': '5', 

2865 'comment': '', 

2866 'kdc-ip': fake.KERBEROS_SECURITY_SERVICE['server'], 

2867 'kdc-port': '88', 

2868 'kdc-vendor': 'other', 

2869 'password-server-ip': fake.KERBEROS_SECURITY_SERVICE['server'], 

2870 'password-server-port': '464', 

2871 'realm': fake.KERBEROS_SECURITY_SERVICE['domain'].upper() 

2872 } 

2873 

2874 self.client.send_request.assert_has_calls([ 

2875 mock.call('kerberos-realm-create', kerberos_realm_create_args)]) 

2876 

2877 def test_create_kerberos_realm_already_present(self): 

2878 self.client.features.add_feature('KERBEROS_VSERVER') 

2879 self.mock_object(self.client, 

2880 'send_request', 

2881 self._mock_api_error(code=netapp_api.EDUPLICATEENTRY)) 

2882 

2883 self.client.create_kerberos_realm(fake.KERBEROS_SECURITY_SERVICE) 

2884 

2885 kerberos_realm_create_args = { 

2886 'admin-server-ip': fake.KERBEROS_SECURITY_SERVICE['server'], 

2887 'admin-server-port': '749', 

2888 'clock-skew': '5', 

2889 'comment': '', 

2890 'kdc-ip': fake.KERBEROS_SECURITY_SERVICE['server'], 

2891 'kdc-port': '88', 

2892 'kdc-vendor': 'other', 

2893 'password-server-ip': fake.KERBEROS_SECURITY_SERVICE['server'], 

2894 'password-server-port': '464', 

2895 'realm': fake.KERBEROS_SECURITY_SERVICE['domain'].upper() 

2896 } 

2897 

2898 self.client.send_request.assert_has_calls([ 

2899 mock.call('kerberos-realm-create', kerberos_realm_create_args)]) 

2900 self.assertEqual(1, client_cmode.LOG.debug.call_count) 

2901 

2902 def test_create_kerberos_realm_api_error(self): 

2903 self.client.features.add_feature('KERBEROS_VSERVER') 

2904 self.mock_object(self.client, 'send_request', self._mock_api_error()) 

2905 

2906 self.assertRaises(exception.NetAppException, 

2907 self.client.create_kerberos_realm, 

2908 fake.KERBEROS_SECURITY_SERVICE) 

2909 

2910 def test_update_kerberos_realm(self): 

2911 self.client.features.add_feature('KERBEROS_VSERVER') 

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

2913 

2914 self.client.update_kerberos_realm(fake.KERBEROS_SECURITY_SERVICE) 

2915 

2916 kerberos_realm_create_args = { 

2917 'admin-server-ip': fake.KERBEROS_SECURITY_SERVICE['server'], 

2918 'kdc-ip': fake.KERBEROS_SECURITY_SERVICE['server'], 

2919 'password-server-ip': fake.KERBEROS_SECURITY_SERVICE['server'], 

2920 'realm': fake.KERBEROS_SECURITY_SERVICE['domain'].upper(), 

2921 } 

2922 

2923 self.client.send_request.assert_has_calls([ 

2924 mock.call('kerberos-realm-modify', 

2925 kerberos_realm_create_args)]) 

2926 

2927 def test_update_kerberos_realm_failure(self): 

2928 self.client.features.add_feature('KERBEROS_VSERVER') 

2929 self.mock_object(self.client, 'send_request', self._mock_api_error()) 

2930 

2931 self.assertRaises(exception.NetAppException, 

2932 self.client.update_kerberos_realm, 

2933 fake.KERBEROS_SECURITY_SERVICE) 

2934 

2935 kerberos_realm_create_args = { 

2936 'admin-server-ip': fake.KERBEROS_SECURITY_SERVICE['server'], 

2937 'kdc-ip': fake.KERBEROS_SECURITY_SERVICE['server'], 

2938 'password-server-ip': fake.KERBEROS_SECURITY_SERVICE['server'], 

2939 'realm': fake.KERBEROS_SECURITY_SERVICE['domain'].upper(), 

2940 } 

2941 

2942 self.client.send_request.assert_has_calls([ 

2943 mock.call('kerberos-realm-modify', 

2944 kerberos_realm_create_args)]) 

2945 

2946 def test_configure_kerberos(self): 

2947 self.client.features.add_feature('KERBEROS_VSERVER') 

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

2949 self.mock_object(self.client, 'configure_dns') 

2950 self.mock_object(self.client, 

2951 'list_network_interfaces', 

2952 mock.Mock(return_value=['lif1', 'lif2'])) 

2953 

2954 self.client.configure_kerberos( 

2955 fake.KERBEROS_SECURITY_SERVICE, fake.VSERVER_NAME) 

2956 

2957 spn = self.client._get_kerberos_service_principal_name( 

2958 fake.KERBEROS_SECURITY_SERVICE, fake.VSERVER_NAME) 

2959 

2960 kerberos_config_modify_args1 = { 

2961 'admin-password': fake.KERBEROS_SECURITY_SERVICE['password'], 

2962 'admin-user-name': fake.KERBEROS_SECURITY_SERVICE['user'], 

2963 'interface-name': 'lif1', 

2964 'is-kerberos-enabled': 'true', 

2965 'service-principal-name': spn 

2966 } 

2967 kerberos_config_modify_args2 = { 

2968 'admin-password': fake.KERBEROS_SECURITY_SERVICE['password'], 

2969 'admin-user-name': fake.KERBEROS_SECURITY_SERVICE['user'], 

2970 'interface-name': 'lif2', 

2971 'is-kerberos-enabled': 'true', 

2972 'service-principal-name': spn 

2973 } 

2974 

2975 self.client.configure_dns.assert_called_with( 

2976 fake.KERBEROS_SECURITY_SERVICE) 

2977 self.client.send_request.assert_has_calls([ 

2978 mock.call('kerberos-config-modify', 

2979 kerberos_config_modify_args1), 

2980 mock.call('kerberos-config-modify', 

2981 kerberos_config_modify_args2)]) 

2982 

2983 def test_configure_kerberos_no_network_interfaces(self): 

2984 self.client.features.add_feature('KERBEROS_VSERVER') 

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

2986 self.mock_object(self.client, 'configure_dns') 

2987 self.mock_object(self.client, 

2988 'list_network_interfaces', 

2989 mock.Mock(return_value=[])) 

2990 

2991 self.assertRaises(exception.NetAppException, 

2992 self.client.configure_kerberos, 

2993 fake.KERBEROS_SECURITY_SERVICE, 

2994 fake.VSERVER_NAME) 

2995 

2996 self.client.configure_dns.assert_called_with( 

2997 fake.KERBEROS_SECURITY_SERVICE) 

2998 

2999 def test_disable_kerberos(self): 

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

3001 self.mock_object(self.client, 

3002 'list_network_interfaces', 

3003 mock.Mock(return_value=['lif1', 'lif2'])) 

3004 

3005 self.client.disable_kerberos(fake.KERBEROS_SECURITY_SERVICE) 

3006 

3007 kerberos_config_modify_args1 = { 

3008 'admin-password': fake.KERBEROS_SECURITY_SERVICE['password'], 

3009 'admin-user-name': fake.KERBEROS_SECURITY_SERVICE['user'], 

3010 'interface-name': 'lif1', 

3011 'is-kerberos-enabled': 'false', 

3012 } 

3013 kerberos_config_modify_args2 = { 

3014 'admin-password': fake.KERBEROS_SECURITY_SERVICE['password'], 

3015 'admin-user-name': fake.KERBEROS_SECURITY_SERVICE['user'], 

3016 'interface-name': 'lif2', 

3017 'is-kerberos-enabled': 'false', 

3018 } 

3019 

3020 self.client.send_request.assert_has_calls([ 

3021 mock.call('kerberos-config-modify', 

3022 kerberos_config_modify_args1), 

3023 mock.call('kerberos-config-modify', 

3024 kerberos_config_modify_args2)]) 

3025 self.client.list_network_interfaces.assert_called_once() 

3026 

3027 def test_disable_kerberos_already_disabled(self): 

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

3029 self._mock_api_error( 

3030 code=netapp_api.EAPIERROR, 

3031 message='Kerberos is already disabled')) 

3032 self.mock_object(self.client, 

3033 'list_network_interfaces', 

3034 mock.Mock(return_value=['lif1'])) 

3035 

3036 self.client.disable_kerberos(fake.KERBEROS_SECURITY_SERVICE) 

3037 

3038 kerberos_config_modify_args = { 

3039 'admin-password': fake.KERBEROS_SECURITY_SERVICE['password'], 

3040 'admin-user-name': fake.KERBEROS_SECURITY_SERVICE['user'], 

3041 'interface-name': 'lif1', 

3042 'is-kerberos-enabled': 'false', 

3043 } 

3044 

3045 self.client.send_request.assert_called_once_with( 

3046 'kerberos-config-modify', kerberos_config_modify_args) 

3047 self.client.list_network_interfaces.assert_called_once() 

3048 

3049 def test_is_kerberos_enabled(self): 

3050 self.client.features.add_feature('KERBEROS_VSERVER') 

3051 api_response = netapp_api.NaElement( 

3052 fake.KERBEROS_CONFIG_GET_RESPONSE) 

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

3054 mock.Mock(return_value=api_response)) 

3055 self.mock_object(self.client, 

3056 'get_network_interfaces', 

3057 mock.Mock(return_value=[{'interface-name': 'lif1'}])) 

3058 

3059 result = self.client.is_kerberos_enabled() 

3060 

3061 kerberos_config_get_args = { 

3062 'interface-name': 'lif1', 

3063 'desired-attributes': { 

3064 'kerberos-config-info': { 

3065 'is-kerberos-enabled': None, 

3066 } 

3067 } 

3068 } 

3069 

3070 self.assertTrue(result) 

3071 self.client.send_request.assert_called_once_with( 

3072 'kerberos-config-get', kerberos_config_get_args) 

3073 self.client.get_network_interfaces.assert_called_once_with( 

3074 protocols=['NFS', 'CIFS']) 

3075 

3076 def test_is_kerberos_enabled_exception_raise(self): 

3077 self.client.features.add_feature('KERBEROS_VSERVER') 

3078 api_response = netapp_api.NaElement( 

3079 fake.KERBEROS_CONFIG_GET_RESPONSE) 

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

3081 mock.Mock(side_effect=[api_response, 

3082 netapp_api.NaApiError('foobar')])) 

3083 self.mock_object(self.client, 

3084 'get_network_interfaces', 

3085 mock.Mock(return_value=[{'interface-name': 'lif1'}, 

3086 {'interface-name': 'lif2'}, 

3087 {'interface-name': 'lif3'}])) 

3088 

3089 self.assertRaises(netapp_api.NaApiError, 

3090 self.client.is_kerberos_enabled) 

3091 

3092 kerberos_config_get_args_lif1 = { 

3093 'interface-name': 'lif1', 

3094 'desired-attributes': { 

3095 'kerberos-config-info': { 

3096 'is-kerberos-enabled': None, 

3097 } 

3098 } 

3099 } 

3100 

3101 kerberos_config_get_args_lif2 = { 

3102 'interface-name': 'lif2', 

3103 'desired-attributes': { 

3104 'kerberos-config-info': { 

3105 'is-kerberos-enabled': None, 

3106 } 

3107 } 

3108 } 

3109 

3110 self.client.send_request.assert_has_calls([ 

3111 mock.call('kerberos-config-get', kerberos_config_get_args_lif1), 

3112 mock.call('kerberos-config-get', kerberos_config_get_args_lif2), 

3113 ]) 

3114 self.client.get_network_interfaces.assert_called_once_with( 

3115 protocols=['NFS', 'CIFS']) 

3116 

3117 def test_is_kerberos_enabled_exception_return_false(self): 

3118 self.client.features.add_feature('KERBEROS_VSERVER') 

3119 api_response = netapp_api.NaElement( 

3120 fake.KERBEROS_CONFIG_GET_RESPONSE) 

3121 self.mock_object( 

3122 self.client, 'send_request', 

3123 mock.Mock(side_effect=[api_response, netapp_api.NaApiError( 

3124 message="entry doesn't exist")])) 

3125 self.mock_object(self.client, 

3126 'get_network_interfaces', 

3127 mock.Mock(return_value=[{'interface-name': 'lif1'}, 

3128 {'interface-name': 'lif2'}, 

3129 {'interface-name': 'lif3'}])) 

3130 

3131 result = self.client.is_kerberos_enabled() 

3132 

3133 kerberos_config_get_args_lif1 = { 

3134 'interface-name': 'lif1', 

3135 'desired-attributes': { 

3136 'kerberos-config-info': { 

3137 'is-kerberos-enabled': None, 

3138 } 

3139 } 

3140 } 

3141 

3142 kerberos_config_get_args_lif2 = { 

3143 'interface-name': 'lif2', 

3144 'desired-attributes': { 

3145 'kerberos-config-info': { 

3146 'is-kerberos-enabled': None, 

3147 } 

3148 } 

3149 } 

3150 

3151 self.assertFalse(result) 

3152 self.client.send_request.assert_has_calls([ 

3153 mock.call('kerberos-config-get', kerberos_config_get_args_lif1), 

3154 mock.call('kerberos-config-get', kerberos_config_get_args_lif2), 

3155 ]) 

3156 self.client.get_network_interfaces.assert_called_once_with( 

3157 protocols=['NFS', 'CIFS']) 

3158 

3159 def test_get_kerberos_service_principal_name(self): 

3160 

3161 spn = self.client._get_kerberos_service_principal_name( 

3162 fake.KERBEROS_SECURITY_SERVICE, fake.VSERVER_NAME 

3163 ) 

3164 self.assertEqual(fake.KERBEROS_SERVICE_PRINCIPAL_NAME, spn) 

3165 

3166 def test_configure_dns_for_active_directory(self): 

3167 

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

3169 self.mock_object(self.client, 'get_dns_config', 

3170 mock.Mock(return_value={})) 

3171 

3172 self.client.configure_dns(fake.CIFS_SECURITY_SERVICE) 

3173 

3174 net_dns_create_args = { 

3175 'domains': [{'string': fake.CIFS_SECURITY_SERVICE['domain']}], 

3176 'name-servers': [{ 

3177 'ip-address': fake.CIFS_SECURITY_SERVICE['dns_ip'] 

3178 }], 

3179 'dns-state': 'enabled' 

3180 } 

3181 

3182 self.client.send_request.assert_has_calls([ 

3183 mock.call('net-dns-create', net_dns_create_args)]) 

3184 

3185 def test_configure_dns_multiple_dns_ip(self): 

3186 

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

3188 self.mock_object(self.client, 'get_dns_config', 

3189 mock.Mock(return_value={})) 

3190 mock_dns_ips = ['10.0.0.1', '10.0.0.2', '10.0.0.3'] 

3191 security_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE) 

3192 security_service['dns_ip'] = ', '.join(mock_dns_ips) 

3193 

3194 self.client.configure_dns(security_service) 

3195 

3196 self.client.send_request.assert_called_once() 

3197 

3198 def test_configure_dns_for_kerberos(self): 

3199 

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

3201 self.mock_object(self.client, 'get_dns_config', 

3202 mock.Mock(return_value={})) 

3203 

3204 self.client.configure_dns(fake.KERBEROS_SECURITY_SERVICE) 

3205 

3206 net_dns_create_args = { 

3207 'domains': [{'string': fake.KERBEROS_SECURITY_SERVICE['domain']}], 

3208 'name-servers': [{ 

3209 'ip-address': fake.KERBEROS_SECURITY_SERVICE['dns_ip'] 

3210 }], 

3211 'dns-state': 'enabled' 

3212 } 

3213 

3214 self.client.send_request.assert_has_calls([ 

3215 mock.call('net-dns-create', net_dns_create_args)]) 

3216 

3217 def test_configure_dns_already_present(self): 

3218 dns_config = { 

3219 'dns-state': 'enabled', 

3220 'domains': [fake.KERBEROS_SECURITY_SERVICE['domain']], 

3221 'dns-ips': [fake.KERBEROS_SECURITY_SERVICE['dns_ip']], 

3222 } 

3223 self.mock_object(self.client, 'get_dns_config', 

3224 mock.Mock(return_value=dns_config)) 

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

3226 

3227 self.client.configure_dns(fake.KERBEROS_SECURITY_SERVICE) 

3228 

3229 net_dns_create_args = { 

3230 'domains': [{'string': fake.KERBEROS_SECURITY_SERVICE['domain']}], 

3231 'name-servers': [{ 

3232 'ip-address': fake.KERBEROS_SECURITY_SERVICE['dns_ip'] 

3233 }], 

3234 'dns-state': 'enabled' 

3235 } 

3236 

3237 self.client.send_request.assert_has_calls([ 

3238 mock.call('net-dns-modify', net_dns_create_args)]) 

3239 

3240 def test_update_dns_configuration(self): 

3241 fake_configured_dns = { 

3242 'dns-state': 'enabled', 

3243 'domains': ['fake_domain_2'], 

3244 'dns-ips': ['fake_dns_ip_2'] 

3245 } 

3246 self.mock_object(self.client, 'get_dns_config', 

3247 mock.Mock(return_value=fake_configured_dns)) 

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

3249 

3250 self.client.configure_dns(fake.KERBEROS_SECURITY_SERVICE) 

3251 domains = set() 

3252 domains.add(fake_configured_dns['domains'][0]) 

3253 domains.add(fake.KERBEROS_SECURITY_SERVICE['domain']) 

3254 

3255 dns_ips = set() 

3256 dns_ips.add(fake_configured_dns['dns-ips'][0]) 

3257 dns_ips.add(fake.KERBEROS_SECURITY_SERVICE['dns_ip']) 

3258 

3259 net_dns_create_args = { 

3260 'domains': [{'string': domain} for domain in domains], 

3261 'dns-state': 'enabled', 

3262 'name-servers': [{'ip-address': dns_ip} for dns_ip in dns_ips] 

3263 } 

3264 

3265 self.client.send_request.assert_has_calls([ 

3266 mock.call('net-dns-modify', net_dns_create_args)]) 

3267 

3268 def test_configure_dns_api_error(self): 

3269 

3270 self.mock_object(self.client, 'send_request', self._mock_api_error()) 

3271 self.mock_object(self.client, 'get_dns_config', 

3272 mock.Mock(return_value={})) 

3273 

3274 self.assertRaises(exception.NetAppException, 

3275 self.client.configure_dns, 

3276 fake.KERBEROS_SECURITY_SERVICE) 

3277 

3278 def test_get_dns_configuration(self): 

3279 api_response = netapp_api.NaElement( 

3280 fake.DNS_CONFIG_GET_RESPONSE) 

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

3282 mock.Mock(return_value=api_response)) 

3283 

3284 result = self.client.get_dns_config() 

3285 

3286 expected_result = { 

3287 'dns-state': 'enabled', 

3288 'domains': ['fake_domain.com'], 

3289 'dns-ips': ['fake_dns_1', 'fake_dns_2'] 

3290 } 

3291 self.assertEqual(expected_result, result) 

3292 self.client.send_request.assert_called_once_with('net-dns-get', {}) 

3293 

3294 @ddt.data(True, False) 

3295 def test_configure_cifs_aes_encryption_enable(self, specify_types): 

3296 self.client.features.add_feature( 

3297 'AES_ENCRYPTION_TYPES', supported=specify_types) 

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

3299 

3300 self.client.configure_cifs_aes_encryption(True) 

3301 

3302 if specify_types: 

3303 configure_cifs_aes_encryption_args = { 

3304 'advertised-enc-types': [{'cifskrbenctypes': 'aes_128'}, 

3305 {'cifskrbenctypes': 'aes_256'}] 

3306 } 

3307 else: 

3308 configure_cifs_aes_encryption_args = { 

3309 'is-aes-encryption-enabled': 'true', 

3310 } 

3311 self.client.send_request.assert_called_with( 

3312 'cifs-security-modify', configure_cifs_aes_encryption_args) 

3313 

3314 @ddt.data(True, False) 

3315 def test_configure_cifs_aes_encryption_disable(self, specify_types): 

3316 self.client.features.add_feature( 

3317 'AES_ENCRYPTION_TYPES', supported=specify_types) 

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

3319 

3320 self.client.configure_cifs_aes_encryption(False) 

3321 

3322 if specify_types: 

3323 configure_cifs_aes_encryption_args = { 

3324 'advertised-enc-types': [{'cifskrbenctypes': 'des'}, 

3325 {'cifskrbenctypes': 'rc4'}] 

3326 } 

3327 else: 

3328 configure_cifs_aes_encryption_args = { 

3329 'is-aes-encryption-enabled': 'false', 

3330 } 

3331 self.client.send_request.assert_called_with( 

3332 'cifs-security-modify', configure_cifs_aes_encryption_args) 

3333 

3334 @ddt.data( 

3335 { 

3336 'server': '', 

3337 'check_feature': False 

3338 }, 

3339 { 

3340 'server': ['10.0.0.2', '10.0.0.3'], 

3341 'check_feature': False 

3342 }, 

3343 { 

3344 'server': '10.0.0.1', 

3345 'check_feature': False 

3346 }, 

3347 { 

3348 'server': '10.0.0.1', 

3349 'check_feature': True 

3350 } 

3351 ) 

3352 @ddt.unpack 

3353 def test_set_preferred_dc(self, server, check_feature): 

3354 if check_feature: 

3355 self.client.features.add_feature('CIFS_DC_ADD_SKIP_CHECK') 

3356 

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

3358 security_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE) 

3359 security_service['server'] = ', '.join(server) 

3360 

3361 self.client.set_preferred_dc(security_service) 

3362 

3363 if server == '': 

3364 self.client.send_request.assert_not_called() 

3365 else: 

3366 preferred_dc_add_args = { 

3367 'domain': fake.CIFS_SECURITY_SERVICE['domain'], 

3368 'preferred-dc': [{'string': dc_ip} for dc_ip in server] 

3369 } 

3370 

3371 if check_feature: 

3372 preferred_dc_add_args['skip-config-validation'] = 'false' 

3373 

3374 self.client.send_request.assert_has_calls([ 

3375 mock.call('cifs-domain-preferred-dc-add', 

3376 preferred_dc_add_args)]) 

3377 

3378 def test_set_preferred_dc_api_error(self): 

3379 

3380 self.mock_object(self.client, 'send_request', self._mock_api_error()) 

3381 security_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE) 

3382 security_service['server'] = 'fake_server' 

3383 

3384 self.assertRaises(exception.NetAppException, 

3385 self.client.set_preferred_dc, 

3386 security_service) 

3387 

3388 def test_remove_preferred_dcs(self): 

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

3390 security_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE) 

3391 

3392 self.client.remove_preferred_dcs(security_service) 

3393 

3394 preferred_dc_add_args = { 

3395 'domain': security_service['domain'], 

3396 } 

3397 self.client.send_request.assert_has_calls([ 

3398 mock.call('cifs-domain-preferred-dc-remove', 

3399 preferred_dc_add_args)]) 

3400 

3401 def test_remove_preferred_dcs_error(self): 

3402 self.mock_object(self.client, 'send_request', self._mock_api_error()) 

3403 security_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE) 

3404 

3405 self.assertRaises(exception.NetAppException, 

3406 self.client.remove_preferred_dcs, 

3407 security_service) 

3408 

3409 preferred_dc_add_args = { 

3410 'domain': security_service['domain'], 

3411 } 

3412 self.client.send_request.assert_has_calls([ 

3413 mock.call('cifs-domain-preferred-dc-remove', 

3414 preferred_dc_add_args)]) 

3415 

3416 @ddt.data(True, False) 

3417 def test_create_volume(self, set_max_files): 

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

3419 self.mock_object(self.client, 'set_volume_max_files') 

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

3421 self.mock_object(self.client, 'update_volume_efficiency_attributes') 

3422 self.mock_object( 

3423 self.client, '_get_create_volume_api_args', 

3424 mock.Mock(return_value={})) 

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

3426 

3427 self.client.create_volume( 

3428 fake.SHARE_AGGREGATE_NAME, fake.SHARE_NAME, 100, 

3429 max_files=fake.MAX_FILES if set_max_files else None, 

3430 **options 

3431 ) 

3432 

3433 volume_create_args = { 

3434 'containing-aggr-name': fake.SHARE_AGGREGATE_NAME, 

3435 'size': '100g', 

3436 'volume': fake.SHARE_NAME, 

3437 } 

3438 

3439 self.client._get_create_volume_api_args.assert_called_once_with( 

3440 fake.SHARE_NAME, False, None, None, None, 'rw', None, False, 

3441 None, None, None) 

3442 self.client.send_request.assert_called_with('volume-create', 

3443 volume_create_args) 

3444 ( 

3445 self.client.update_volume_efficiency_attributes. 

3446 assert_called_once_with 

3447 (fake.SHARE_NAME, False, False, 

3448 efficiency_policy=fake.VOLUME_EFFICIENCY_POLICY_NAME) 

3449 ) 

3450 if set_max_files: 

3451 self.client.set_volume_max_files.assert_called_once_with( 

3452 fake.SHARE_NAME, fake.MAX_FILES) 

3453 else: 

3454 self.client.set_volume_max_files.assert_not_called() 

3455 

3456 @ddt.data(True, False) 

3457 def test_create_volume_thin_provisioned(self, thin_provisioned): 

3458 

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

3460 self.mock_object(self.client, 'update_volume_efficiency_attributes') 

3461 

3462 self.client.create_volume( 

3463 fake.SHARE_AGGREGATE_NAME, fake.SHARE_NAME, 100, 

3464 thin_provisioned=thin_provisioned) 

3465 

3466 volume_create_args = { 

3467 'containing-aggr-name': fake.SHARE_AGGREGATE_NAME, 

3468 'size': '100g', 

3469 'volume': fake.SHARE_NAME, 

3470 'volume-type': 'rw', 

3471 'junction-path': '/%s' % fake.SHARE_NAME, 

3472 'space-reserve': ('none' if thin_provisioned else 'volume'), 

3473 'encrypt': 'false' 

3474 } 

3475 

3476 self.client.send_request.assert_called_once_with('volume-create', 

3477 volume_create_args) 

3478 

3479 @ddt.data("compliance", "enterprise") 

3480 def test_create_volume_snaplock_type(self, snaplock_type): 

3481 

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

3483 self.mock_object(self.client, 'update_volume_efficiency_attributes') 

3484 self.mock_object(self.client, 'set_snaplock_attributes') 

3485 

3486 self.client.create_volume( 

3487 fake.SHARE_AGGREGATE_NAME, fake.SHARE_NAME, 100, 

3488 snaplock_type=snaplock_type) 

3489 

3490 volume_create_args = { 

3491 'containing-aggr-name': fake.SHARE_AGGREGATE_NAME, 

3492 'size': '100g', 

3493 'volume': fake.SHARE_NAME, 

3494 'volume-type': 'rw', 

3495 'junction-path': '/%s' % fake.SHARE_NAME, 

3496 'space-reserve': 'volume', 

3497 'encrypt': 'false', 

3498 'snaplock-type': snaplock_type, 

3499 } 

3500 

3501 self.client.send_request.assert_called_once_with('volume-create', 

3502 volume_create_args) 

3503 

3504 def test_create_volume_adaptive_not_supported(self): 

3505 

3506 self.client.features.add_feature('ADAPTIVE_QOS', supported=False) 

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

3508 self.assertRaises(exception.NetAppException, 

3509 self.client.create_volume, 

3510 fake.SHARE_AGGREGATE_NAME, 

3511 fake.SHARE_NAME, 

3512 100, 

3513 adaptive_qos_policy_group='fake') 

3514 self.client.send_request.assert_not_called() 

3515 

3516 @ddt.data(True, False) 

3517 def test_create_volume_async(self, auto_provisioned): 

3518 api_response = netapp_api.NaElement(fake.ASYNC_OPERATION_RESPONSE) 

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

3520 mock.Mock(return_value=api_response)) 

3521 self.mock_object( 

3522 self.client, '_get_create_volume_api_args', 

3523 mock.Mock(return_value={})) 

3524 

3525 result = self.client.create_volume_async( 

3526 [fake.SHARE_AGGREGATE_NAME], fake.SHARE_NAME, 1, 

3527 auto_provisioned=auto_provisioned) 

3528 

3529 volume_create_args = { 

3530 'size': 1073741824, 

3531 'volume-name': fake.SHARE_NAME, 

3532 } 

3533 if auto_provisioned: 

3534 volume_create_args['auto-provision-as'] = 'flexgroup' 

3535 else: 

3536 volume_create_args['aggr-list'] = [ 

3537 {'aggr-name': fake.SHARE_AGGREGATE_NAME}] 

3538 

3539 expected_result = { 

3540 'jobid': '123', 

3541 'error-code': None, 

3542 'error-message': None, 

3543 } 

3544 

3545 self.client._get_create_volume_api_args.assert_called_once_with( 

3546 fake.SHARE_NAME, False, None, None, None, 'rw', None, False, 

3547 None, None, None) 

3548 self.client.send_request.assert_called_with('volume-create-async', 

3549 volume_create_args) 

3550 self.assertEqual(expected_result, result) 

3551 

3552 def test_create_volume_async_adaptive_not_supported(self): 

3553 

3554 self.client.features.add_feature('ADAPTIVE_QOS', supported=False) 

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

3556 self.assertRaises(exception.NetAppException, 

3557 self.client.create_volume_async, 

3558 [fake.SHARE_AGGREGATE_NAME], 

3559 fake.SHARE_NAME, 

3560 100, 

3561 adaptive_qos_policy_group='fake') 

3562 self.client.send_request.assert_not_called() 

3563 

3564 def test_get_create_volume_api_args_with_mount_point_name(self): 

3565 

3566 self.client.features.add_feature('FLEXVOL_ENCRYPTION') 

3567 volume_type = 'rw' 

3568 thin_provisioned = False 

3569 snapshot_policy = 'default' 

3570 language = 'en-US' 

3571 reserve = 15 

3572 qos_name = 'fake_qos' 

3573 encrypt = True 

3574 qos_adaptive_name = 'fake_adaptive_qos' 

3575 mount_point_name = 'fake_mp' 

3576 

3577 result_api_args = self.client._get_create_volume_api_args( 

3578 fake.SHARE_NAME, thin_provisioned, snapshot_policy, language, 

3579 reserve, volume_type, qos_name, encrypt, qos_adaptive_name, 

3580 mount_point_name) 

3581 

3582 expected_api_args = { 

3583 'volume-type': volume_type, 

3584 'junction-path': '/fake_mp', 

3585 'space-reserve': 'volume', 

3586 'snapshot-policy': snapshot_policy, 

3587 'language-code': language, 

3588 'percentage-snapshot-reserve': str(reserve), 

3589 'qos-policy-group-name': qos_name, 

3590 'qos-adaptive-policy-group-name': qos_adaptive_name, 

3591 'encrypt': 'true', 

3592 } 

3593 self.assertEqual(expected_api_args, result_api_args) 

3594 

3595 def test_get_create_volume_api_args_with_extra_specs(self): 

3596 

3597 self.client.features.add_feature('FLEXVOL_ENCRYPTION') 

3598 volume_type = 'rw' 

3599 thin_provisioned = False 

3600 snapshot_policy = 'default' 

3601 language = 'en-US' 

3602 reserve = 15 

3603 qos_name = 'fake_qos' 

3604 encrypt = True 

3605 qos_adaptive_name = 'fake_adaptive_qos' 

3606 

3607 result_api_args = self.client._get_create_volume_api_args( 

3608 fake.SHARE_NAME, thin_provisioned, snapshot_policy, language, 

3609 reserve, volume_type, qos_name, encrypt, qos_adaptive_name) 

3610 

3611 expected_api_args = { 

3612 'volume-type': volume_type, 

3613 'junction-path': '/fake_share', 

3614 'space-reserve': 'volume', 

3615 'snapshot-policy': snapshot_policy, 

3616 'language-code': language, 

3617 'percentage-snapshot-reserve': str(reserve), 

3618 'qos-policy-group-name': qos_name, 

3619 'qos-adaptive-policy-group-name': qos_adaptive_name, 

3620 'encrypt': 'true', 

3621 } 

3622 self.assertEqual(expected_api_args, result_api_args) 

3623 

3624 def test_get_create_volume_api_args_no_extra_specs(self): 

3625 

3626 self.client.features.add_feature('FLEXVOL_ENCRYPTION') 

3627 volume_type = 'dp' 

3628 thin_provisioned = False 

3629 snapshot_policy = None 

3630 language = None 

3631 reserve = None 

3632 qos_name = None 

3633 encrypt = False 

3634 qos_adaptive_name = None 

3635 

3636 result_api_args = self.client._get_create_volume_api_args( 

3637 fake.SHARE_NAME, thin_provisioned, snapshot_policy, language, 

3638 reserve, volume_type, qos_name, encrypt, qos_adaptive_name) 

3639 

3640 expected_api_args = { 

3641 'volume-type': volume_type, 

3642 'space-reserve': 'volume', 

3643 'encrypt': 'false' 

3644 } 

3645 self.assertEqual(expected_api_args, result_api_args) 

3646 

3647 def test_get_create_volume_api_args_encrypted_not_supported(self): 

3648 

3649 encrypt = True 

3650 self.assertRaises(exception.NetAppException, 

3651 self.client._get_create_volume_api_args, 

3652 fake.SHARE_NAME, True, 'default', 'en-US', 

3653 15, 'rw', 'fake_qos', encrypt, 'fake_qos_adaptive') 

3654 

3655 def test_is_flexvol_encrypted_unsupported(self): 

3656 

3657 self.client.features.add_feature('FLEXVOL_ENCRYPTION', supported=False) 

3658 

3659 result = self.client.is_flexvol_encrypted(fake.SHARE_NAME, 

3660 fake.VSERVER_NAME) 

3661 

3662 self.assertFalse(result) 

3663 

3664 def test_is_flexvol_encrypted_no_records_found(self): 

3665 

3666 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

3667 self.mock_object(self.client, 

3668 'send_iter_request', 

3669 mock.Mock(return_value=api_response)) 

3670 

3671 result = self.client.is_flexvol_encrypted(fake.SHARE_NAME, 

3672 fake.VSERVER_NAME) 

3673 

3674 self.assertFalse(result) 

3675 

3676 def test_is_flexvol_encrypted(self): 

3677 

3678 self.client.features.add_feature('FLEXVOL_ENCRYPTION', supported=True) 

3679 api_response = netapp_api.NaElement( 

3680 fake.GET_VOLUME_FOR_ENCRYPTED_RESPONSE) 

3681 self.mock_object(self.client, 

3682 'send_iter_request', 

3683 mock.Mock(return_value=api_response)) 

3684 

3685 result = self.client.is_flexvol_encrypted(fake.SHARE_NAME, 

3686 fake.VSERVER_NAME) 

3687 

3688 volume_get_iter_args = { 

3689 'query': { 

3690 'volume-attributes': { 

3691 'encrypt': 'true', 

3692 'volume-id-attributes': { 

3693 'name': fake.SHARE_NAME, 

3694 'owning-vserver-name': fake.VSERVER_NAME, 

3695 } 

3696 } 

3697 }, 

3698 'desired-attributes': { 

3699 'volume-attributes': { 

3700 'encrypt': None, 

3701 } 

3702 } 

3703 } 

3704 

3705 self.client.send_iter_request.assert_called_once_with( 

3706 'volume-get-iter', volume_get_iter_args) 

3707 

3708 self.assertTrue(result) 

3709 

3710 def test_is_flexvol_encrypted_8_x_system_version_response(self): 

3711 

3712 self.client.features.add_feature('FLEXVOL_ENCRYPTION', supported=True) 

3713 api_response = netapp_api.NaElement( 

3714 fake.GET_VOLUME_FOR_ENCRYPTED_OLD_SYS_VERSION_RESPONSE) 

3715 self.mock_object(self.client, 

3716 'send_iter_request', 

3717 mock.Mock(return_value=api_response)) 

3718 

3719 result = self.client.is_flexvol_encrypted(fake.SHARE_NAME, 

3720 fake.VSERVER_NAME) 

3721 

3722 volume_get_iter_args = { 

3723 'query': { 

3724 'volume-attributes': { 

3725 'encrypt': 'true', 

3726 'volume-id-attributes': { 

3727 'name': fake.SHARE_NAME, 

3728 'owning-vserver-name': fake.VSERVER_NAME, 

3729 } 

3730 } 

3731 }, 

3732 'desired-attributes': { 

3733 'volume-attributes': { 

3734 'encrypt': None, 

3735 } 

3736 } 

3737 } 

3738 

3739 self.client.send_iter_request.assert_called_once_with( 

3740 'volume-get-iter', volume_get_iter_args) 

3741 

3742 self.assertFalse(result) 

3743 

3744 def test_update_volume_snapshot_policy(self): 

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

3746 

3747 self.client.update_volume_snapshot_policy(fake.SHARE_NAME, 

3748 fake.SNAPSHOT_POLICY_NAME) 

3749 

3750 volume_modify_iter_api_args = { 

3751 'query': { 

3752 'volume-attributes': { 

3753 'volume-id-attributes': { 

3754 'name': fake.SHARE_NAME, 

3755 }, 

3756 }, 

3757 }, 

3758 'attributes': { 

3759 'volume-attributes': { 

3760 'volume-snapshot-attributes': { 

3761 'snapshot-policy': fake.SNAPSHOT_POLICY_NAME, 

3762 }, 

3763 }, 

3764 }, 

3765 } 

3766 

3767 self.client.send_request.assert_called_once_with( 

3768 'volume-modify-iter', volume_modify_iter_api_args) 

3769 

3770 def test_enable_dedup(self): 

3771 

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

3773 

3774 self.client.enable_dedup(fake.SHARE_NAME) 

3775 

3776 sis_enable_args = {'path': '/vol/%s' % fake.SHARE_NAME} 

3777 

3778 self.client.send_request.assert_called_once_with('sis-enable', 

3779 sis_enable_args) 

3780 

3781 def test_enable_dedup_already_enabled(self): 

3782 side_effect = netapp_api.NaApiError( 

3783 code=netapp_api.OPERATION_ALREADY_ENABLED, 

3784 message='It has already been enabled') 

3785 

3786 self.mock_object(self.client, 

3787 'send_request', 

3788 mock.Mock(side_effect=side_effect)) 

3789 

3790 self.client.enable_dedup(fake.SHARE_NAME) 

3791 

3792 sis_enable_args = {'path': '/vol/%s' % fake.SHARE_NAME} 

3793 

3794 self.client.send_request.assert_called_once_with('sis-enable', 

3795 sis_enable_args) 

3796 

3797 def test_enable_dedup_currently_active(self): 

3798 side_effect = netapp_api.NaApiError( 

3799 code=netapp_api.OPERATION_ALREADY_ENABLED, 

3800 message='The sis operation is currently active') 

3801 

3802 self.mock_object(self.client, 

3803 'send_request', 

3804 mock.Mock(side_effect=side_effect)) 

3805 

3806 self.assertRaises(exception.NetAppException, 

3807 self.client.enable_dedup, 

3808 fake.SHARE_NAME) 

3809 

3810 def test_disable_dedup(self): 

3811 

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

3813 

3814 self.client.disable_dedup(fake.SHARE_NAME) 

3815 

3816 sis_disable_args = {'path': '/vol/%s' % fake.SHARE_NAME} 

3817 

3818 self.client.send_request.assert_called_once_with('sis-disable', 

3819 sis_disable_args) 

3820 

3821 def test_disable_dedup_currently_active(self): 

3822 side_effect = netapp_api.NaApiError( 

3823 code=netapp_api.OPERATION_ALREADY_ENABLED, 

3824 message='The sis operation is currently active') 

3825 

3826 self.mock_object(self.client, 

3827 'send_request', 

3828 mock.Mock(side_effect=side_effect)) 

3829 

3830 self.assertRaises(exception.NetAppException, 

3831 self.client.disable_dedup, 

3832 fake.SHARE_NAME) 

3833 

3834 def test_enable_compression(self): 

3835 

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

3837 

3838 self.client.enable_compression(fake.SHARE_NAME) 

3839 

3840 sis_set_config_args = { 

3841 'path': '/vol/%s' % fake.SHARE_NAME, 

3842 'enable-compression': 'true' 

3843 } 

3844 

3845 self.client.send_request.assert_called_once_with('sis-set-config', 

3846 sis_set_config_args) 

3847 

3848 def test_disable_compression(self): 

3849 

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

3851 

3852 self.client.disable_compression(fake.SHARE_NAME) 

3853 

3854 sis_set_config_args = { 

3855 'path': '/vol/%s' % fake.SHARE_NAME, 

3856 'enable-compression': 'false' 

3857 } 

3858 

3859 self.client.send_request.assert_called_once_with('sis-set-config', 

3860 sis_set_config_args) 

3861 

3862 def test_enable_dedupe_async(self): 

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

3864 

3865 self.client.enable_dedupe_async(fake.SHARE_NAME) 

3866 

3867 sis_enable_args = {'volume-name': fake.SHARE_NAME} 

3868 self.client.send_request.assert_called_once_with( 

3869 'sis-enable-async', sis_enable_args) 

3870 

3871 def test_disable_dedupe_async(self): 

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

3873 

3874 self.client.disable_dedupe_async(fake.SHARE_NAME) 

3875 

3876 sis_enable_args = {'volume-name': fake.SHARE_NAME} 

3877 self.client.send_request.assert_called_once_with( 

3878 'sis-disable-async', sis_enable_args) 

3879 

3880 def test_enable_compression_async(self): 

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

3882 

3883 self.client.enable_compression_async(fake.SHARE_NAME) 

3884 

3885 sis_set_config_args = { 

3886 'volume-name': fake.SHARE_NAME, 

3887 'enable-compression': 'true' 

3888 } 

3889 self.client.send_request.assert_called_once_with( 

3890 'sis-set-config-async', sis_set_config_args) 

3891 

3892 def test_disable_compression_async(self): 

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

3894 

3895 self.client.disable_compression_async(fake.SHARE_NAME) 

3896 

3897 sis_set_config_args = { 

3898 'volume-name': fake.SHARE_NAME, 

3899 'enable-compression': 'false' 

3900 } 

3901 self.client.send_request.assert_called_once_with( 

3902 'sis-set-config-async', sis_set_config_args) 

3903 

3904 def test_apply_volume_efficiency_policy_with_policy(self): 

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

3906 self.client.apply_volume_efficiency_policy( 

3907 fake.SHARE_NAME, fake.VOLUME_EFFICIENCY_POLICY_NAME 

3908 ) 

3909 

3910 volume_efficiency_config_args = { 

3911 'path': '/vol/%s' % fake.SHARE_NAME, 

3912 'policy-name': fake.VOLUME_EFFICIENCY_POLICY_NAME 

3913 } 

3914 

3915 self.client.send_request.assert_called_once_with( 

3916 'sis-set-config', volume_efficiency_config_args) 

3917 

3918 def test_apply_volume_efficiency_policy_without_policy(self): 

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

3920 self.client.apply_volume_efficiency_policy( 

3921 fake.SHARE_NAME, None 

3922 ) 

3923 

3924 self.client.send_request.assert_not_called() 

3925 

3926 def test_apply_volume_efficiency_policy_async_with_policy(self): 

3927 self.mock_object(self.client.connection, 'send_request') 

3928 self.client.apply_volume_efficiency_policy_async( 

3929 fake.SHARE_NAME, fake.VOLUME_EFFICIENCY_POLICY_NAME 

3930 ) 

3931 

3932 volume_efficiency_config_args = { 

3933 'path': '/vol/%s' % fake.SHARE_NAME, 

3934 'policy-name': fake.VOLUME_EFFICIENCY_POLICY_NAME 

3935 } 

3936 

3937 self.client.connection.send_request.assert_called_once_with( 

3938 'sis-set-config-async', volume_efficiency_config_args) 

3939 

3940 def test_apply_volume_efficiency_policy_async_without_policy(self): 

3941 self.mock_object(self.client.connection, 'send_request') 

3942 self.client.apply_volume_efficiency_policy_async( 

3943 fake.SHARE_NAME 

3944 ) 

3945 

3946 self.client.connection.send_request.assert_not_called() 

3947 

3948 def test_get_volume_efficiency_status(self): 

3949 

3950 api_response = netapp_api.NaElement(fake.SIS_GET_ITER_RESPONSE) 

3951 self.mock_object(self.client, 

3952 'send_iter_request', 

3953 mock.Mock(return_value=api_response)) 

3954 

3955 result = self.client.get_volume_efficiency_status(fake.SHARE_NAME) 

3956 

3957 sis_get_iter_args = { 

3958 'query': { 

3959 'sis-status-info': { 

3960 'path': '/vol/%s' % fake.SHARE_NAME, 

3961 }, 

3962 }, 

3963 'desired-attributes': { 

3964 'sis-status-info': { 

3965 'state': None, 

3966 'is-compression-enabled': None, 

3967 }, 

3968 }, 

3969 } 

3970 self.client.send_iter_request.assert_has_calls([ 

3971 mock.call('sis-get-iter', sis_get_iter_args)]) 

3972 

3973 expected = {'dedupe': True, 'compression': True} 

3974 self.assertDictEqual(expected, result) 

3975 

3976 def test_get_volume_efficiency_status_not_found(self): 

3977 

3978 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

3979 self.mock_object(self.client, 

3980 'send_iter_request', 

3981 mock.Mock(return_value=api_response)) 

3982 

3983 result = self.client.get_volume_efficiency_status(fake.SHARE_NAME) 

3984 

3985 expected = {'dedupe': False, 'compression': False} 

3986 self.assertDictEqual(expected, result) 

3987 

3988 def test_set_volume_max_files(self): 

3989 

3990 api_response = netapp_api.NaElement(fake.VOLUME_MODIFY_ITER_RESPONSE) 

3991 self.mock_object(self.client, 

3992 'send_request', 

3993 mock.Mock(return_value=api_response)) 

3994 

3995 self.client.set_volume_max_files(fake.SHARE_NAME, fake.MAX_FILES) 

3996 

3997 volume_modify_iter_api_args = { 

3998 'query': { 

3999 'volume-attributes': { 

4000 'volume-id-attributes': { 

4001 'name': fake.SHARE_NAME, 

4002 }, 

4003 }, 

4004 }, 

4005 'attributes': { 

4006 'volume-attributes': { 

4007 'volume-inode-attributes': { 

4008 'files-total': fake.MAX_FILES, 

4009 }, 

4010 }, 

4011 }, 

4012 } 

4013 

4014 self.client.send_request.assert_called_once_with( 

4015 'volume-modify-iter', volume_modify_iter_api_args) 

4016 

4017 def test_set_volume_name(self): 

4018 

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

4020 

4021 self.client.set_volume_name(fake.SHARE_NAME, 'new_name') 

4022 

4023 volume_rename_api_args = { 

4024 'volume': fake.SHARE_NAME, 

4025 'new-volume-name': 'new_name', 

4026 } 

4027 

4028 self.client.send_request.assert_called_once_with( 

4029 'volume-rename', volume_rename_api_args) 

4030 

4031 def test_rename_vserver(self): 

4032 

4033 vserver_api_args = { 

4034 'vserver-name': fake.VSERVER_NAME, 

4035 'new-name': fake.VSERVER_NAME_2, 

4036 } 

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

4038 

4039 self.client.rename_vserver(fake.VSERVER_NAME, fake.VSERVER_NAME_2) 

4040 

4041 self.client.send_request.assert_called_once_with( 

4042 'vserver-rename', vserver_api_args 

4043 ) 

4044 

4045 @ddt.data(True, False) 

4046 def test_modify_volume_no_optional_args(self, is_flexgroup): 

4047 

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

4049 mock_update_volume_efficiency_attributes = self.mock_object( 

4050 self.client, 'update_volume_efficiency_attributes') 

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

4052 mock.Mock(return_value=True)) 

4053 

4054 aggr = fake.SHARE_AGGREGATE_NAME 

4055 if is_flexgroup: 

4056 aggr = list(fake.SHARE_AGGREGATE_NAMES) 

4057 

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

4059 

4060 volume_modify_iter_api_args = { 

4061 'query': { 

4062 'volume-attributes': { 

4063 'volume-id-attributes': { 

4064 'name': fake.SHARE_NAME, 

4065 }, 

4066 }, 

4067 }, 

4068 'attributes': { 

4069 'volume-attributes': { 

4070 'volume-inode-attributes': {}, 

4071 'volume-language-attributes': {}, 

4072 'volume-snapshot-attributes': {}, 

4073 'volume-space-attributes': { 

4074 'space-guarantee': 'volume', 

4075 }, 

4076 'volume-autosize-attributes': {}, 

4077 }, 

4078 }, 

4079 } 

4080 

4081 if is_flexgroup: 

4082 volume_modify_iter_api_args['query']['volume-attributes'][ 

4083 'volume-id-attributes']['aggr-list'] = [ 

4084 {'aggr-name': aggr[0]}, {'aggr-name': aggr[1]}] 

4085 else: 

4086 volume_modify_iter_api_args['query']['volume-attributes'][ 

4087 'volume-id-attributes'][ 

4088 'containing-aggregate-name'] = aggr 

4089 

4090 self.client.send_request.assert_called_once_with( 

4091 'volume-modify-iter', volume_modify_iter_api_args) 

4092 mock_update_volume_efficiency_attributes.assert_called_once_with( 

4093 fake.SHARE_NAME, False, False, 

4094 is_flexgroup=is_flexgroup, efficiency_policy=None 

4095 ) 

4096 

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

4098 (None, fake.ADAPTIVE_QOS_POLICY_GROUP_NAME)) 

4099 @ddt.unpack 

4100 def test_modify_volume_all_optional_args(self, qos_group, 

4101 adaptive_qos_group): 

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

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

4104 mock_update_volume_efficiency_attributes = self.mock_object( 

4105 self.client, 'update_volume_efficiency_attributes') 

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

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

4108 mock.Mock(return_value=True)) 

4109 

4110 self.client.modify_volume( 

4111 fake.SHARE_AGGREGATE_NAME, 

4112 fake.SHARE_NAME, 

4113 thin_provisioned=True, 

4114 snapshot_policy=fake.SNAPSHOT_POLICY_NAME, 

4115 language=fake.LANGUAGE, 

4116 dedup_enabled=True, 

4117 compression_enabled=False, 

4118 max_files=fake.MAX_FILES, 

4119 qos_policy_group=qos_group, 

4120 adaptive_qos_policy_group=adaptive_qos_group, 

4121 autosize_attributes=fake.VOLUME_AUTOSIZE_ATTRS, 

4122 hide_snapdir=True, 

4123 **options 

4124 ) 

4125 

4126 volume_modify_iter_api_args = { 

4127 'query': { 

4128 'volume-attributes': { 

4129 'volume-id-attributes': { 

4130 'containing-aggregate-name': fake.SHARE_AGGREGATE_NAME, 

4131 'name': fake.SHARE_NAME, 

4132 }, 

4133 }, 

4134 }, 

4135 'attributes': { 

4136 'volume-attributes': { 

4137 'volume-inode-attributes': { 

4138 'files-total': fake.MAX_FILES, 

4139 }, 

4140 'volume-language-attributes': { 

4141 'language': fake.LANGUAGE, 

4142 }, 

4143 'volume-snapshot-attributes': { 

4144 'snapshot-policy': fake.SNAPSHOT_POLICY_NAME, 

4145 'snapdir-access-enabled': 'false' 

4146 }, 

4147 'volume-space-attributes': { 

4148 'space-guarantee': 'none', 

4149 }, 

4150 'volume-autosize-attributes': fake.VOLUME_AUTOSIZE_ATTRS, 

4151 }, 

4152 }, 

4153 } 

4154 if qos_group: 

4155 qos_update = { 

4156 'volume-qos-attributes': { 

4157 'policy-group-name': qos_group, 

4158 }, 

4159 } 

4160 volume_modify_iter_api_args[ 

4161 'attributes']['volume-attributes'].update(qos_update) 

4162 if adaptive_qos_group: 

4163 qos_update = { 

4164 'volume-qos-attributes': { 

4165 'adaptive-policy-group-name': adaptive_qos_group, 

4166 }, 

4167 } 

4168 volume_modify_iter_api_args[ 

4169 'attributes']['volume-attributes'].update(qos_update) 

4170 

4171 self.client.send_request.assert_called_once_with( 

4172 'volume-modify-iter', volume_modify_iter_api_args) 

4173 mock_update_volume_efficiency_attributes.assert_called_once_with( 

4174 fake.SHARE_NAME, True, False, 

4175 is_flexgroup=False, 

4176 efficiency_policy=fake.VOLUME_EFFICIENCY_POLICY_NAME 

4177 ) 

4178 

4179 @ddt.data( 

4180 {'existing': (True, True), 'desired': (True, True), 'fg': False, 

4181 'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}, 

4182 {'existing': (True, True), 'desired': (False, False), 'fg': False, 

4183 'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}, 

4184 {'existing': (True, True), 'desired': (True, False), 'fg': False, 

4185 'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}, 

4186 {'existing': (True, False), 'desired': (True, False), 'fg': False, 

4187 'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}, 

4188 {'existing': (True, False), 'desired': (False, False), 'fg': False, 

4189 'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}, 

4190 {'existing': (True, False), 'desired': (True, True), 'fg': False, 

4191 'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}, 

4192 {'existing': (False, False), 'desired': (False, False), 'fg': False, 

4193 'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}, 

4194 {'existing': (False, False), 'desired': (True, False), 'fg': False, 

4195 'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}, 

4196 {'existing': (False, False), 'desired': (True, True), 'fg': False, 

4197 'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}, 

4198 {'existing': (True, True), 'desired': (True, True), 'fg': True, 

4199 'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}, 

4200 {'existing': (True, True), 'desired': (False, False), 'fg': True, 

4201 'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}, 

4202 {'existing': (True, True), 'desired': (True, False), 'fg': True, 

4203 'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}, 

4204 {'existing': (True, False), 'desired': (True, False), 'fg': True, 

4205 'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}, 

4206 {'existing': (True, False), 'desired': (False, False), 'fg': True, 

4207 'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}, 

4208 {'existing': (True, False), 'desired': (True, True), 'fg': True, 

4209 'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}, 

4210 {'existing': (False, False), 'desired': (False, False), 'fg': True, 

4211 'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}, 

4212 {'existing': (False, False), 'desired': (True, False), 'fg': True, 

4213 'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}, 

4214 {'existing': (False, False), 'desired': (True, True), 'fg': True, 

4215 'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}, 

4216 ) 

4217 @ddt.unpack 

4218 def test_update_volume_efficiency_attributes(self, existing, desired, fg, 

4219 efficiency_policy): 

4220 

4221 existing_dedupe = existing[0] 

4222 existing_compression = existing[1] 

4223 desired_dedupe = desired[0] 

4224 desired_compression = desired[1] 

4225 

4226 self.mock_object( 

4227 self.client, 

4228 'get_volume_efficiency_status', 

4229 mock.Mock(return_value={'dedupe': existing_dedupe, 

4230 'compression': existing_compression})) 

4231 mock_enable_compression = self.mock_object(self.client, 

4232 'enable_compression') 

4233 mock_enable_compression_async = self.mock_object( 

4234 self.client, 'enable_compression_async') 

4235 mock_disable_compression = self.mock_object(self.client, 

4236 'disable_compression') 

4237 mock_disable_compression_async = self.mock_object( 

4238 self.client, 'disable_compression_async') 

4239 mock_enable_dedup = self.mock_object(self.client, 'enable_dedup') 

4240 mock_enable_dedup_async = self.mock_object(self.client, 

4241 'enable_dedupe_async') 

4242 mock_disable_dedup = self.mock_object(self.client, 'disable_dedup') 

4243 mock_disable_dedup_async = self.mock_object(self.client, 

4244 'disable_dedupe_async') 

4245 mock_apply_volume_efficiency_policy = ( 

4246 self.mock_object(self.client, 'apply_volume_efficiency_policy')) 

4247 mock_apply_volume_efficiency_policy_async = ( 

4248 self.mock_object(self.client, 

4249 'apply_volume_efficiency_policy_async' 

4250 ) 

4251 ) 

4252 

4253 self.client.update_volume_efficiency_attributes( 

4254 fake.SHARE_NAME, desired_dedupe, desired_compression, 

4255 is_flexgroup=fg, efficiency_policy=efficiency_policy) 

4256 

4257 if existing_dedupe == desired_dedupe: 

4258 if fg: 

4259 self.assertFalse(mock_enable_dedup_async.called) 

4260 self.assertFalse(mock_disable_dedup_async.called) 

4261 else: 

4262 self.assertFalse(mock_enable_dedup.called) 

4263 self.assertFalse(mock_disable_dedup.called) 

4264 elif existing_dedupe and not desired_dedupe: 

4265 if fg: 

4266 self.assertFalse(mock_enable_dedup_async.called) 

4267 self.assertTrue(mock_disable_dedup_async.called) 

4268 else: 

4269 self.assertFalse(mock_enable_dedup.called) 

4270 self.assertTrue(mock_disable_dedup.called) 

4271 elif not existing_dedupe and desired_dedupe: 4271 ↛ 4279line 4271 didn't jump to line 4279 because the condition on line 4271 was always true

4272 if fg: 

4273 self.assertTrue(mock_enable_dedup_async.called) 

4274 self.assertFalse(mock_disable_dedup_async.called) 

4275 else: 

4276 self.assertTrue(mock_enable_dedup.called) 

4277 self.assertFalse(mock_disable_dedup.called) 

4278 

4279 if existing_compression == desired_compression: 

4280 if fg: 

4281 self.assertFalse(mock_enable_compression_async.called) 

4282 self.assertFalse(mock_disable_compression_async.called) 

4283 else: 

4284 self.assertFalse(mock_enable_compression.called) 

4285 self.assertFalse(mock_disable_compression.called) 

4286 elif existing_compression and not desired_compression: 

4287 if fg: 

4288 self.assertFalse(mock_enable_compression_async.called) 

4289 self.assertTrue(mock_disable_compression_async.called) 

4290 else: 

4291 self.assertFalse(mock_enable_compression.called) 

4292 self.assertTrue(mock_disable_compression.called) 

4293 elif not existing_compression and desired_compression: 4293 ↛ 4301line 4293 didn't jump to line 4301 because the condition on line 4293 was always true

4294 if fg: 

4295 self.assertTrue(mock_enable_compression_async.called) 

4296 self.assertFalse(mock_disable_compression_async.called) 

4297 else: 

4298 self.assertTrue(mock_enable_compression.called) 

4299 self.assertFalse(mock_disable_compression.called) 

4300 

4301 if fg: 

4302 self.assertTrue(mock_apply_volume_efficiency_policy_async.called) 

4303 else: 

4304 self.assertTrue(mock_apply_volume_efficiency_policy.called) 

4305 

4306 def test_set_volume_size(self): 

4307 

4308 api_response = netapp_api.NaElement(fake.VOLUME_MODIFY_ITER_RESPONSE) 

4309 self.mock_object(self.client, 

4310 'send_request', 

4311 mock.Mock(return_value=api_response)) 

4312 

4313 self.client.set_volume_size(fake.SHARE_NAME, 10) 

4314 

4315 volume_modify_iter_args = { 

4316 'query': { 

4317 'volume-attributes': { 

4318 'volume-id-attributes': { 

4319 'name': fake.SHARE_NAME 

4320 } 

4321 } 

4322 }, 

4323 'attributes': { 

4324 'volume-attributes': { 

4325 'volume-space-attributes': { 

4326 'size': 10737418240, 

4327 }, 

4328 }, 

4329 }, 

4330 } 

4331 self.client.send_request.assert_has_calls([ 

4332 mock.call('volume-modify-iter', volume_modify_iter_args)]) 

4333 

4334 @ddt.data(True, False) 

4335 def test_set_volume_snapdir_access(self, hide_snapdir): 

4336 api_response = netapp_api.NaElement( 

4337 fake.VOLUME_MODIFY_ITER_RESPONSE) 

4338 self.mock_object(self.client, 

4339 'send_request', 

4340 mock.Mock(return_value=api_response)) 

4341 

4342 self.client.set_volume_snapdir_access(fake.SHARE_NAME, hide_snapdir) 

4343 

4344 api_args = { 

4345 'query': { 

4346 'volume-attributes': { 

4347 'volume-id-attributes': { 

4348 'name': fake.SHARE_NAME 

4349 } 

4350 } 

4351 }, 

4352 'attributes': { 

4353 'volume-attributes': { 

4354 'volume-snapshot-attributes': { 

4355 'snapdir-access-enabled': str( 

4356 not hide_snapdir).lower(), 

4357 }, 

4358 }, 

4359 }, 

4360 } 

4361 self.client.send_request.assert_called_once_with( 

4362 'volume-modify-iter', api_args) 

4363 

4364 def test_set_volume_snapdir_access_api_error(self): 

4365 

4366 api_response = netapp_api.NaElement( 

4367 fake.VOLUME_MODIFY_ITER_ERROR_RESPONSE) 

4368 self.mock_object(self.client, 

4369 'send_request', 

4370 mock.Mock(return_value=api_response)) 

4371 

4372 self.assertRaises(netapp_api.NaApiError, 

4373 self.client.set_volume_size, 

4374 fake.SHARE_NAME, 

4375 10) 

4376 

4377 @ddt.data(True, False) 

4378 def test_set_volume_filesys_size_fixed(self, filesys_size_fixed): 

4379 api_response = netapp_api.NaElement( 

4380 fake.VOLUME_MODIFY_ITER_RESPONSE) 

4381 self.mock_object(self.client, 

4382 'send_request', 

4383 mock.Mock(return_value=api_response)) 

4384 

4385 self.client.set_volume_filesys_size_fixed(fake.SHARE_NAME, 

4386 filesys_size_fixed) 

4387 

4388 api_args = { 

4389 'query': { 

4390 'volume-attributes': { 

4391 'volume-id-attributes': { 

4392 'name': fake.SHARE_NAME 

4393 } 

4394 } 

4395 }, 

4396 'attributes': { 

4397 'volume-attributes': { 

4398 'volume-space-attributes': { 

4399 'is-filesys-size-fixed': str( 

4400 filesys_size_fixed).lower(), 

4401 }, 

4402 }, 

4403 }, 

4404 } 

4405 self.client.send_request.assert_called_once_with( 

4406 'volume-modify-iter', api_args) 

4407 

4408 def test_set_volume_size_api_error(self): 

4409 

4410 api_response = netapp_api.NaElement( 

4411 fake.VOLUME_MODIFY_ITER_ERROR_RESPONSE) 

4412 self.mock_object(self.client, 

4413 'send_request', 

4414 mock.Mock(return_value=api_response)) 

4415 

4416 self.assertRaises(netapp_api.NaApiError, 

4417 self.client.set_volume_size, 

4418 fake.SHARE_NAME, 

4419 10) 

4420 

4421 @ddt.data(None, 'ntfs') 

4422 def test_set_volume_security_style(self, security_style): 

4423 

4424 api_response = netapp_api.NaElement(fake.VOLUME_MODIFY_ITER_RESPONSE) 

4425 self.mock_object(self.client, 

4426 'send_request', 

4427 mock.Mock(return_value=api_response)) 

4428 kwargs = {'security_style': security_style} if security_style else {} 

4429 

4430 self.client.set_volume_security_style(fake.SHARE_NAME, **kwargs) 

4431 

4432 volume_modify_iter_args = { 

4433 'query': { 

4434 'volume-attributes': { 

4435 'volume-id-attributes': { 

4436 'name': fake.SHARE_NAME 

4437 } 

4438 } 

4439 }, 

4440 'attributes': { 

4441 'volume-attributes': { 

4442 'volume-security-attributes': { 

4443 'style': security_style or 'unix', 

4444 }, 

4445 }, 

4446 }, 

4447 } 

4448 self.client.send_request.assert_called_once_with( 

4449 'volume-modify-iter', volume_modify_iter_args) 

4450 

4451 def test_set_volume_security_style_api_error(self): 

4452 

4453 api_response = netapp_api.NaElement( 

4454 fake.VOLUME_MODIFY_ITER_ERROR_RESPONSE) 

4455 self.mock_object(self.client, 

4456 'send_request', 

4457 mock.Mock(return_value=api_response)) 

4458 

4459 self.assertRaises(netapp_api.NaApiError, 

4460 self.client.set_volume_security_style, 

4461 fake.SHARE_NAME, 

4462 'ntfs') 

4463 

4464 def test_volume_exists(self): 

4465 

4466 api_response = netapp_api.NaElement(fake.VOLUME_GET_NAME_RESPONSE) 

4467 self.mock_object(self.client, 

4468 'send_iter_request', 

4469 mock.Mock(return_value=api_response)) 

4470 

4471 result = self.client.volume_exists(fake.SHARE_NAME) 

4472 

4473 volume_get_iter_args = { 

4474 'query': { 

4475 'volume-attributes': { 

4476 'volume-id-attributes': { 

4477 'name': fake.SHARE_NAME 

4478 } 

4479 } 

4480 }, 

4481 'desired-attributes': { 

4482 'volume-attributes': { 

4483 'volume-id-attributes': { 

4484 'name': None 

4485 } 

4486 } 

4487 } 

4488 } 

4489 

4490 self.client.send_iter_request.assert_has_calls([ 

4491 mock.call('volume-get-iter', volume_get_iter_args)]) 

4492 self.assertTrue(result) 

4493 

4494 def test_volume_exists_not_found(self): 

4495 

4496 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

4497 self.mock_object(self.client, 

4498 'send_request', 

4499 mock.Mock(return_value=api_response)) 

4500 

4501 self.assertFalse(self.client.volume_exists(fake.SHARE_NAME)) 

4502 

4503 def test_snapshot_exists(self): 

4504 

4505 api_response = netapp_api.NaElement(fake.VOLUME_GET_NAME_RESPONSE) 

4506 self.mock_object(self.client, 

4507 'send_request', 

4508 mock.Mock(return_value=api_response)) 

4509 

4510 result = self.client.snapshot_exists(fake.SNAPSHOT_NAME, 

4511 fake.SHARE_NAME) 

4512 

4513 snapshot_get_iter_args = { 

4514 'query': { 

4515 'snapshot-info': { 

4516 'name': fake.SNAPSHOT_NAME, 

4517 'volume': fake.SHARE_NAME, 

4518 } 

4519 }, 

4520 'desired-attributes': { 

4521 'snapshot-info': { 

4522 'name': None, 

4523 'volume': None, 

4524 'busy': None, 

4525 'snapshot-owners-list': { 

4526 'snapshot-owner': None, 

4527 } 

4528 } 

4529 } 

4530 } 

4531 

4532 self.client.send_request.assert_has_calls([ 

4533 mock.call('snapshot-get-iter', snapshot_get_iter_args)]) 

4534 self.assertTrue(result) 

4535 

4536 def test_snapshot_exists_not_found(self): 

4537 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

4538 self.mock_object(self.client, 

4539 'send_request', 

4540 mock.Mock(return_value=api_response)) 

4541 

4542 self.assertFalse(self.client.snapshot_exists(fake.SNAPSHOT_NAME, 

4543 fake.SHARE_NAME)) 

4544 

4545 @ddt.data({ 

4546 'api_response_xml': fake.SNAPSHOT_GET_ITER_UNAVAILABLE_RESPONSE, 

4547 'raised_exception': exception.SnapshotUnavailable, 

4548 }, { 

4549 'api_response_xml': fake.SNAPSHOT_GET_ITER_OTHER_ERROR_RESPONSE, 

4550 'raised_exception': exception.NetAppException, 

4551 }) 

4552 @ddt.unpack 

4553 def test_snapshot_exists_error(self, api_response_xml, raised_exception): 

4554 

4555 api_response = netapp_api.NaElement(api_response_xml) 

4556 self.mock_object(self.client, 

4557 'send_request', 

4558 mock.Mock(return_value=api_response)) 

4559 

4560 self.assertRaises(raised_exception, 

4561 self.client.snapshot_exists, 

4562 fake.SNAPSHOT_NAME, 

4563 fake.SHARE_NAME) 

4564 

4565 @ddt.data(True, False) 

4566 def test_get_aggregate_for_volume(self, is_flexgroup): 

4567 

4568 api_response = netapp_api.NaElement( 

4569 fake.GET_AGGREGATE_FOR_FLEXGROUP_VOL_RESPONSE if is_flexgroup 

4570 else fake.GET_AGGREGATE_FOR_VOLUME_RESPONSE) 

4571 self.mock_object(self.client, 

4572 'send_iter_request', 

4573 mock.Mock(return_value=api_response)) 

4574 

4575 result = self.client.get_aggregate_for_volume(fake.SHARE_NAME) 

4576 

4577 volume_get_iter_args = { 

4578 'query': { 

4579 'volume-attributes': { 

4580 'volume-id-attributes': { 

4581 'name': fake.SHARE_NAME 

4582 } 

4583 } 

4584 }, 

4585 'desired-attributes': { 

4586 'volume-attributes': { 

4587 'volume-id-attributes': { 

4588 'aggr-list': { 

4589 'aggr-name': None, 

4590 }, 

4591 'containing-aggregate-name': None, 

4592 'name': None 

4593 } 

4594 } 

4595 } 

4596 } 

4597 

4598 self.client.send_iter_request.assert_has_calls([ 

4599 mock.call('volume-get-iter', volume_get_iter_args)]) 

4600 if is_flexgroup: 

4601 self.assertEqual([fake.SHARE_AGGREGATE_NAME], result) 

4602 else: 

4603 self.assertEqual(fake.SHARE_AGGREGATE_NAME, result) 

4604 

4605 def test_get_aggregate_for_volume_not_found(self): 

4606 

4607 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

4608 self.mock_object(self.client, 

4609 'send_iter_request', 

4610 mock.Mock(return_value=api_response)) 

4611 

4612 self.assertRaises(exception.NetAppException, 

4613 self.client.get_aggregate_for_volume, 

4614 fake.SHARE_NAME) 

4615 

4616 def test_volume_has_luns(self): 

4617 

4618 api_response = netapp_api.NaElement(fake.LUN_GET_ITER_RESPONSE) 

4619 self.mock_object(self.client, 

4620 'send_iter_request', 

4621 mock.Mock(return_value=api_response)) 

4622 

4623 result = self.client.volume_has_luns(fake.SHARE_NAME) 

4624 

4625 lun_get_iter_args = { 

4626 'query': { 

4627 'lun-info': { 

4628 'volume': fake.SHARE_NAME, 

4629 }, 

4630 }, 

4631 'desired-attributes': { 

4632 'lun-info': { 

4633 'path': None, 

4634 }, 

4635 }, 

4636 } 

4637 

4638 self.client.send_iter_request.assert_has_calls([ 

4639 mock.call('lun-get-iter', lun_get_iter_args)]) 

4640 self.assertTrue(result) 

4641 

4642 def test_volume_has_luns_not_found(self): 

4643 

4644 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

4645 self.mock_object(self.client, 

4646 'send_request', 

4647 mock.Mock(return_value=api_response)) 

4648 

4649 result = self.client.volume_has_luns(fake.SHARE_NAME) 

4650 

4651 self.assertFalse(result) 

4652 

4653 def test_volume_has_junctioned_volumes(self): 

4654 

4655 api_response = netapp_api.NaElement( 

4656 fake.VOLUME_GET_ITER_JUNCTIONED_VOLUMES_RESPONSE) 

4657 self.mock_object(self.client, 

4658 'send_iter_request', 

4659 mock.Mock(return_value=api_response)) 

4660 

4661 fake_junction_path = '/%s' % fake.SHARE_NAME 

4662 result = self.client.volume_has_junctioned_volumes(fake_junction_path) 

4663 

4664 volume_get_iter_args = { 

4665 'query': { 

4666 'volume-attributes': { 

4667 'volume-id-attributes': { 

4668 'junction-path': fake_junction_path + '/*', 

4669 }, 

4670 }, 

4671 }, 

4672 'desired-attributes': { 

4673 'volume-attributes': { 

4674 'volume-id-attributes': { 

4675 'name': None, 

4676 }, 

4677 }, 

4678 }, 

4679 } 

4680 self.client.send_iter_request.assert_has_calls([ 

4681 mock.call('volume-get-iter', volume_get_iter_args)]) 

4682 self.assertTrue(result) 

4683 

4684 def test_volume_has_junctioned_volumes_no_junction_path(self): 

4685 

4686 result = self.client.volume_has_junctioned_volumes(None) 

4687 

4688 self.assertFalse(result) 

4689 

4690 def test_volume_has_junctioned_volumes_not_found(self): 

4691 

4692 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

4693 self.mock_object(self.client, 

4694 'send_request', 

4695 mock.Mock(return_value=api_response)) 

4696 

4697 fake_junction_path = '/%s' % fake.SHARE_NAME 

4698 result = self.client.volume_has_junctioned_volumes(fake_junction_path) 

4699 

4700 self.assertFalse(result) 

4701 

4702 def test_get_volume_snapshot_attributes(self): 

4703 

4704 api_response = netapp_api.NaElement( 

4705 fake.VOLUME_GET_ITER_SNAPSHOT_ATTRIBUTES_RESPONSE) 

4706 self.mock_object(self.client, 

4707 'send_request', 

4708 mock.Mock(return_value=api_response)) 

4709 

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

4711 

4712 desired_snapshot_attributes = { 

4713 'snapshot-policy': None, 

4714 'snapdir-access-enabled': None, 

4715 } 

4716 snap_get_iter_args = { 

4717 'query': { 

4718 'volume-attributes': { 

4719 'volume-id-attributes': { 

4720 'name': fake.SHARE_NAME, 

4721 }, 

4722 }, 

4723 }, 

4724 'desired-attributes': { 

4725 'volume-attributes': { 

4726 'volume-snapshot-attributes': desired_snapshot_attributes, 

4727 }, 

4728 }, 

4729 } 

4730 

4731 self.client.send_request.assert_has_calls([ 

4732 mock.call('volume-get-iter', snap_get_iter_args)]) 

4733 

4734 expected = { 

4735 'snapshot-policy': 'daily', 'snapdir-access-enabled': 'false'} 

4736 self.assertDictEqual(expected, result) 

4737 

4738 @ddt.data(True, False) 

4739 def test_get_volume(self, is_flexgroup): 

4740 

4741 api_response = netapp_api.NaElement( 

4742 fake.VOLUME_GET_ITER_FLEXGROUP_VOLUME_TO_MANAGE_RESPONSE 

4743 if is_flexgroup 

4744 else fake.VOLUME_GET_ITER_VOLUME_TO_MANAGE_RESPONSE) 

4745 self.mock_object(self.client, 

4746 'send_request', 

4747 mock.Mock(return_value=api_response)) 

4748 

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

4750 

4751 volume_get_iter_args = { 

4752 'query': { 

4753 'volume-attributes': { 

4754 'volume-id-attributes': { 

4755 'name': fake.SHARE_NAME, 

4756 }, 

4757 }, 

4758 }, 

4759 'desired-attributes': { 

4760 'volume-attributes': { 

4761 'volume-id-attributes': { 

4762 'aggr-list': { 

4763 'aggr-name': None, 

4764 }, 

4765 'containing-aggregate-name': None, 

4766 'junction-path': None, 

4767 'name': None, 

4768 'owning-vserver-name': None, 

4769 'type': None, 

4770 'style': None, 

4771 'style-extended': None, 

4772 }, 

4773 'volume-space-attributes': { 

4774 'size': None, 

4775 'size-used': None, 

4776 }, 

4777 'volume-qos-attributes': { 

4778 'policy-group-name': None, 

4779 }, 

4780 'volume-snaplock-attributes': { 

4781 'snaplock-type': None, 

4782 }, 

4783 }, 

4784 }, 

4785 } 

4786 

4787 expected = { 

4788 'aggregate': '' if is_flexgroup else fake.SHARE_AGGREGATE_NAME, 

4789 'aggr-list': [fake.SHARE_AGGREGATE_NAME] if is_flexgroup else [], 

4790 'junction-path': '/%s' % fake.SHARE_NAME, 

4791 'name': fake.SHARE_NAME, 

4792 'type': 'rw', 

4793 'style': 'flex', 

4794 'size': fake.SHARE_SIZE, 

4795 'size-used': fake.SHARE_USED_SIZE, 

4796 'owning-vserver-name': fake.VSERVER_NAME, 

4797 'qos-policy-group-name': fake.QOS_POLICY_GROUP_NAME, 

4798 'style-extended': (fake.FLEXGROUP_STYLE_EXTENDED 

4799 if is_flexgroup 

4800 else fake.FLEXVOL_STYLE_EXTENDED), 

4801 'snaplock-type': 'compliance', 

4802 } 

4803 self.client.send_request.assert_has_calls([ 

4804 mock.call('volume-get-iter', volume_get_iter_args)]) 

4805 self.assertDictEqual(expected, result) 

4806 

4807 def test_get_volume_no_qos(self): 

4808 api_response = netapp_api.NaElement( 

4809 fake.VOLUME_GET_ITER_NO_QOS_RESPONSE) 

4810 self.mock_object(self.client, 

4811 'send_request', 

4812 mock.Mock(return_value=api_response)) 

4813 

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

4815 

4816 volume_get_iter_args = { 

4817 'query': { 

4818 'volume-attributes': { 

4819 'volume-id-attributes': { 

4820 'name': fake.SHARE_NAME, 

4821 }, 

4822 }, 

4823 }, 

4824 'desired-attributes': { 

4825 'volume-attributes': { 

4826 'volume-id-attributes': { 

4827 'aggr-list': { 

4828 'aggr-name': None, 

4829 }, 

4830 'containing-aggregate-name': None, 

4831 'junction-path': None, 

4832 'name': None, 

4833 'owning-vserver-name': None, 

4834 'type': None, 

4835 'style': None, 

4836 'style-extended': None, 

4837 }, 

4838 'volume-space-attributes': { 

4839 'size': None, 

4840 'size-used': None, 

4841 }, 

4842 'volume-qos-attributes': { 

4843 'policy-group-name': None, 

4844 }, 

4845 'volume-snaplock-attributes': { 

4846 'snaplock-type': None, 

4847 }, 

4848 }, 

4849 }, 

4850 } 

4851 

4852 expected = { 

4853 'aggregate': fake.SHARE_AGGREGATE_NAME, 

4854 'aggr-list': [], 

4855 'junction-path': '/%s' % fake.SHARE_NAME, 

4856 'name': fake.SHARE_NAME, 

4857 'type': 'rw', 

4858 'style': 'flex', 

4859 'size': fake.SHARE_SIZE, 

4860 'size-used': fake.SHARE_USED_SIZE, 

4861 'owning-vserver-name': fake.VSERVER_NAME, 

4862 'qos-policy-group-name': None, 

4863 'style-extended': fake.FLEXVOL_STYLE_EXTENDED, 

4864 'snaplock-type': "compliance", 

4865 } 

4866 self.client.send_request.assert_has_calls([ 

4867 mock.call('volume-get-iter', volume_get_iter_args)]) 

4868 self.assertDictEqual(expected, result) 

4869 

4870 def test_get_volume_not_found(self): 

4871 

4872 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

4873 self.mock_object(self.client, 

4874 'send_request', 

4875 mock.Mock(return_value=api_response)) 

4876 

4877 self.assertRaises(exception.StorageResourceNotFound, 

4878 self.client.get_volume, 

4879 fake.SHARE_NAME) 

4880 

4881 def test_get_volume_not_unique(self): 

4882 

4883 api_response = netapp_api.NaElement( 

4884 fake.VOLUME_GET_ITER_NOT_UNIQUE_RESPONSE) 

4885 self.mock_object(self.client, 

4886 'send_request', 

4887 mock.Mock(return_value=api_response)) 

4888 

4889 self.assertRaises(exception.NetAppException, 

4890 self.client.get_volume, 

4891 fake.SHARE_NAME) 

4892 

4893 def test_get_volume_at_junction_path(self): 

4894 

4895 api_response = netapp_api.NaElement( 

4896 fake.VOLUME_GET_ITER_VOLUME_TO_MANAGE_RESPONSE) 

4897 self.mock_object(self.client, 

4898 'send_iter_request', 

4899 mock.Mock(return_value=api_response)) 

4900 fake_junction_path = '/%s' % fake.SHARE_NAME 

4901 

4902 result = self.client.get_volume_at_junction_path(fake_junction_path) 

4903 

4904 volume_get_iter_args = { 

4905 'query': { 

4906 'volume-attributes': { 

4907 'volume-id-attributes': { 

4908 'junction-path': fake_junction_path, 

4909 'style-extended': 'flexgroup|flexvol', 

4910 }, 

4911 }, 

4912 }, 

4913 'desired-attributes': { 

4914 'volume-attributes': { 

4915 'volume-id-attributes': { 

4916 'name': None, 

4917 }, 

4918 }, 

4919 }, 

4920 } 

4921 expected = { 

4922 'name': fake.SHARE_NAME, 

4923 } 

4924 self.client.send_iter_request.assert_has_calls([ 

4925 mock.call('volume-get-iter', volume_get_iter_args)]) 

4926 self.assertDictEqual(expected, result) 

4927 

4928 def test_get_volume_at_junction_path_not_specified(self): 

4929 

4930 result = self.client.get_volume_at_junction_path(None) 

4931 

4932 self.assertIsNone(result) 

4933 

4934 def test_get_volume_at_junction_path_not_found(self): 

4935 

4936 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

4937 self.mock_object(self.client, 

4938 'send_iter_request', 

4939 mock.Mock(return_value=api_response)) 

4940 fake_junction_path = '/%s' % fake.SHARE_NAME 

4941 

4942 result = self.client.get_volume_at_junction_path(fake_junction_path) 

4943 

4944 self.assertIsNone(result) 

4945 

4946 @ddt.data(True, False) 

4947 def test_get_volume_to_manage(self, is_flexgroup): 

4948 

4949 api_response = netapp_api.NaElement( 

4950 fake.VOLUME_GET_ITER_FLEXGROUP_VOLUME_TO_MANAGE_RESPONSE 

4951 if is_flexgroup 

4952 else fake.VOLUME_GET_ITER_VOLUME_TO_MANAGE_RESPONSE) 

4953 self.mock_object(self.client, 

4954 'send_iter_request', 

4955 mock.Mock(return_value=api_response)) 

4956 

4957 aggr = fake.SHARE_AGGREGATE_NAME 

4958 result = self.client.get_volume_to_manage( 

4959 [aggr] if is_flexgroup else aggr, 

4960 fake.SHARE_NAME) 

4961 

4962 volume_get_iter_args = { 

4963 'query': { 

4964 'volume-attributes': { 

4965 'volume-id-attributes': { 

4966 'name': fake.SHARE_NAME, 

4967 }, 

4968 }, 

4969 }, 

4970 'desired-attributes': { 

4971 'volume-attributes': { 

4972 'volume-id-attributes': { 

4973 'aggr-list': { 

4974 'aggr-name': None, 

4975 }, 

4976 'containing-aggregate-name': None, 

4977 'junction-path': None, 

4978 'name': None, 

4979 'type': None, 

4980 'style': None, 

4981 'owning-vserver-name': None, 

4982 }, 

4983 'volume-space-attributes': { 

4984 'size': None, 

4985 }, 

4986 'volume-qos-attributes': { 

4987 'policy-group-name': None, 

4988 }, 

4989 }, 

4990 }, 

4991 } 

4992 if is_flexgroup: 

4993 volume_get_iter_args['query']['volume-attributes'][ 

4994 'volume-id-attributes']['aggr-list'] = [{'aggr-name': aggr}] 

4995 else: 

4996 volume_get_iter_args['query']['volume-attributes'][ 

4997 'volume-id-attributes']['containing-aggregate-name'] = aggr 

4998 

4999 expected = { 

5000 'aggregate': '' if is_flexgroup else aggr, 

5001 'aggr-list': [aggr] if is_flexgroup else [], 

5002 'junction-path': '/%s' % fake.SHARE_NAME, 

5003 'name': fake.SHARE_NAME, 

5004 'type': 'rw', 

5005 'style': 'flex', 

5006 'size': fake.SHARE_SIZE, 

5007 'owning-vserver-name': fake.VSERVER_NAME, 

5008 'qos-policy-group-name': fake.QOS_POLICY_GROUP_NAME, 

5009 } 

5010 self.client.send_iter_request.assert_has_calls([ 

5011 mock.call('volume-get-iter', volume_get_iter_args)]) 

5012 self.assertDictEqual(expected, result) 

5013 

5014 def test_get_volume_to_manage_not_found(self): 

5015 

5016 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

5017 self.mock_object(self.client, 

5018 'send_iter_request', 

5019 mock.Mock(return_value=api_response)) 

5020 

5021 result = self.client.get_volume_to_manage(fake.SHARE_AGGREGATE_NAME, 

5022 fake.SHARE_NAME) 

5023 

5024 self.assertIsNone(result) 

5025 

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

5027 'adaptive_qos_policy_group_name': None}, 

5028 {'qos_policy_group_name': fake.QOS_POLICY_GROUP_NAME, 

5029 'adaptive_qos_policy_group_name': None}, 

5030 {'qos_policy_group_name': None, 

5031 'adaptive_qos_policy_group_name': 

5032 fake.ADAPTIVE_QOS_POLICY_GROUP_NAME}, 

5033 {'mount_point_name': None}, 

5034 ) 

5035 @ddt.unpack 

5036 def test_create_volume_clone(self, qos_policy_group_name=None, 

5037 adaptive_qos_policy_group_name=None, 

5038 mount_point_name=None): 

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

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

5041 set_qos_adapt_mock = self.mock_object( 

5042 self.client, 

5043 'set_qos_adaptive_policy_group_for_volume') 

5044 

5045 self.client.create_volume_clone( 

5046 fake.SHARE_NAME, 

5047 fake.PARENT_SHARE_NAME, 

5048 fake.PARENT_SNAPSHOT_NAME, 

5049 mount_point_name=mount_point_name, 

5050 qos_policy_group=qos_policy_group_name, 

5051 adaptive_qos_policy_group=adaptive_qos_policy_group_name,) 

5052 

5053 volume_clone_create_args = { 

5054 'volume': fake.SHARE_NAME, 

5055 'parent-volume': fake.PARENT_SHARE_NAME, 

5056 'parent-snapshot': fake.PARENT_SNAPSHOT_NAME, 

5057 'junction-path': '/%s' % (mount_point_name or fake.SHARE_NAME) 

5058 } 

5059 

5060 if qos_policy_group_name: 

5061 volume_clone_create_args.update( 

5062 {'qos-policy-group-name': fake.QOS_POLICY_GROUP_NAME}) 

5063 if adaptive_qos_policy_group_name: 

5064 set_qos_adapt_mock.assert_called_once_with( 

5065 fake.SHARE_NAME, fake.ADAPTIVE_QOS_POLICY_GROUP_NAME 

5066 ) 

5067 

5068 @ddt.data(None, 

5069 mock.Mock(side_effect=netapp_api.NaApiError( 

5070 code=netapp_api.EVOL_CLONE_BEING_SPLIT))) 

5071 def test_volume_clone_split_start(self, side_effect): 

5072 

5073 self.mock_object( 

5074 self.client, 'send_request', 

5075 mock.Mock(side_effect=side_effect)) 

5076 

5077 self.client.volume_clone_split_start(fake.SHARE_NAME) 

5078 

5079 volume_clone_split_args = {'volume': fake.SHARE_NAME} 

5080 

5081 self.client.send_request.assert_has_calls([ 

5082 mock.call('volume-clone-split-start', volume_clone_split_args)]) 

5083 

5084 @ddt.data(None, 

5085 mock.Mock(side_effect=netapp_api.NaApiError( 

5086 code=netapp_api.EVOLOPNOTUNDERWAY))) 

5087 def test_volume_clone_split_stop(self, side_effect): 

5088 

5089 self.mock_object( 

5090 self.client, 'send_request', 

5091 mock.Mock(side_effect=side_effect)) 

5092 

5093 self.client.volume_clone_split_stop(fake.SHARE_NAME) 

5094 

5095 volume_clone_split_args = {'volume': fake.SHARE_NAME} 

5096 

5097 self.client.send_request.assert_has_calls([ 

5098 mock.call('volume-clone-split-stop', volume_clone_split_args)]) 

5099 

5100 def test_volume_clone_split_start_api_error(self): 

5101 

5102 self.mock_object(self.client, 

5103 'send_request', 

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

5105 

5106 self.assertRaises(netapp_api.NaApiError, 

5107 self.client.volume_clone_split_start, 

5108 fake.SHARE_NAME) 

5109 

5110 def test_get_clone_children_for_snapshot(self): 

5111 

5112 api_response = netapp_api.NaElement( 

5113 fake.VOLUME_GET_ITER_CLONE_CHILDREN_RESPONSE) 

5114 self.mock_object(self.client, 

5115 'send_iter_request', 

5116 mock.Mock(return_value=api_response)) 

5117 

5118 result = self.client.get_clone_children_for_snapshot( 

5119 fake.SHARE_NAME, fake.SNAPSHOT_NAME) 

5120 

5121 volume_get_iter_args = { 

5122 'query': { 

5123 'volume-attributes': { 

5124 'volume-clone-attributes': { 

5125 'volume-clone-parent-attributes': { 

5126 'name': fake.SHARE_NAME, 

5127 'snapshot-name': fake.SNAPSHOT_NAME, 

5128 }, 

5129 }, 

5130 }, 

5131 }, 

5132 'desired-attributes': { 

5133 'volume-attributes': { 

5134 'volume-id-attributes': { 

5135 'name': None, 

5136 }, 

5137 }, 

5138 }, 

5139 } 

5140 self.client.send_iter_request.assert_has_calls([ 

5141 mock.call('volume-get-iter', volume_get_iter_args)]) 

5142 

5143 expected = [ 

5144 {'name': fake.CLONE_CHILD_1}, 

5145 {'name': fake.CLONE_CHILD_2}, 

5146 ] 

5147 self.assertEqual(expected, result) 

5148 

5149 def test_get_clone_children_for_snapshot_not_found(self): 

5150 

5151 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

5152 self.mock_object(self.client, 

5153 'send_iter_request', 

5154 mock.Mock(return_value=api_response)) 

5155 

5156 result = self.client.get_clone_children_for_snapshot( 

5157 fake.SHARE_NAME, fake.SNAPSHOT_NAME) 

5158 

5159 self.assertEqual([], result) 

5160 

5161 def test_get_volume_junction_path(self): 

5162 

5163 api_response = netapp_api.NaElement( 

5164 fake.VOLUME_GET_VOLUME_PATH_RESPONSE) 

5165 self.mock_object(self.client, 

5166 'send_request', 

5167 mock.Mock(return_value=api_response)) 

5168 

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

5170 

5171 volume_get_volume_path_args = { 

5172 'volume': fake.SHARE_NAME, 

5173 'is-style-cifs': 'false' 

5174 } 

5175 

5176 self.client.send_request.assert_has_calls([ 

5177 mock.call('volume-get-volume-path', volume_get_volume_path_args)]) 

5178 self.assertEqual(fake.VOLUME_JUNCTION_PATH, result) 

5179 

5180 def test_get_volume_junction_path_cifs(self): 

5181 

5182 api_response = netapp_api.NaElement( 

5183 fake.VOLUME_GET_VOLUME_PATH_CIFS_RESPONSE) 

5184 self.mock_object(self.client, 

5185 'send_request', 

5186 mock.Mock(return_value=api_response)) 

5187 

5188 result = self.client.get_volume_junction_path(fake.SHARE_NAME, 

5189 is_style_cifs=True) 

5190 

5191 volume_get_volume_path_args = { 

5192 'volume': fake.SHARE_NAME, 

5193 'is-style-cifs': 'true' 

5194 } 

5195 

5196 self.client.send_request.assert_has_calls([ 

5197 mock.call('volume-get-volume-path', volume_get_volume_path_args)]) 

5198 self.assertEqual(fake.VOLUME_JUNCTION_PATH_CIFS, result) 

5199 

5200 def test_mount_volume_default_junction_path(self): 

5201 

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

5203 

5204 self.client.mount_volume(fake.SHARE_NAME) 

5205 

5206 volume_mount_args = { 

5207 'volume-name': fake.SHARE_NAME, 

5208 'junction-path': '/%s' % fake.SHARE_NAME, 

5209 } 

5210 

5211 self.client.send_request.assert_has_calls([ 

5212 mock.call('volume-mount', volume_mount_args)]) 

5213 

5214 def test_mount_volume(self): 

5215 

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

5217 fake_path = '/fake_path' 

5218 

5219 self.client.mount_volume(fake.SHARE_NAME, junction_path=fake_path) 

5220 

5221 volume_mount_args = { 

5222 'volume-name': fake.SHARE_NAME, 

5223 'junction-path': fake_path, 

5224 } 

5225 

5226 self.client.send_request.assert_has_calls([ 

5227 mock.call('volume-mount', volume_mount_args)]) 

5228 

5229 def test_online_volume(self): 

5230 

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

5232 

5233 self.client.online_volume(fake.SHARE_NAME) 

5234 

5235 volume_online_args = {'name': fake.SHARE_NAME} 

5236 

5237 self.client.send_request.assert_has_calls([ 

5238 mock.call('volume-online', volume_online_args)]) 

5239 

5240 def test_online_volume_api_error(self): 

5241 

5242 self.mock_object(self.client, 

5243 'send_request', 

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

5245 

5246 self.assertRaises(exception.NetAppException, 

5247 self.client.online_volume, 

5248 fake.SHARE_NAME) 

5249 

5250 def test_offline_volume(self): 

5251 

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

5253 

5254 self.client.offline_volume(fake.SHARE_NAME) 

5255 

5256 volume_offline_args = {'name': fake.SHARE_NAME} 

5257 

5258 self.client.send_request.assert_has_calls([ 

5259 mock.call('volume-offline', volume_offline_args)]) 

5260 

5261 def test_offline_volume_already_offline(self): 

5262 

5263 self.mock_object(self.client, 

5264 'send_request', 

5265 mock.Mock(side_effect=self._mock_api_error( 

5266 netapp_api.EVOLUMEOFFLINE))) 

5267 

5268 self.client.offline_volume(fake.SHARE_NAME) 

5269 

5270 volume_offline_args = {'name': fake.SHARE_NAME} 

5271 

5272 self.client.send_request.assert_has_calls([ 

5273 mock.call('volume-offline', volume_offline_args)]) 

5274 

5275 def test_offline_volume_api_error(self): 

5276 

5277 self.mock_object(self.client, 

5278 'send_request', 

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

5280 

5281 self.assertRaises(exception.NetAppException, 

5282 self.client.offline_volume, 

5283 fake.SHARE_NAME) 

5284 

5285 def test__unmount_volume(self): 

5286 

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

5288 

5289 self.client._unmount_volume(fake.SHARE_NAME) 

5290 

5291 volume_unmount_args = { 

5292 'volume-name': fake.SHARE_NAME, 

5293 'force': 'false' 

5294 } 

5295 

5296 self.client.send_request.assert_has_calls([ 

5297 mock.call('volume-unmount', volume_unmount_args)]) 

5298 

5299 def test__unmount_volume_force(self): 

5300 

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

5302 

5303 self.client._unmount_volume(fake.SHARE_NAME, force=True) 

5304 

5305 volume_unmount_args = {'volume-name': fake.SHARE_NAME, 'force': 'true'} 

5306 

5307 self.client.send_request.assert_has_calls([ 

5308 mock.call('volume-unmount', volume_unmount_args)]) 

5309 

5310 def test__unmount_volume_already_unmounted(self): 

5311 

5312 self.mock_object(self.client, 

5313 'send_request', 

5314 mock.Mock(side_effect=self._mock_api_error( 

5315 netapp_api.EVOL_NOT_MOUNTED))) 

5316 

5317 self.client._unmount_volume(fake.SHARE_NAME, force=True) 

5318 

5319 volume_unmount_args = {'volume-name': fake.SHARE_NAME, 'force': 'true'} 

5320 

5321 self.client.send_request.assert_has_calls([ 

5322 mock.call('volume-unmount', volume_unmount_args)]) 

5323 

5324 def test__unmount_volume_api_error(self): 

5325 

5326 self.mock_object(self.client, 

5327 'send_request', 

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

5329 

5330 self.assertRaises(netapp_api.NaApiError, 

5331 self.client._unmount_volume, 

5332 fake.SHARE_NAME, 

5333 force=True) 

5334 

5335 def test_unmount_volume(self): 

5336 

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

5338 

5339 self.client.unmount_volume(fake.SHARE_NAME) 

5340 

5341 self.client._unmount_volume.assert_called_once_with(fake.SHARE_NAME, 

5342 force=False) 

5343 self.assertEqual(1, client_cmode.LOG.debug.call_count) 

5344 self.assertEqual(0, client_cmode.LOG.warning.call_count) 

5345 

5346 def test_unmount_volume_api_error(self): 

5347 

5348 self.mock_object(self.client, 

5349 '_unmount_volume', 

5350 self._mock_api_error()) 

5351 

5352 self.assertRaises(netapp_api.NaApiError, 

5353 self.client.unmount_volume, 

5354 fake.SHARE_NAME) 

5355 

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

5357 self.assertEqual(0, client_cmode.LOG.debug.call_count) 

5358 self.assertEqual(0, client_cmode.LOG.warning.call_count) 

5359 

5360 def test_unmount_volume_with_retries(self): 

5361 

5362 side_effect = [netapp_api.NaApiError(code=netapp_api.EAPIERROR, 

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

5364 side_effect.append(None) 

5365 self.mock_object(self.client, 

5366 '_unmount_volume', 

5367 mock.Mock(side_effect=side_effect)) 

5368 self.mock_object(time, 'sleep') 

5369 

5370 self.client.unmount_volume(fake.SHARE_NAME) 

5371 

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

5373 self.assertEqual(1, client_cmode.LOG.debug.call_count) 

5374 self.assertEqual(5, client_cmode.LOG.warning.call_count) 

5375 

5376 def test_unmount_volume_with_max_retries(self): 

5377 

5378 side_effect = [netapp_api.NaApiError(code=netapp_api.EAPIERROR, 

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

5380 self.mock_object(self.client, 

5381 '_unmount_volume', 

5382 mock.Mock(side_effect=side_effect)) 

5383 self.mock_object(time, 'sleep') 

5384 

5385 self.assertRaises(exception.NetAppException, 

5386 self.client.unmount_volume, 

5387 fake.SHARE_NAME) 

5388 

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

5390 self.assertEqual(0, client_cmode.LOG.debug.call_count) 

5391 self.assertEqual(10, client_cmode.LOG.warning.call_count) 

5392 

5393 def test_delete_volume(self): 

5394 

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

5396 

5397 self.client.delete_volume(fake.SHARE_NAME) 

5398 

5399 volume_destroy_args = {'name': fake.SHARE_NAME} 

5400 self.client.send_request.assert_has_calls([ 

5401 mock.call('volume-destroy', volume_destroy_args)]) 

5402 

5403 def test_rename_volume(self): 

5404 

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

5406 

5407 self.client.rename_volume( 

5408 fake.SHARE_NAME, 

5409 client_cmode.DELETED_PREFIX + fake.SHARE_NAME) 

5410 volume_rename_args = { 

5411 'volume': fake.SHARE_NAME, 

5412 'new-volume-name': client_cmode.DELETED_PREFIX + fake.SHARE_NAME, 

5413 } 

5414 self.client.send_request.assert_has_calls([ 

5415 mock.call('volume-rename', volume_rename_args)]) 

5416 

5417 def test_soft_delete_volume(self): 

5418 

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

5420 

5421 self.client.soft_delete_volume(fake.SHARE_NAME) 

5422 

5423 volume_destroy_args = {'name': fake.SHARE_NAME} 

5424 self.client.send_request.assert_has_calls([ 

5425 mock.call('volume-destroy', volume_destroy_args)]) 

5426 

5427 def test_soft_delete_volume_error(self): 

5428 

5429 self.mock_object( 

5430 self.client, 'send_request', 

5431 self._mock_api_error(code=netapp_api.EVOLDEL_NOT_ALLOW_BY_CLONE)) 

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

5433 

5434 self.client.soft_delete_volume(fake.SHARE_NAME) 

5435 

5436 volume_destroy_args = {'name': fake.SHARE_NAME} 

5437 self.client.send_request.assert_has_calls([ 

5438 mock.call('volume-destroy', volume_destroy_args)]) 

5439 mock_rename.assert_called_once_with( 

5440 fake.SHARE_NAME, client_cmode.DELETED_PREFIX + fake.SHARE_NAME) 

5441 

5442 def test_create_snapshot(self): 

5443 

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

5445 

5446 self.client.create_snapshot(fake.SHARE_NAME, fake.SNAPSHOT_NAME) 

5447 

5448 snapshot_create_args = { 

5449 'volume': fake.SHARE_NAME, 

5450 'snapshot': fake.SNAPSHOT_NAME 

5451 } 

5452 

5453 self.client.send_request.assert_has_calls([ 

5454 mock.call('snapshot-create', snapshot_create_args)]) 

5455 

5456 @ddt.data({ 

5457 'mock_return': fake.SNAPSHOT_GET_ITER_NOT_BUSY_RESPONSE, 

5458 'expected': { 

5459 'access-time': fake.SNAPSHOT_ACCESS_TIME, 

5460 'name': fake.SNAPSHOT_NAME, 

5461 'volume': fake.SHARE_NAME, 

5462 'busy': False, 

5463 'owners': set(), 

5464 'locked_by_clone': False, 

5465 } 

5466 }, { 

5467 'mock_return': fake.SNAPSHOT_GET_ITER_BUSY_RESPONSE, 

5468 'expected': { 

5469 'access-time': fake.SNAPSHOT_ACCESS_TIME, 

5470 'name': fake.SNAPSHOT_NAME, 

5471 'volume': fake.SHARE_NAME, 

5472 'busy': True, 

5473 'owners': {'volume clone'}, 

5474 'locked_by_clone': True, 

5475 } 

5476 }) 

5477 @ddt.unpack 

5478 def test_get_snapshot(self, mock_return, expected): 

5479 

5480 api_response = netapp_api.NaElement(mock_return) 

5481 self.mock_object(self.client, 

5482 'send_request', 

5483 mock.Mock(return_value=api_response)) 

5484 

5485 result = self.client.get_snapshot(fake.SHARE_NAME, fake.SNAPSHOT_NAME) 

5486 

5487 snapshot_get_iter_args = { 

5488 'query': { 

5489 'snapshot-info': { 

5490 'name': fake.SNAPSHOT_NAME, 

5491 'volume': fake.SHARE_NAME, 

5492 }, 

5493 }, 

5494 'desired-attributes': { 

5495 'snapshot-info': { 

5496 'access-time': None, 

5497 'name': None, 

5498 'volume': None, 

5499 'busy': None, 

5500 'snapshot-owners-list': { 

5501 'snapshot-owner': None, 

5502 } 

5503 }, 

5504 }, 

5505 } 

5506 self.client.send_request.assert_has_calls([ 

5507 mock.call('snapshot-get-iter', snapshot_get_iter_args)]) 

5508 self.assertDictEqual(expected, result) 

5509 

5510 @ddt.data({ 

5511 'api_response_xml': fake.NO_RECORDS_RESPONSE, 

5512 'raised_exception': exception.SnapshotResourceNotFound, 

5513 }, { 

5514 'api_response_xml': fake.SNAPSHOT_GET_ITER_NOT_UNIQUE_RESPONSE, 

5515 'raised_exception': exception.NetAppException, 

5516 }, { 

5517 'api_response_xml': fake.SNAPSHOT_GET_ITER_UNAVAILABLE_RESPONSE, 

5518 'raised_exception': exception.SnapshotUnavailable, 

5519 }, { 

5520 'api_response_xml': fake.SNAPSHOT_GET_ITER_OTHER_ERROR_RESPONSE, 

5521 'raised_exception': exception.NetAppException, 

5522 }) 

5523 @ddt.unpack 

5524 def test_get_snapshot_error(self, api_response_xml, raised_exception): 

5525 

5526 api_response = netapp_api.NaElement(api_response_xml) 

5527 self.mock_object(self.client, 

5528 'send_request', 

5529 mock.Mock(return_value=api_response)) 

5530 

5531 self.assertRaises(raised_exception, 

5532 self.client.get_snapshot, 

5533 fake.SHARE_NAME, 

5534 fake.SNAPSHOT_NAME) 

5535 

5536 def test_rename_snapshot(self): 

5537 

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

5539 

5540 self.client.rename_snapshot(fake.SHARE_NAME, 

5541 fake.SNAPSHOT_NAME, 

5542 'new_snapshot_name') 

5543 

5544 snapshot_rename_args = { 

5545 'volume': fake.SHARE_NAME, 

5546 'current-name': fake.SNAPSHOT_NAME, 

5547 'new-name': 'new_snapshot_name' 

5548 } 

5549 self.client.send_request.assert_has_calls([ 

5550 mock.call('snapshot-rename', snapshot_rename_args)]) 

5551 

5552 def test_restore_snapshot(self): 

5553 

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

5555 

5556 self.client.restore_snapshot(fake.SHARE_NAME, 

5557 fake.SNAPSHOT_NAME) 

5558 

5559 snapshot_restore_args = { 

5560 'volume': fake.SHARE_NAME, 

5561 'snapshot': fake.SNAPSHOT_NAME, 

5562 } 

5563 self.client.send_request.assert_has_calls([ 

5564 mock.call('snapshot-restore-volume', snapshot_restore_args)]) 

5565 

5566 @ddt.data(True, False) 

5567 def test_delete_snapshot(self, ignore_owners): 

5568 

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

5570 

5571 self.client.delete_snapshot( 

5572 fake.SHARE_NAME, fake.SNAPSHOT_NAME, ignore_owners=ignore_owners) 

5573 

5574 snapshot_delete_args = { 

5575 'volume': fake.SHARE_NAME, 

5576 'snapshot': fake.SNAPSHOT_NAME, 

5577 'ignore-owners': 'true' if ignore_owners else 'false', 

5578 } 

5579 

5580 self.client.send_request.assert_has_calls([ 

5581 mock.call('snapshot-delete', snapshot_delete_args)]) 

5582 

5583 def test_soft_delete_snapshot(self): 

5584 

5585 mock_delete_snapshot = self.mock_object(self.client, 'delete_snapshot') 

5586 mock_rename_snapshot = self.mock_object(self.client, 'rename_snapshot') 

5587 

5588 self.client.soft_delete_snapshot(fake.SHARE_NAME, fake.SNAPSHOT_NAME) 

5589 

5590 mock_delete_snapshot.assert_called_once_with( 

5591 fake.SHARE_NAME, fake.SNAPSHOT_NAME) 

5592 self.assertFalse(mock_rename_snapshot.called) 

5593 

5594 def test_soft_delete_snapshot_api_error(self): 

5595 

5596 mock_delete_snapshot = self.mock_object( 

5597 self.client, 'delete_snapshot', self._mock_api_error()) 

5598 mock_rename_snapshot = self.mock_object(self.client, 'rename_snapshot') 

5599 mock_get_clone_children_for_snapshot = self.mock_object( 

5600 self.client, 'get_clone_children_for_snapshot', 

5601 mock.Mock(return_value=fake.CDOT_CLONE_CHILDREN)) 

5602 mock_volume_clone_split_start = self.mock_object( 

5603 self.client, 'volume_clone_split_start') 

5604 

5605 self.client.soft_delete_snapshot(fake.SHARE_NAME, fake.SNAPSHOT_NAME) 

5606 

5607 mock_delete_snapshot.assert_called_once_with( 

5608 fake.SHARE_NAME, fake.SNAPSHOT_NAME) 

5609 mock_rename_snapshot.assert_called_once_with( 

5610 fake.SHARE_NAME, fake.SNAPSHOT_NAME, 

5611 'deleted_manila_' + fake.SNAPSHOT_NAME) 

5612 mock_get_clone_children_for_snapshot.assert_called_once_with( 

5613 fake.SHARE_NAME, 'deleted_manila_' + fake.SNAPSHOT_NAME) 

5614 mock_volume_clone_split_start.assert_has_calls([ 

5615 mock.call(fake.CDOT_CLONE_CHILD_1), 

5616 mock.call(fake.CDOT_CLONE_CHILD_2), 

5617 ]) 

5618 

5619 def test_prune_deleted_snapshots(self): 

5620 

5621 deleted_snapshots_map = { 

5622 'vserver1': [{ 

5623 'name': 'deleted_snap_1', 

5624 'volume': 'fake_volume_1', 

5625 'vserver': 'vserver1', 

5626 }], 

5627 'vserver2': [{ 

5628 'name': 'deleted_snap_2', 

5629 'volume': 'fake_volume_2', 

5630 'vserver': 'vserver2', 

5631 }], 

5632 } 

5633 mock_get_deleted_snapshots = self.mock_object( 

5634 self.client, '_get_deleted_snapshots', 

5635 mock.Mock(return_value=deleted_snapshots_map)) 

5636 mock_delete_snapshot = self.mock_object( 

5637 self.client, 'delete_snapshot', 

5638 mock.Mock(side_effect=[None, netapp_api.NaApiError])) 

5639 self.mock_object( 

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

5641 

5642 self.client.prune_deleted_snapshots() 

5643 

5644 mock_get_deleted_snapshots.assert_called_once_with() 

5645 mock_delete_snapshot.assert_has_calls([ 

5646 mock.call('fake_volume_1', 'deleted_snap_1'), 

5647 mock.call('fake_volume_2', 'deleted_snap_2'), 

5648 ], any_order=True) 

5649 

5650 def test_get_deleted_snapshots(self): 

5651 

5652 api_response = netapp_api.NaElement( 

5653 fake.SNAPSHOT_GET_ITER_DELETED_RESPONSE) 

5654 self.mock_object(self.client, 

5655 'send_iter_request', 

5656 mock.Mock(return_value=api_response)) 

5657 

5658 result = self.client._get_deleted_snapshots() 

5659 

5660 snapshot_get_iter_args = { 

5661 'query': { 

5662 'snapshot-info': { 

5663 'name': 'deleted_manila_*', 

5664 'busy': 'false', 

5665 }, 

5666 }, 

5667 'desired-attributes': { 

5668 'snapshot-info': { 

5669 'name': None, 

5670 'vserver': None, 

5671 'volume': None, 

5672 }, 

5673 }, 

5674 } 

5675 self.client.send_iter_request.assert_has_calls([ 

5676 mock.call('snapshot-get-iter', snapshot_get_iter_args)]) 

5677 

5678 expected = { 

5679 fake.VSERVER_NAME: [{ 

5680 'name': 'deleted_manila_' + fake.SNAPSHOT_NAME, 

5681 'volume': fake.SHARE_NAME, 

5682 'vserver': fake.VSERVER_NAME, 

5683 }], 

5684 } 

5685 self.assertDictEqual(expected, result) 

5686 

5687 def test_create_cg_snapshot(self): 

5688 

5689 mock_start_cg_snapshot = self.mock_object( 

5690 self.client, '_start_cg_snapshot', 

5691 mock.Mock(return_value=fake.CG_SNAPSHOT_ID)) 

5692 mock_commit_cg_snapshot = self.mock_object( 

5693 self.client, '_commit_cg_snapshot') 

5694 

5695 self.client.create_cg_snapshot([fake.SHARE_NAME, fake.SHARE_NAME_2], 

5696 fake.SNAPSHOT_NAME) 

5697 

5698 mock_start_cg_snapshot.assert_called_once_with( 

5699 [fake.SHARE_NAME, fake.SHARE_NAME_2], fake.SNAPSHOT_NAME) 

5700 mock_commit_cg_snapshot.assert_called_once_with(fake.CG_SNAPSHOT_ID) 

5701 

5702 def test_create_cg_snapshot_no_id(self): 

5703 

5704 mock_start_cg_snapshot = self.mock_object( 

5705 self.client, '_start_cg_snapshot', mock.Mock(return_value=None)) 

5706 mock_commit_cg_snapshot = self.mock_object( 

5707 self.client, '_commit_cg_snapshot') 

5708 

5709 self.assertRaises(exception.NetAppException, 

5710 self.client.create_cg_snapshot, 

5711 [fake.SHARE_NAME, fake.SHARE_NAME_2], 

5712 fake.SNAPSHOT_NAME) 

5713 

5714 mock_start_cg_snapshot.assert_called_once_with( 

5715 [fake.SHARE_NAME, fake.SHARE_NAME_2], fake.SNAPSHOT_NAME) 

5716 self.assertFalse(mock_commit_cg_snapshot.called) 

5717 

5718 def test_start_cg_snapshot(self): 

5719 

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

5721 

5722 self.client._start_cg_snapshot([fake.SHARE_NAME, fake.SHARE_NAME_2], 

5723 fake.SNAPSHOT_NAME) 

5724 

5725 cg_start_args = { 

5726 'snapshot': fake.SNAPSHOT_NAME, 

5727 'timeout': 'relaxed', 

5728 'volumes': [ 

5729 {'volume-name': fake.SHARE_NAME}, 

5730 {'volume-name': fake.SHARE_NAME_2}, 

5731 ], 

5732 } 

5733 

5734 self.client.send_request.assert_has_calls([ 

5735 mock.call('cg-start', cg_start_args)]) 

5736 

5737 def test_commit_cg_snapshot(self): 

5738 

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

5740 

5741 self.client._commit_cg_snapshot(fake.CG_SNAPSHOT_ID) 

5742 

5743 cg_commit_args = {'cg-id': fake.CG_SNAPSHOT_ID} 

5744 

5745 self.client.send_request.assert_has_calls([ 

5746 mock.call('cg-commit', cg_commit_args)]) 

5747 

5748 def test_create_cifs_share(self): 

5749 

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

5751 

5752 self.client.create_cifs_share( 

5753 fake.SHARE_NAME, fake.VOLUME_JUNCTION_PATH) 

5754 

5755 cifs_share_create_args = { 

5756 'path': fake.VOLUME_JUNCTION_PATH, 

5757 'share-name': fake.SHARE_NAME 

5758 } 

5759 

5760 self.client.send_request.assert_has_calls([ 

5761 mock.call('cifs-share-create', cifs_share_create_args)]) 

5762 

5763 def test_get_cifs_share_access(self): 

5764 

5765 api_response = netapp_api.NaElement( 

5766 fake.CIFS_SHARE_ACCESS_CONTROL_GET_ITER) 

5767 self.mock_object(self.client, 

5768 'send_iter_request', 

5769 mock.Mock(return_value=api_response)) 

5770 

5771 result = self.client.get_cifs_share_access(fake.SHARE_NAME) 

5772 

5773 cifs_share_access_control_get_iter_args = { 

5774 'query': { 

5775 'cifs-share-access-control': { 

5776 'share': fake.SHARE_NAME, 

5777 }, 

5778 }, 

5779 'desired-attributes': { 

5780 'cifs-share-access-control': { 

5781 'user-or-group': None, 

5782 'permission': None, 

5783 }, 

5784 }, 

5785 } 

5786 self.client.send_iter_request.assert_has_calls([ 

5787 mock.call('cifs-share-access-control-get-iter', 

5788 cifs_share_access_control_get_iter_args)]) 

5789 

5790 expected = { 

5791 'Administrator': 'full_control', 

5792 'Administrators': 'change', 

5793 'Power Users': 'read', 

5794 'Users': 'no_access', 

5795 } 

5796 self.assertDictEqual(expected, result) 

5797 

5798 def test_get_cifs_share_access_not_found(self): 

5799 

5800 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

5801 self.mock_object(self.client, 

5802 'send_iter_request', 

5803 mock.Mock(return_value=api_response)) 

5804 

5805 result = self.client.get_cifs_share_access(fake.SHARE_NAME) 

5806 

5807 self.assertEqual({}, result) 

5808 

5809 @ddt.data({'readonly': False, 'exception': True}, 

5810 {'readonly': True, 'exception': False}, 

5811 {'readonly': False, 'exception': False}, 

5812 {'readonly': True, 'exception': True}) 

5813 @ddt.unpack 

5814 def test_add_cifs_share_access(self, readonly, exception): 

5815 

5816 mock_exception = mock.Mock(side_effect=netapp_api.NaApiError( 

5817 code=netapp_api.EDUPLICATEENTRY)) 

5818 

5819 self.mock_object( 

5820 self.client, 'send_request', 

5821 mock_exception if exception else mock.Mock(return_value=None)) 

5822 

5823 self.client.add_cifs_share_access(fake.SHARE_NAME, 

5824 fake.USER_NAME, 

5825 readonly) 

5826 

5827 cifs_share_access_control_create_args = { 

5828 'permission': 'read' if readonly else 'full_control', 

5829 'share': fake.SHARE_NAME, 

5830 'user-or-group': fake.USER_NAME 

5831 } 

5832 

5833 self.client.send_request.assert_has_calls([ 

5834 mock.call( 

5835 'cifs-share-access-control-create', 

5836 cifs_share_access_control_create_args)]) 

5837 

5838 @ddt.data(True, False) 

5839 def test_modify_cifs_share_access(self, readonly): 

5840 

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

5842 

5843 self.client.modify_cifs_share_access(fake.SHARE_NAME, 

5844 fake.USER_NAME, 

5845 readonly) 

5846 

5847 cifs_share_access_control_modify_args = { 

5848 'permission': 'read' if readonly else 'full_control', 

5849 'share': fake.SHARE_NAME, 

5850 'user-or-group': fake.USER_NAME 

5851 } 

5852 

5853 self.client.send_request.assert_has_calls([ 

5854 mock.call( 

5855 'cifs-share-access-control-modify', 

5856 cifs_share_access_control_modify_args)]) 

5857 

5858 def test_remove_cifs_share_access(self): 

5859 

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

5861 

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

5863 

5864 cifs_share_access_control_delete_args = { 

5865 'user-or-group': fake.USER_NAME, 

5866 'share': fake.SHARE_NAME 

5867 } 

5868 

5869 self.client.send_request.assert_has_calls([ 

5870 mock.call( 

5871 'cifs-share-access-control-delete', 

5872 cifs_share_access_control_delete_args)]) 

5873 

5874 def test_remove_cifs_share(self): 

5875 

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

5877 

5878 self.client.remove_cifs_share(fake.SHARE_NAME) 

5879 

5880 cifs_share_delete_args = {'share-name': fake.SHARE_NAME} 

5881 

5882 self.client.send_request.assert_has_calls([ 

5883 mock.call('cifs-share-delete', cifs_share_delete_args)]) 

5884 

5885 def test_remove_cifs_share_not_found(self): 

5886 

5887 self.mock_object(self.client, 

5888 'send_request', 

5889 self._mock_api_error(code=netapp_api.EOBJECTNOTFOUND)) 

5890 

5891 self.client.remove_cifs_share(fake.SHARE_NAME) 

5892 

5893 cifs_share_args = {'share-name': fake.SHARE_NAME} 

5894 self.client.send_request.assert_has_calls([ 

5895 mock.call('cifs-share-delete', cifs_share_args)]) 

5896 

5897 def test_add_nfs_export_rule(self): 

5898 

5899 mock_get_nfs_export_rule_indices = self.mock_object( 

5900 self.client, '_get_nfs_export_rule_indices', 

5901 mock.Mock(return_value=[])) 

5902 mock_add_nfs_export_rule = self.mock_object( 

5903 self.client, '_add_nfs_export_rule') 

5904 mock_update_nfs_export_rule = self.mock_object( 

5905 self.client, '_update_nfs_export_rule') 

5906 auth_methods = ['sys'] 

5907 

5908 self.client.add_nfs_export_rule(fake.EXPORT_POLICY_NAME, 

5909 fake.IP_ADDRESS, 

5910 False, 

5911 auth_methods) 

5912 

5913 mock_get_nfs_export_rule_indices.assert_called_once_with( 

5914 fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS) 

5915 mock_add_nfs_export_rule.assert_called_once_with( 

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

5917 self.assertFalse(mock_update_nfs_export_rule.called) 

5918 

5919 def test_add_nfs_export_rule_single_existing(self): 

5920 

5921 mock_get_nfs_export_rule_indices = self.mock_object( 

5922 self.client, '_get_nfs_export_rule_indices', 

5923 mock.Mock(return_value=['1'])) 

5924 mock_add_nfs_export_rule = self.mock_object( 

5925 self.client, '_add_nfs_export_rule') 

5926 mock_update_nfs_export_rule = self.mock_object( 

5927 self.client, '_update_nfs_export_rule') 

5928 mock_remove_nfs_export_rules = self.mock_object( 

5929 self.client, '_remove_nfs_export_rules') 

5930 auth_methods = ['sys'] 

5931 

5932 self.client.add_nfs_export_rule(fake.EXPORT_POLICY_NAME, 

5933 fake.IP_ADDRESS, 

5934 False, 

5935 auth_methods) 

5936 

5937 mock_get_nfs_export_rule_indices.assert_called_once_with( 

5938 fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS) 

5939 self.assertFalse(mock_add_nfs_export_rule.called) 

5940 mock_update_nfs_export_rule.assert_called_once_with( 

5941 fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS, False, '1', 

5942 auth_methods) 

5943 mock_remove_nfs_export_rules.assert_called_once_with( 

5944 fake.EXPORT_POLICY_NAME, []) 

5945 

5946 def test_add_nfs_export_rule_multiple_existing(self): 

5947 

5948 mock_get_nfs_export_rule_indices = self.mock_object( 

5949 self.client, '_get_nfs_export_rule_indices', 

5950 mock.Mock(return_value=['2', '4', '6'])) 

5951 mock_add_nfs_export_rule = self.mock_object( 

5952 self.client, '_add_nfs_export_rule') 

5953 mock_update_nfs_export_rule = self.mock_object( 

5954 self.client, '_update_nfs_export_rule') 

5955 mock_remove_nfs_export_rules = self.mock_object( 

5956 self.client, '_remove_nfs_export_rules') 

5957 auth_methods = ['sys'] 

5958 self.client.add_nfs_export_rule(fake.EXPORT_POLICY_NAME, 

5959 fake.IP_ADDRESS, 

5960 False, 

5961 auth_methods) 

5962 

5963 mock_get_nfs_export_rule_indices.assert_called_once_with( 

5964 fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS) 

5965 self.assertFalse(mock_add_nfs_export_rule.called) 

5966 mock_update_nfs_export_rule.assert_called_once_with( 

5967 fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS, False, '2', auth_methods) 

5968 mock_remove_nfs_export_rules.assert_called_once_with( 

5969 fake.EXPORT_POLICY_NAME, ['4', '6']) 

5970 

5971 @ddt.data({'readonly': False, 'auth_method': 'sys'}, 

5972 {'readonly': True, 'auth_method': 'sys'}) 

5973 @ddt.unpack 

5974 def test__add_nfs_export_rule(self, readonly, auth_method): 

5975 

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

5977 

5978 self.client._add_nfs_export_rule(fake.EXPORT_POLICY_NAME, 

5979 fake.IP_ADDRESS, 

5980 readonly, 

5981 [auth_method]) 

5982 export_rule_create_args = { 

5983 'policy-name': fake.EXPORT_POLICY_NAME, 

5984 'client-match': fake.IP_ADDRESS, 

5985 'ro-rule': [ 

5986 {'security-flavor': auth_method}, 

5987 ], 

5988 'rw-rule': [ 

5989 {'security-flavor': auth_method}, 

5990 ], 

5991 'super-user-security': [ 

5992 {'security-flavor': auth_method}, 

5993 ], 

5994 } 

5995 if readonly: 

5996 export_rule_create_args['rw-rule'] = [ 

5997 {'security-flavor': 'never'} 

5998 ] 

5999 

6000 self.client.send_request.assert_has_calls( 

6001 [mock.call('export-rule-create', export_rule_create_args)]) 

6002 

6003 @ddt.data({'readonly': False, 'auth_method': 'sys', 'index': '2'}, 

6004 {'readonly': True, 'auth_method': 'krb5', 'index': '4'}) 

6005 @ddt.unpack 

6006 def test_update_nfs_export_rule(self, readonly, auth_method, index): 

6007 

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

6009 self.client._update_nfs_export_rule(fake.EXPORT_POLICY_NAME, 

6010 fake.IP_ADDRESS, 

6011 readonly, 

6012 index, 

6013 [auth_method]) 

6014 

6015 export_rule_modify_args = { 

6016 'policy-name': fake.EXPORT_POLICY_NAME, 

6017 'rule-index': index, 

6018 'client-match': fake.IP_ADDRESS, 

6019 'ro-rule': [ 

6020 {'security-flavor': auth_method}, 

6021 ], 

6022 'rw-rule': [ 

6023 {'security-flavor': auth_method}, 

6024 ], 

6025 'super-user-security': [ 

6026 {'security-flavor': auth_method}, 

6027 ], 

6028 } 

6029 if readonly: 

6030 export_rule_modify_args['rw-rule'] = [ 

6031 {'security-flavor': 'never'} 

6032 ] 

6033 

6034 self.client.send_request.assert_has_calls( 

6035 [mock.call('export-rule-modify', export_rule_modify_args)]) 

6036 

6037 def test_get_nfs_export_rule_indices(self): 

6038 

6039 api_response = netapp_api.NaElement(fake.EXPORT_RULE_GET_ITER_RESPONSE) 

6040 self.mock_object(self.client, 

6041 'send_iter_request', 

6042 mock.Mock(return_value=api_response)) 

6043 

6044 result = self.client._get_nfs_export_rule_indices( 

6045 fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS) 

6046 

6047 export_rule_get_iter_args = { 

6048 'query': { 

6049 'export-rule-info': { 

6050 'policy-name': fake.EXPORT_POLICY_NAME, 

6051 'client-match': fake.IP_ADDRESS, 

6052 }, 

6053 }, 

6054 'desired-attributes': { 

6055 'export-rule-info': { 

6056 'vserver-name': None, 

6057 'policy-name': None, 

6058 'client-match': None, 

6059 'rule-index': None, 

6060 }, 

6061 }, 

6062 } 

6063 self.assertListEqual(['1', '3'], result) 

6064 self.client.send_iter_request.assert_has_calls([ 

6065 mock.call('export-rule-get-iter', export_rule_get_iter_args)]) 

6066 

6067 def test_remove_nfs_export_rule(self): 

6068 

6069 fake_indices = ['1', '3', '4'] 

6070 mock_get_nfs_export_rule_indices = self.mock_object( 

6071 self.client, '_get_nfs_export_rule_indices', 

6072 mock.Mock(return_value=fake_indices)) 

6073 mock_remove_nfs_export_rules = self.mock_object( 

6074 self.client, '_remove_nfs_export_rules') 

6075 

6076 self.client.remove_nfs_export_rule(fake.EXPORT_POLICY_NAME, 

6077 fake.IP_ADDRESS) 

6078 

6079 mock_get_nfs_export_rule_indices.assert_called_once_with( 

6080 fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS) 

6081 mock_remove_nfs_export_rules.assert_called_once_with( 

6082 fake.EXPORT_POLICY_NAME, fake_indices) 

6083 

6084 def test_remove_nfs_export_rules(self): 

6085 

6086 fake_indices = ['1', '3'] 

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

6088 

6089 self.client._remove_nfs_export_rules(fake.EXPORT_POLICY_NAME, 

6090 fake_indices) 

6091 

6092 self.client.send_request.assert_has_calls([ 

6093 mock.call( 

6094 'export-rule-destroy', 

6095 {'policy-name': fake.EXPORT_POLICY_NAME, 'rule-index': '1'}), 

6096 mock.call( 

6097 'export-rule-destroy', 

6098 {'policy-name': fake.EXPORT_POLICY_NAME, 'rule-index': '3'})]) 

6099 

6100 def test_remove_nfs_export_rules_not_found(self): 

6101 

6102 self.mock_object(self.client, 

6103 'send_request', 

6104 self._mock_api_error(code=netapp_api.EOBJECTNOTFOUND)) 

6105 

6106 self.client._remove_nfs_export_rules(fake.EXPORT_POLICY_NAME, ['1']) 

6107 

6108 self.client.send_request.assert_has_calls([ 

6109 mock.call( 

6110 'export-rule-destroy', 

6111 {'policy-name': fake.EXPORT_POLICY_NAME, 'rule-index': '1'})]) 

6112 

6113 def test_remove_nfs_export_rules_api_error(self): 

6114 

6115 self.mock_object(self.client, 'send_request', self._mock_api_error()) 

6116 

6117 self.assertRaises(netapp_api.NaApiError, 

6118 self.client._remove_nfs_export_rules, 

6119 fake.EXPORT_POLICY_NAME, 

6120 ['1']) 

6121 

6122 def test_clear_nfs_export_policy_for_volume(self): 

6123 

6124 mock_set_nfs_export_policy_for_volume = self.mock_object( 

6125 self.client, 'set_nfs_export_policy_for_volume') 

6126 

6127 self.client.clear_nfs_export_policy_for_volume(fake.SHARE_NAME) 

6128 

6129 mock_set_nfs_export_policy_for_volume.assert_called_once_with( 

6130 fake.SHARE_NAME, 'default') 

6131 

6132 def test_set_nfs_export_policy_for_volume(self): 

6133 

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

6135 

6136 self.client.set_nfs_export_policy_for_volume(fake.SHARE_NAME, 

6137 fake.EXPORT_POLICY_NAME) 

6138 

6139 volume_modify_iter_args = { 

6140 'query': { 

6141 'volume-attributes': { 

6142 'volume-id-attributes': { 

6143 'name': fake.SHARE_NAME, 

6144 }, 

6145 }, 

6146 }, 

6147 'attributes': { 

6148 'volume-attributes': { 

6149 'volume-export-attributes': { 

6150 'policy': fake.EXPORT_POLICY_NAME, 

6151 }, 

6152 }, 

6153 }, 

6154 } 

6155 self.client.send_request.assert_has_calls([ 

6156 mock.call('volume-modify-iter', volume_modify_iter_args)]) 

6157 

6158 def test_set_qos_policy_group_for_volume(self): 

6159 

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

6161 

6162 self.client.set_qos_policy_group_for_volume(fake.SHARE_NAME, 

6163 fake.QOS_POLICY_GROUP_NAME) 

6164 

6165 volume_modify_iter_args = { 

6166 'query': { 

6167 'volume-attributes': { 

6168 'volume-id-attributes': { 

6169 'name': fake.SHARE_NAME, 

6170 }, 

6171 }, 

6172 }, 

6173 'attributes': { 

6174 'volume-attributes': { 

6175 'volume-qos-attributes': { 

6176 'policy-group-name': fake.QOS_POLICY_GROUP_NAME, 

6177 }, 

6178 }, 

6179 }, 

6180 } 

6181 self.client.send_request.assert_called_once_with( 

6182 'volume-modify-iter', volume_modify_iter_args) 

6183 

6184 def test_get_nfs_export_policy_for_volume(self): 

6185 

6186 api_response = netapp_api.NaElement( 

6187 fake.VOLUME_GET_EXPORT_POLICY_RESPONSE) 

6188 self.mock_object(self.client, 

6189 'send_iter_request', 

6190 mock.Mock(return_value=api_response)) 

6191 

6192 result = self.client.get_nfs_export_policy_for_volume(fake.SHARE_NAME) 

6193 

6194 volume_get_iter_args = { 

6195 'query': { 

6196 'volume-attributes': { 

6197 'volume-id-attributes': { 

6198 'name': fake.SHARE_NAME, 

6199 }, 

6200 }, 

6201 }, 

6202 'desired-attributes': { 

6203 'volume-attributes': { 

6204 'volume-export-attributes': { 

6205 'policy': None, 

6206 }, 

6207 }, 

6208 }, 

6209 } 

6210 self.assertEqual(fake.EXPORT_POLICY_NAME, result) 

6211 self.client.send_iter_request.assert_has_calls([ 

6212 mock.call('volume-get-iter', volume_get_iter_args)]) 

6213 

6214 def test_get_nfs_export_policy_for_volume_not_found(self): 

6215 

6216 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

6217 self.mock_object(self.client, 

6218 'send_iter_request', 

6219 mock.Mock(return_value=api_response)) 

6220 

6221 self.assertRaises(exception.NetAppException, 

6222 self.client.get_nfs_export_policy_for_volume, 

6223 fake.SHARE_NAME) 

6224 

6225 def test_create_nfs_export_policy(self): 

6226 

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

6228 

6229 self.client.create_nfs_export_policy(fake.EXPORT_POLICY_NAME) 

6230 

6231 export_policy_create_args = {'policy-name': fake.EXPORT_POLICY_NAME} 

6232 self.client.send_request.assert_has_calls([ 

6233 mock.call('export-policy-create', export_policy_create_args)]) 

6234 

6235 def test_create_nfs_export_policy_already_present(self): 

6236 

6237 self.mock_object(self.client, 

6238 'send_request', 

6239 self._mock_api_error(code=netapp_api.EDUPLICATEENTRY)) 

6240 

6241 self.client.create_nfs_export_policy(fake.EXPORT_POLICY_NAME) 

6242 

6243 export_policy_create_args = {'policy-name': fake.EXPORT_POLICY_NAME} 

6244 self.client.send_request.assert_has_calls([ 

6245 mock.call('export-policy-create', export_policy_create_args)]) 

6246 

6247 def test_create_nfs_export_policy_api_error(self): 

6248 

6249 self.mock_object(self.client, 'send_request', self._mock_api_error()) 

6250 

6251 self.assertRaises(netapp_api.NaApiError, 

6252 self.client.create_nfs_export_policy, 

6253 fake.EXPORT_POLICY_NAME) 

6254 

6255 def test_soft_delete_nfs_export_policy(self): 

6256 

6257 self.mock_object(self.client, 'delete_nfs_export_policy') 

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

6259 

6260 self.client.soft_delete_nfs_export_policy(fake.EXPORT_POLICY_NAME) 

6261 

6262 self.client.delete_nfs_export_policy.assert_has_calls([ 

6263 mock.call(fake.EXPORT_POLICY_NAME)]) 

6264 self.assertFalse(self.client.rename_nfs_export_policy.called) 

6265 

6266 def test_soft_delete_nfs_export_policy_api_error(self): 

6267 

6268 self.mock_object(self.client, 

6269 'delete_nfs_export_policy', 

6270 self._mock_api_error()) 

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

6272 

6273 self.client.soft_delete_nfs_export_policy(fake.EXPORT_POLICY_NAME) 

6274 

6275 self.client.delete_nfs_export_policy.assert_has_calls([ 

6276 mock.call(fake.EXPORT_POLICY_NAME)]) 

6277 self.assertTrue(self.client.rename_nfs_export_policy.called) 

6278 

6279 def test_delete_nfs_export_policy(self): 

6280 

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

6282 

6283 self.client.delete_nfs_export_policy(fake.EXPORT_POLICY_NAME) 

6284 

6285 export_policy_destroy_args = {'policy-name': fake.EXPORT_POLICY_NAME} 

6286 self.client.send_request.assert_has_calls([ 

6287 mock.call('export-policy-destroy', export_policy_destroy_args)]) 

6288 

6289 def test_delete_nfs_export_policy_not_found(self): 

6290 

6291 self.mock_object(self.client, 

6292 'send_request', 

6293 self._mock_api_error(code=netapp_api.EOBJECTNOTFOUND)) 

6294 

6295 self.client.delete_nfs_export_policy(fake.EXPORT_POLICY_NAME) 

6296 

6297 export_policy_destroy_args = {'policy-name': fake.EXPORT_POLICY_NAME} 

6298 self.client.send_request.assert_has_calls([ 

6299 mock.call('export-policy-destroy', export_policy_destroy_args)]) 

6300 

6301 def test_delete_nfs_export_policy_api_error(self): 

6302 

6303 self.mock_object(self.client, 'send_request', self._mock_api_error()) 

6304 

6305 self.assertRaises(netapp_api.NaApiError, 

6306 self.client.delete_nfs_export_policy, 

6307 fake.EXPORT_POLICY_NAME) 

6308 

6309 def test_rename_nfs_export_policy(self): 

6310 

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

6312 

6313 self.client.rename_nfs_export_policy(fake.EXPORT_POLICY_NAME, 

6314 'new_policy_name') 

6315 

6316 export_policy_rename_args = { 

6317 'policy-name': fake.EXPORT_POLICY_NAME, 

6318 'new-policy-name': 'new_policy_name' 

6319 } 

6320 self.client.send_request.assert_has_calls([ 

6321 mock.call('export-policy-rename', export_policy_rename_args)]) 

6322 

6323 def test_prune_deleted_nfs_export_policies(self): 

6324 # Mock client lest we not be able to see calls on its copy. 

6325 self.mock_object(copy, 

6326 'deepcopy', 

6327 mock.Mock(return_value=self.client)) 

6328 self.mock_object(self.client, 

6329 '_get_deleted_nfs_export_policies', 

6330 mock.Mock(return_value=fake.DELETED_EXPORT_POLICIES)) 

6331 self.mock_object(self.client, 'delete_nfs_export_policy') 

6332 

6333 self.client.prune_deleted_nfs_export_policies() 

6334 

6335 self.assertTrue(self.client.delete_nfs_export_policy.called) 

6336 self.client.delete_nfs_export_policy.assert_has_calls( 

6337 [mock.call(policy) for policy in 

6338 fake.DELETED_EXPORT_POLICIES[fake.VSERVER_NAME]]) 

6339 

6340 def test_prune_deleted_nfs_export_policies_api_error(self): 

6341 self.mock_object(copy, 

6342 'deepcopy', 

6343 mock.Mock(return_value=self.client)) 

6344 self.mock_object(self.client, 

6345 '_get_deleted_nfs_export_policies', 

6346 mock.Mock(return_value=fake.DELETED_EXPORT_POLICIES)) 

6347 self.mock_object(self.client, 

6348 'delete_nfs_export_policy', 

6349 self._mock_api_error()) 

6350 

6351 self.client.prune_deleted_nfs_export_policies() 

6352 

6353 self.assertTrue(self.client.delete_nfs_export_policy.called) 

6354 self.client.delete_nfs_export_policy.assert_has_calls( 

6355 [mock.call(policy) for policy in 

6356 fake.DELETED_EXPORT_POLICIES[fake.VSERVER_NAME]]) 

6357 

6358 def test_get_deleted_nfs_export_policies(self): 

6359 

6360 api_response = netapp_api.NaElement( 

6361 fake.DELETED_EXPORT_POLICY_GET_ITER_RESPONSE) 

6362 self.mock_object(self.client, 

6363 'send_iter_request', 

6364 mock.Mock(return_value=api_response)) 

6365 

6366 result = self.client._get_deleted_nfs_export_policies() 

6367 

6368 export_policy_get_iter_args = { 

6369 'query': { 

6370 'export-policy-info': { 

6371 'policy-name': 'deleted_manila_*', 

6372 }, 

6373 }, 

6374 'desired-attributes': { 

6375 'export-policy-info': { 

6376 'policy-name': None, 

6377 'vserver': None, 

6378 }, 

6379 }, 

6380 } 

6381 self.assertSequenceEqual(fake.DELETED_EXPORT_POLICIES, result) 

6382 self.client.send_iter_request.assert_has_calls([ 

6383 mock.call('export-policy-get-iter', export_policy_get_iter_args)]) 

6384 

6385 def test_get_ems_log_destination_vserver(self): 

6386 

6387 self.mock_object(self.client, 

6388 'get_ontapi_version', 

6389 mock.Mock(return_value=(1, 21))) 

6390 mock_list_vservers = self.mock_object( 

6391 self.client, 

6392 'list_vservers', 

6393 mock.Mock(return_value=[fake.ADMIN_VSERVER_NAME])) 

6394 

6395 result = self.client._get_ems_log_destination_vserver() 

6396 

6397 mock_list_vservers.assert_called_once_with(vserver_type='admin') 

6398 self.assertEqual(fake.ADMIN_VSERVER_NAME, result) 

6399 

6400 def test_get_ems_log_destination_vserver_future(self): 

6401 

6402 self.mock_object(self.client, 

6403 'get_ontapi_version', 

6404 mock.Mock(return_value=(2, 0))) 

6405 mock_list_vservers = self.mock_object( 

6406 self.client, 

6407 'list_vservers', 

6408 mock.Mock(return_value=[fake.ADMIN_VSERVER_NAME])) 

6409 

6410 result = self.client._get_ems_log_destination_vserver() 

6411 

6412 mock_list_vservers.assert_called_once_with(vserver_type='admin') 

6413 self.assertEqual(fake.ADMIN_VSERVER_NAME, result) 

6414 

6415 def test_get_ems_log_destination_vserver_legacy(self): 

6416 

6417 self.mock_object(self.client, 

6418 'get_ontapi_version', 

6419 mock.Mock(return_value=(1, 15))) 

6420 mock_list_vservers = self.mock_object( 

6421 self.client, 

6422 'list_vservers', 

6423 mock.Mock(return_value=[fake.NODE_VSERVER_NAME])) 

6424 

6425 result = self.client._get_ems_log_destination_vserver() 

6426 

6427 mock_list_vservers.assert_called_once_with(vserver_type='node') 

6428 self.assertEqual(fake.NODE_VSERVER_NAME, result) 

6429 

6430 def test_get_ems_log_destination_no_cluster_creds(self): 

6431 

6432 self.mock_object(self.client, 

6433 'get_ontapi_version', 

6434 mock.Mock(return_value=(1, 21))) 

6435 mock_list_vservers = self.mock_object( 

6436 self.client, 

6437 'list_vservers', 

6438 mock.Mock(side_effect=[[], [fake.VSERVER_NAME]])) 

6439 

6440 result = self.client._get_ems_log_destination_vserver() 

6441 

6442 mock_list_vservers.assert_has_calls([ 

6443 mock.call(vserver_type='admin'), 

6444 mock.call(vserver_type='data')]) 

6445 self.assertEqual(fake.VSERVER_NAME, result) 

6446 

6447 def test_get_ems_log_destination_vserver_not_found(self): 

6448 

6449 self.mock_object(self.client, 

6450 'get_ontapi_version', 

6451 mock.Mock(return_value=(1, 21))) 

6452 mock_list_vservers = self.mock_object( 

6453 self.client, 

6454 'list_vservers', 

6455 mock.Mock(return_value=[])) 

6456 

6457 self.assertRaises(exception.NotFound, 

6458 self.client._get_ems_log_destination_vserver) 

6459 

6460 mock_list_vservers.assert_has_calls([ 

6461 mock.call(vserver_type='admin'), 

6462 mock.call(vserver_type='data'), 

6463 mock.call(vserver_type='node')]) 

6464 

6465 def test_send_ems_log_message(self): 

6466 

6467 # Mock client lest we not be able to see calls on its copy. 

6468 self.mock_object( 

6469 copy, 'copy', 

6470 mock.Mock(side_effect=[self.client, self.client.connection])) 

6471 self.mock_object(self.client, 

6472 '_get_ems_log_destination_vserver', 

6473 mock.Mock(return_value=fake.ADMIN_VSERVER_NAME)) 

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

6475 

6476 self.client.send_ems_log_message(fake.EMS_MESSAGE) 

6477 

6478 self.client.send_request.assert_has_calls([ 

6479 mock.call('ems-autosupport-log', fake.EMS_MESSAGE)]) 

6480 self.assertEqual(1, client_cmode.LOG.debug.call_count) 

6481 

6482 def test_send_ems_log_message_api_error(self): 

6483 

6484 # Mock client lest we not be able to see calls on its copy. 

6485 self.mock_object( 

6486 copy, 'copy', 

6487 mock.Mock(side_effect=[self.client, self.client.connection])) 

6488 self.mock_object(self.client, 

6489 '_get_ems_log_destination_vserver', 

6490 mock.Mock(return_value=fake.ADMIN_VSERVER_NAME)) 

6491 self.mock_object(self.client, 'send_request', self._mock_api_error()) 

6492 

6493 self.client.send_ems_log_message(fake.EMS_MESSAGE) 

6494 

6495 self.client.send_request.assert_has_calls([ 

6496 mock.call('ems-autosupport-log', fake.EMS_MESSAGE)]) 

6497 self.assertEqual(1, client_cmode.LOG.warning.call_count) 

6498 

6499 def test_get_aggregate_none_specified(self): 

6500 

6501 result = self.client.get_aggregate('') 

6502 

6503 self.assertEqual({}, result) 

6504 

6505 def test_get_aggregate(self): 

6506 self.client.features.SNAPLOCK = True 

6507 api_response = netapp_api.NaElement( 

6508 fake.AGGR_GET_ITER_SSC_RESPONSE).get_child_by_name( 

6509 'attributes-list').get_children() 

6510 self.mock_object(self.client, 

6511 '_get_aggregates', 

6512 mock.Mock(return_value=api_response)) 

6513 

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

6515 desired_attributes = { 

6516 'aggr-attributes': { 

6517 'aggregate-name': None, 

6518 'aggr-raid-attributes': { 

6519 'raid-type': None, 

6520 'is-hybrid': None, 

6521 }, 

6522 'aggr-ownership-attributes': { 

6523 'home-id': None, 

6524 'owner-id': None, 

6525 }, 

6526 }, 

6527 } 

6528 

6529 if self.client.features.SNAPLOCK: 6529 ↛ 6533line 6529 didn't jump to line 6533 because the condition on line 6529 was always true

6530 desired_attributes['aggr-attributes']['aggr-snaplock-attributes']\ 

6531 = {'is-snaplock': None, 'snaplock-type': None} 

6532 

6533 self.client._get_aggregates.assert_has_calls([ 

6534 mock.call( 

6535 aggregate_names=[fake.SHARE_AGGREGATE_NAME], 

6536 desired_attributes=desired_attributes)]) 

6537 

6538 expected = { 

6539 'name': fake.SHARE_AGGREGATE_NAME, 

6540 'raid-type': 'raid_dp', 

6541 'is-hybrid': False, 

6542 'is-home': True, 

6543 'snaplock-type': 'compliance', 

6544 'is-snaplock': 'true' 

6545 } 

6546 self.assertEqual(expected, result) 

6547 

6548 def test_get_aggregate_not_found(self): 

6549 

6550 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

6551 self.mock_object(self.client, 

6552 'send_request', 

6553 mock.Mock(return_value=api_response)) 

6554 

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

6556 

6557 self.assertEqual({}, result) 

6558 

6559 def test_get_aggregate_api_error(self): 

6560 

6561 self.mock_object(self.client, 

6562 'send_request', 

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

6564 

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

6566 

6567 self.assertEqual({}, result) 

6568 

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

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

6571 @ddt.unpack 

6572 def test_get_aggregate_disk_types(self, types, expected): 

6573 

6574 mock_get_aggregate_disk_types = self.mock_object( 

6575 self.client, '_get_aggregate_disk_types', 

6576 mock.Mock(return_value=types)) 

6577 

6578 result = self.client.get_aggregate_disk_types( 

6579 fake.SHARE_AGGREGATE_NAME) 

6580 

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

6582 mock_get_aggregate_disk_types.assert_called_once_with( 

6583 fake.SHARE_AGGREGATE_NAME) 

6584 

6585 def test_get_aggregate_disk_types_not_found(self): 

6586 

6587 mock_get_aggregate_disk_types = self.mock_object( 

6588 self.client, '_get_aggregate_disk_types', 

6589 mock.Mock(return_value=set())) 

6590 

6591 result = self.client.get_aggregate_disk_types( 

6592 fake.SHARE_AGGREGATE_NAME) 

6593 

6594 self.assertIsNone(result) 

6595 mock_get_aggregate_disk_types.assert_called_once_with( 

6596 fake.SHARE_AGGREGATE_NAME) 

6597 

6598 def test_get_aggregate_disk_types_shared(self): 

6599 

6600 self.client.features.add_feature('ADVANCED_DISK_PARTITIONING') 

6601 mock_get_aggregate_disk_types = self.mock_object( 

6602 self.client, '_get_aggregate_disk_types', 

6603 mock.Mock(side_effect=[set(['SSD']), set(['SATA'])])) 

6604 

6605 result = self.client.get_aggregate_disk_types( 

6606 fake.SHARE_AGGREGATE_NAME) 

6607 

6608 self.assertIsInstance(result, list) 

6609 self.assertEqual(sorted(['SATA', 'SSD']), sorted(result)) 

6610 mock_get_aggregate_disk_types.assert_has_calls([ 

6611 mock.call(fake.SHARE_AGGREGATE_NAME), 

6612 mock.call(fake.SHARE_AGGREGATE_NAME, shared=True), 

6613 ]) 

6614 

6615 @ddt.data({ 

6616 'shared': False, 

6617 'query_disk_raid_info': { 

6618 'disk-aggregate-info': { 

6619 'aggregate-name': fake.SHARE_AGGREGATE_NAME, 

6620 }, 

6621 }, 

6622 }, { 

6623 'shared': True, 

6624 'query_disk_raid_info': { 

6625 'disk-shared-info': { 

6626 'aggregate-list': { 

6627 'shared-aggregate-info': { 

6628 'aggregate-name': 

6629 fake.SHARE_AGGREGATE_NAME, 

6630 }, 

6631 }, 

6632 }, 

6633 }, 

6634 }) 

6635 @ddt.unpack 

6636 def test__get_aggregate_disk_types_ddt(self, shared, query_disk_raid_info): 

6637 

6638 api_response = netapp_api.NaElement( 

6639 fake.STORAGE_DISK_GET_ITER_RESPONSE) 

6640 self.mock_object(self.client, 

6641 'send_iter_request', 

6642 mock.Mock(return_value=api_response)) 

6643 

6644 result = self.client._get_aggregate_disk_types( 

6645 fake.SHARE_AGGREGATE_NAME, shared=shared) 

6646 

6647 storage_disk_get_iter_args = { 

6648 'query': { 

6649 'storage-disk-info': { 

6650 'disk-raid-info': query_disk_raid_info, 

6651 }, 

6652 }, 

6653 'desired-attributes': { 

6654 'storage-disk-info': { 

6655 'disk-raid-info': { 

6656 'effective-disk-type': None, 

6657 }, 

6658 }, 

6659 }, 

6660 } 

6661 self.client.send_iter_request.assert_called_once_with( 

6662 'storage-disk-get-iter', storage_disk_get_iter_args) 

6663 

6664 expected = set(fake.SHARE_AGGREGATE_DISK_TYPES) 

6665 self.assertEqual(expected, result) 

6666 

6667 def test__get_aggregate_disk_types_not_found(self): 

6668 

6669 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

6670 self.mock_object(self.client, 

6671 'send_iter_request', 

6672 mock.Mock(return_value=api_response)) 

6673 

6674 result = self.client._get_aggregate_disk_types( 

6675 fake.SHARE_AGGREGATE_NAME) 

6676 

6677 self.assertEqual(set(), result) 

6678 

6679 def test__get_aggregate_disk_types_api_error(self): 

6680 

6681 self.mock_object(self.client, 

6682 'send_iter_request', 

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

6684 

6685 result = self.client._get_aggregate_disk_types( 

6686 fake.SHARE_AGGREGATE_NAME) 

6687 

6688 self.assertEqual(set([]), result) 

6689 

6690 def test_check_for_cluster_credentials(self): 

6691 

6692 api_response = netapp_api.NaElement(fake.SYSTEM_NODE_GET_ITER_RESPONSE) 

6693 self.mock_object(self.client, 

6694 'send_iter_request', 

6695 mock.Mock(return_value=api_response)) 

6696 

6697 result = self.client.check_for_cluster_credentials() 

6698 

6699 self.assertTrue(result) 

6700 

6701 def test_check_for_cluster_credentials_not_cluster(self): 

6702 

6703 self.mock_object(self.client, 

6704 'send_iter_request', 

6705 mock.Mock(side_effect=self._mock_api_error( 

6706 netapp_api.EAPINOTFOUND))) 

6707 

6708 result = self.client.check_for_cluster_credentials() 

6709 

6710 self.assertFalse(result) 

6711 

6712 def test_check_for_cluster_credentials_api_error(self): 

6713 

6714 self.mock_object(self.client, 

6715 'send_iter_request', 

6716 self._mock_api_error()) 

6717 

6718 self.assertRaises(netapp_api.NaApiError, 

6719 self.client.check_for_cluster_credentials) 

6720 

6721 def test_create_cluster_peer(self): 

6722 

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

6724 

6725 self.client.create_cluster_peer(['fake_address_1', 'fake_address_2'], 

6726 'fake_user', 'fake_password', 

6727 'fake_passphrase') 

6728 

6729 cluster_peer_create_args = { 

6730 'peer-addresses': [ 

6731 {'remote-inet-address': 'fake_address_1'}, 

6732 {'remote-inet-address': 'fake_address_2'}, 

6733 ], 

6734 'user-name': 'fake_user', 

6735 'password': 'fake_password', 

6736 'passphrase': 'fake_passphrase', 

6737 } 

6738 self.client.send_request.assert_has_calls([ 

6739 mock.call('cluster-peer-create', cluster_peer_create_args, 

6740 enable_tunneling=False)]) 

6741 

6742 def test_get_cluster_peers(self): 

6743 

6744 api_response = netapp_api.NaElement( 

6745 fake.CLUSTER_PEER_GET_ITER_RESPONSE) 

6746 self.mock_object(self.client, 

6747 'send_iter_request', 

6748 mock.Mock(return_value=api_response)) 

6749 

6750 result = self.client.get_cluster_peers() 

6751 

6752 cluster_peer_get_iter_args = {} 

6753 self.client.send_iter_request.assert_has_calls([ 

6754 mock.call('cluster-peer-get-iter', cluster_peer_get_iter_args)]) 

6755 

6756 expected = [{ 

6757 'active-addresses': [ 

6758 fake.CLUSTER_ADDRESS_1, 

6759 fake.CLUSTER_ADDRESS_2 

6760 ], 

6761 'availability': 'available', 

6762 'cluster-name': fake.CLUSTER_NAME, 

6763 'cluster-uuid': 'fake_uuid', 

6764 'peer-addresses': [fake.CLUSTER_ADDRESS_1], 

6765 'remote-cluster-name': fake.REMOTE_CLUSTER_NAME, 

6766 'serial-number': 'fake_serial_number', 

6767 'timeout': '60', 

6768 }] 

6769 

6770 self.assertEqual(expected, result) 

6771 

6772 def test_get_cluster_peers_single(self): 

6773 

6774 api_response = netapp_api.NaElement( 

6775 fake.CLUSTER_PEER_GET_ITER_RESPONSE) 

6776 self.mock_object(self.client, 

6777 'send_iter_request', 

6778 mock.Mock(return_value=api_response)) 

6779 

6780 self.client.get_cluster_peers(remote_cluster_name=fake.CLUSTER_NAME) 

6781 

6782 cluster_peer_get_iter_args = { 

6783 'query': { 

6784 'cluster-peer-info': { 

6785 'remote-cluster-name': fake.CLUSTER_NAME, 

6786 } 

6787 }, 

6788 } 

6789 self.client.send_iter_request.assert_has_calls([ 

6790 mock.call('cluster-peer-get-iter', cluster_peer_get_iter_args)]) 

6791 

6792 def test_get_cluster_peers_not_found(self): 

6793 

6794 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

6795 self.mock_object(self.client, 

6796 'send_iter_request', 

6797 mock.Mock(return_value=api_response)) 

6798 

6799 result = self.client.get_cluster_peers( 

6800 remote_cluster_name=fake.CLUSTER_NAME) 

6801 

6802 self.assertEqual([], result) 

6803 self.assertTrue(self.client.send_iter_request.called) 

6804 

6805 def test_delete_cluster_peer(self): 

6806 

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

6808 

6809 self.client.delete_cluster_peer(fake.CLUSTER_NAME) 

6810 

6811 cluster_peer_delete_args = {'cluster-name': fake.CLUSTER_NAME} 

6812 self.client.send_request.assert_has_calls([ 

6813 mock.call('cluster-peer-delete', cluster_peer_delete_args, 

6814 enable_tunneling=False)]) 

6815 

6816 def test_get_cluster_peer_policy(self): 

6817 

6818 self.client.features.add_feature('CLUSTER_PEER_POLICY') 

6819 

6820 api_response = netapp_api.NaElement( 

6821 fake.CLUSTER_PEER_POLICY_GET_RESPONSE) 

6822 self.mock_object(self.client, 

6823 'send_request', 

6824 mock.Mock(return_value=api_response)) 

6825 

6826 result = self.client.get_cluster_peer_policy() 

6827 

6828 expected = { 

6829 'is-unauthenticated-access-permitted': False, 

6830 'passphrase-minimum-length': 8 

6831 } 

6832 self.assertEqual(expected, result) 

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

6834 

6835 def test_get_cluster_peer_policy_not_supported(self): 

6836 

6837 result = self.client.get_cluster_peer_policy() 

6838 

6839 self.assertEqual({}, result) 

6840 

6841 def test_set_cluster_peer_policy_not_supported(self): 

6842 

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

6844 

6845 self.client.set_cluster_peer_policy() 

6846 

6847 self.assertFalse(self.client.send_request.called) 

6848 

6849 def test_set_cluster_peer_policy_no_arguments(self): 

6850 

6851 self.client.features.add_feature('CLUSTER_PEER_POLICY') 

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

6853 

6854 self.client.set_cluster_peer_policy() 

6855 

6856 self.assertFalse(self.client.send_request.called) 

6857 

6858 def test_set_cluster_peer_policy(self): 

6859 

6860 self.client.features.add_feature('CLUSTER_PEER_POLICY') 

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

6862 

6863 self.client.set_cluster_peer_policy( 

6864 is_unauthenticated_access_permitted=True, 

6865 passphrase_minimum_length=12) 

6866 

6867 cluster_peer_policy_modify_args = { 

6868 'is-unauthenticated-access-permitted': 'true', 

6869 'passphrase-minlength': '12', 

6870 } 

6871 self.client.send_request.assert_has_calls([ 

6872 mock.call('cluster-peer-policy-modify', 

6873 cluster_peer_policy_modify_args)]) 

6874 

6875 @ddt.data(None, 'cluster_name') 

6876 def test_create_vserver_peer(self, cluster_name): 

6877 

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

6879 

6880 self.client.create_vserver_peer(fake.VSERVER_NAME, 

6881 fake.VSERVER_PEER_NAME, 

6882 peer_cluster_name=cluster_name) 

6883 

6884 vserver_peer_create_args = { 

6885 'vserver': fake.VSERVER_NAME, 

6886 'peer-vserver': fake.VSERVER_PEER_NAME, 

6887 'applications': [ 

6888 {'vserver-peer-application': 'snapmirror'}, 

6889 ], 

6890 } 

6891 if cluster_name: 

6892 vserver_peer_create_args['peer-cluster'] = cluster_name 

6893 

6894 self.client.send_request.assert_has_calls([ 

6895 mock.call('vserver-peer-create', vserver_peer_create_args, 

6896 enable_tunneling=False)]) 

6897 

6898 def test_delete_vserver_peer(self): 

6899 

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

6901 

6902 self.client.delete_vserver_peer('fake_vserver', 'fake_vserver_peer') 

6903 

6904 vserver_peer_delete_args = { 

6905 'vserver': 'fake_vserver', 

6906 'peer-vserver': 'fake_vserver_peer', 

6907 } 

6908 self.client.send_request.assert_has_calls([ 

6909 mock.call('vserver-peer-delete', vserver_peer_delete_args, 

6910 enable_tunneling=False)]) 

6911 

6912 def test_accept_vserver_peer(self): 

6913 

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

6915 

6916 self.client.accept_vserver_peer('fake_vserver', 'fake_vserver_peer') 

6917 

6918 vserver_peer_accept_args = { 

6919 'vserver': 'fake_vserver', 

6920 'peer-vserver': 'fake_vserver_peer', 

6921 } 

6922 self.client.send_request.assert_has_calls([ 

6923 mock.call('vserver-peer-accept', vserver_peer_accept_args, 

6924 enable_tunneling=False)]) 

6925 

6926 def test_get_vserver_peers(self): 

6927 

6928 api_response = netapp_api.NaElement( 

6929 fake.VSERVER_PEER_GET_ITER_RESPONSE) 

6930 self.mock_object(self.client, 

6931 'send_iter_request', 

6932 mock.Mock(return_value=api_response)) 

6933 

6934 result = self.client.get_vserver_peers( 

6935 vserver_name=fake.VSERVER_NAME, 

6936 peer_vserver_name=fake.VSERVER_NAME_2) 

6937 

6938 vserver_peer_get_iter_args = { 

6939 'query': { 

6940 'vserver-peer-info': { 

6941 'vserver': fake.VSERVER_NAME, 

6942 'peer-vserver': fake.VSERVER_NAME_2, 

6943 } 

6944 }, 

6945 } 

6946 self.client.send_iter_request.assert_has_calls([ 

6947 mock.call('vserver-peer-get-iter', vserver_peer_get_iter_args)]) 

6948 

6949 expected = [{ 

6950 'vserver': 'fake_vserver', 

6951 'peer-vserver': 'fake_vserver_2', 

6952 'peer-state': 'peered', 

6953 'peer-cluster': 'fake_cluster' 

6954 }] 

6955 self.assertEqual(expected, result) 

6956 

6957 def test_get_vserver_peers_not_found(self): 

6958 

6959 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

6960 self.mock_object(self.client, 

6961 'send_iter_request', 

6962 mock.Mock(return_value=api_response)) 

6963 

6964 result = self.client.get_vserver_peers( 

6965 vserver_name=fake.VSERVER_NAME, 

6966 peer_vserver_name=fake.VSERVER_NAME_2) 

6967 

6968 self.assertEqual([], result) 

6969 self.assertTrue(self.client.send_iter_request.called) 

6970 

6971 def test_ensure_snapmirror_v2(self): 

6972 

6973 self.assertIsNone(self.client._ensure_snapmirror_v2()) 

6974 

6975 def test_ensure_snapmirror_v2_not_supported(self): 

6976 

6977 self.client.features.add_feature('SNAPMIRROR_V2', supported=False) 

6978 

6979 self.assertRaises(exception.NetAppException, 

6980 self.client._ensure_snapmirror_v2) 

6981 

6982 @ddt.data({'schedule': 'fake_schedule', 'policy': 'fake_policy'}, 

6983 {'schedule': None, 'policy': None}) 

6984 @ddt.unpack 

6985 def test_create_snapmirror(self, schedule, policy): 

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

6987 

6988 self.client.create_snapmirror_vol( 

6989 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

6990 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME, 

6991 na_utils.DATA_PROTECTION_TYPE, schedule=schedule, policy=policy) 

6992 

6993 snapmirror_create_args = { 

6994 'source-vserver': fake.SM_SOURCE_VSERVER, 

6995 'source-volume': fake.SM_SOURCE_VOLUME, 

6996 'destination-vserver': fake.SM_DEST_VSERVER, 

6997 'destination-volume': fake.SM_DEST_VOLUME, 

6998 'relationship-type': na_utils.DATA_PROTECTION_TYPE, 

6999 } 

7000 if schedule: 

7001 snapmirror_create_args['schedule'] = schedule 

7002 if policy: 

7003 snapmirror_create_args['policy'] = policy 

7004 self.client.send_request.assert_has_calls([ 

7005 mock.call('snapmirror-create', snapmirror_create_args)]) 

7006 

7007 def test_create_snapmirror_already_exists(self): 

7008 mock_send_req = mock.Mock(side_effect=netapp_api.NaApiError( 

7009 code=netapp_api.ERELATION_EXISTS)) 

7010 self.mock_object(self.client, 'send_request', mock_send_req) 

7011 

7012 self.client.create_snapmirror_vol( 

7013 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

7014 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME, 

7015 na_utils.DATA_PROTECTION_TYPE) 

7016 

7017 snapmirror_create_args = { 

7018 'source-vserver': fake.SM_SOURCE_VSERVER, 

7019 'source-volume': fake.SM_SOURCE_VOLUME, 

7020 'destination-vserver': fake.SM_DEST_VSERVER, 

7021 'destination-volume': fake.SM_DEST_VOLUME, 

7022 'relationship-type': na_utils.DATA_PROTECTION_TYPE, 

7023 'policy': na_utils.MIRROR_ALL_SNAP_POLICY, 

7024 } 

7025 self.client.send_request.assert_has_calls([ 

7026 mock.call('snapmirror-create', snapmirror_create_args)]) 

7027 

7028 def test_create_snapmirror_error(self): 

7029 mock_send_req = mock.Mock(side_effect=netapp_api.NaApiError( 

7030 code=0)) 

7031 self.mock_object(self.client, 'send_request', mock_send_req) 

7032 

7033 self.assertRaises(netapp_api.NaApiError, 

7034 self.client.create_snapmirror_vol, 

7035 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

7036 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME, 

7037 na_utils.DATA_PROTECTION_TYPE) 

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

7039 

7040 def test_create_snapmirror_svm(self): 

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

7042 

7043 self.client.create_snapmirror_svm(fake.SM_SOURCE_VSERVER, 

7044 fake.SM_DEST_VSERVER, 

7045 max_transfer_rate='fake_xfer_rate') 

7046 

7047 snapmirror_create_args = { 

7048 'source-vserver': fake.SM_SOURCE_VSERVER, 

7049 'destination-vserver': fake.SM_DEST_VSERVER, 

7050 'relationship-type': na_utils.DATA_PROTECTION_TYPE, 

7051 'identity-preserve': 'true', 

7052 'max-transfer-rate': 'fake_xfer_rate' 

7053 } 

7054 self.client.send_request.assert_has_calls([ 

7055 mock.call('snapmirror-create', snapmirror_create_args)]) 

7056 

7057 @ddt.data( 

7058 { 

7059 'source_snapshot': 'fake_snapshot', 

7060 'transfer_priority': 'fake_priority' 

7061 }, 

7062 { 

7063 'source_snapshot': None, 

7064 'transfer_priority': None 

7065 } 

7066 ) 

7067 @ddt.unpack 

7068 def test_initialize_snapmirror(self, source_snapshot, transfer_priority): 

7069 

7070 api_response = netapp_api.NaElement(fake.SNAPMIRROR_INITIALIZE_RESULT) 

7071 self.mock_object(self.client, 

7072 'send_request', 

7073 mock.Mock(return_value=api_response)) 

7074 

7075 result = self.client.initialize_snapmirror_vol( 

7076 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

7077 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME, 

7078 source_snapshot=source_snapshot, 

7079 transfer_priority=transfer_priority) 

7080 

7081 snapmirror_initialize_args = { 

7082 'source-vserver': fake.SM_SOURCE_VSERVER, 

7083 'source-volume': fake.SM_SOURCE_VOLUME, 

7084 'destination-vserver': fake.SM_DEST_VSERVER, 

7085 'destination-volume': fake.SM_DEST_VOLUME, 

7086 } 

7087 if source_snapshot: 

7088 snapmirror_initialize_args['source-snapshot'] = source_snapshot 

7089 if transfer_priority: 

7090 snapmirror_initialize_args['transfer-priority'] = transfer_priority 

7091 self.client.send_request.assert_has_calls([ 

7092 mock.call('snapmirror-initialize', snapmirror_initialize_args)]) 

7093 

7094 expected = { 

7095 'operation-id': None, 

7096 'status': 'succeeded', 

7097 'jobid': None, 

7098 'error-code': None, 

7099 'error-message': None 

7100 } 

7101 self.assertEqual(expected, result) 

7102 

7103 def test_initialize_snapmirror_svm(self): 

7104 

7105 api_response = netapp_api.NaElement(fake.SNAPMIRROR_INITIALIZE_RESULT) 

7106 self.mock_object(self.client, 

7107 'send_request', 

7108 mock.Mock(return_value=api_response)) 

7109 

7110 result = self.client.initialize_snapmirror_svm(fake.SM_SOURCE_VSERVER, 

7111 fake.SM_DEST_VSERVER) 

7112 

7113 snapmirror_initialize_args = { 

7114 'source-location': fake.SM_SOURCE_VSERVER + ':', 

7115 'destination-location': fake.SM_DEST_VSERVER + ':', 

7116 } 

7117 self.client.send_request.assert_has_calls([ 

7118 mock.call('snapmirror-initialize', snapmirror_initialize_args)]) 

7119 

7120 expected = { 

7121 'operation-id': None, 

7122 'status': 'succeeded', 

7123 'jobid': None, 

7124 'error-code': None, 

7125 'error-message': None 

7126 } 

7127 self.assertEqual(expected, result) 

7128 

7129 @ddt.data({'snapmirror_destinations_list': [], 

7130 'relationship_info_only': True}, 

7131 {'snapmirror_destinations_list': [], 

7132 'relationship_info_only': False}, 

7133 {'snapmirror_destinations_list': 

7134 [{'relationship-id': 'fake_relationship_id'}], 

7135 'relationship_info_only': True}, 

7136 {'snapmirror_destinations_list': 

7137 [{'relationship-id': 'fake_relationship_id'}], 

7138 'relationship_info_only': False}) 

7139 @ddt.unpack 

7140 def test_release_snapmirror_vol(self, relationship_info_only, 

7141 snapmirror_destinations_list): 

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

7143 self.mock_object(self.client, 'get_snapmirror_destinations', 

7144 mock.Mock(return_value=snapmirror_destinations_list)) 

7145 self.mock_object(self.client, '_ensure_snapmirror_v2') 

7146 

7147 self.client.release_snapmirror_vol( 

7148 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

7149 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME, 

7150 relationship_info_only=relationship_info_only) 

7151 

7152 snapmirror_release_args = { 

7153 'source-vserver': fake.SM_SOURCE_VSERVER, 

7154 'source-volume': fake.SM_SOURCE_VOLUME, 

7155 'destination-vserver': fake.SM_DEST_VSERVER, 

7156 'destination-volume': fake.SM_DEST_VOLUME, 

7157 'relationship-info-only': ('true' if relationship_info_only 

7158 else 'false'), 

7159 } 

7160 

7161 if len(snapmirror_destinations_list) == 1: 

7162 snapmirror_release_args['relationship-id'] = 'fake_relationship_id' 

7163 

7164 self.client.send_request.assert_called_once_with( 

7165 'snapmirror-release', snapmirror_release_args, 

7166 enable_tunneling=True) 

7167 

7168 def test_release_snapmirror_vol_error_not_unique_relationship(self): 

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

7170 self.mock_object(self.client, 'get_snapmirror_destinations', 

7171 mock.Mock(return_value=[{'relationship-id': 'fake'}, 

7172 {'relationship-id': 'fake'}])) 

7173 

7174 self.assertRaises(exception.NetAppException, 

7175 self.client.release_snapmirror_vol, 

7176 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

7177 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME) 

7178 

7179 def test_release_snapmirror_svm(self): 

7180 

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

7182 self.mock_object(self.client, '_ensure_snapmirror_v2') 

7183 

7184 self.client.release_snapmirror_svm( 

7185 fake.SM_SOURCE_VSERVER, fake.SM_DEST_VSERVER) 

7186 

7187 snapmirror_release_args = { 

7188 'query': { 

7189 'snapmirror-destination-info': { 

7190 'source-location': fake.SM_SOURCE_VSERVER + ':', 

7191 'destination-location': fake.SM_DEST_VSERVER + ':', 

7192 }, 

7193 }, 

7194 'relationship-info-only': 'false', 

7195 } 

7196 self.client.send_request.assert_has_calls([ 

7197 mock.call('snapmirror-release-iter', snapmirror_release_args, 

7198 enable_tunneling=False)]) 

7199 

7200 def test_quiesce_snapmirror(self): 

7201 

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

7203 

7204 self.client.quiesce_snapmirror_vol( 

7205 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

7206 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME) 

7207 

7208 snapmirror_quiesce_args = { 

7209 'source-vserver': fake.SM_SOURCE_VSERVER, 

7210 'source-volume': fake.SM_SOURCE_VOLUME, 

7211 'destination-vserver': fake.SM_DEST_VSERVER, 

7212 'destination-volume': fake.SM_DEST_VOLUME, 

7213 } 

7214 self.client.send_request.assert_has_calls([ 

7215 mock.call('snapmirror-quiesce', snapmirror_quiesce_args)]) 

7216 

7217 def test_quiesce_snapmirror_svm(self): 

7218 

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

7220 

7221 self.client.quiesce_snapmirror_svm( 

7222 fake.SM_SOURCE_VSERVER, fake.SM_DEST_VSERVER) 

7223 

7224 snapmirror_quiesce_args = { 

7225 'source-location': fake.SM_SOURCE_VSERVER + ':', 

7226 'destination-location': fake.SM_DEST_VSERVER + ':', 

7227 } 

7228 self.client.send_request.assert_has_calls([ 

7229 mock.call('snapmirror-quiesce', snapmirror_quiesce_args)]) 

7230 

7231 @ddt.data(True, False) 

7232 def test_abort_snapmirror(self, clear_checkpoint): 

7233 

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

7235 

7236 self.client.abort_snapmirror_vol( 

7237 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

7238 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME, 

7239 clear_checkpoint=clear_checkpoint) 

7240 

7241 snapmirror_abort_args = { 

7242 'source-vserver': fake.SM_SOURCE_VSERVER, 

7243 'source-volume': fake.SM_SOURCE_VOLUME, 

7244 'destination-vserver': fake.SM_DEST_VSERVER, 

7245 'destination-volume': fake.SM_DEST_VOLUME, 

7246 'clear-checkpoint': 'true' if clear_checkpoint else 'false', 

7247 } 

7248 self.client.send_request.assert_has_calls([ 

7249 mock.call('snapmirror-abort', snapmirror_abort_args)]) 

7250 

7251 def test_abort_snapmirror_svm(self): 

7252 

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

7254 

7255 self.client.abort_snapmirror_svm( 

7256 fake.SM_SOURCE_VSERVER, fake.SM_DEST_VSERVER) 

7257 

7258 snapmirror_abort_args = { 

7259 'source-location': fake.SM_SOURCE_VSERVER + ':', 

7260 'destination-location': fake.SM_DEST_VSERVER + ':', 

7261 'clear-checkpoint': 'false' 

7262 } 

7263 self.client.send_request.assert_has_calls([ 

7264 mock.call('snapmirror-abort', snapmirror_abort_args)]) 

7265 

7266 def test_abort_snapmirror_no_transfer_in_progress(self): 

7267 mock_send_req = mock.Mock(side_effect=netapp_api.NaApiError( 

7268 code=netapp_api.ENOTRANSFER_IN_PROGRESS)) 

7269 self.mock_object(self.client, 'send_request', mock_send_req) 

7270 

7271 self.client.abort_snapmirror_vol( 

7272 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

7273 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME) 

7274 

7275 snapmirror_abort_args = { 

7276 'source-vserver': fake.SM_SOURCE_VSERVER, 

7277 'source-volume': fake.SM_SOURCE_VOLUME, 

7278 'destination-vserver': fake.SM_DEST_VSERVER, 

7279 'destination-volume': fake.SM_DEST_VOLUME, 

7280 'clear-checkpoint': 'false', 

7281 } 

7282 self.client.send_request.assert_has_calls([ 

7283 mock.call('snapmirror-abort', snapmirror_abort_args)]) 

7284 

7285 def test_abort_snapmirror_error(self): 

7286 mock_send_req = mock.Mock(side_effect=netapp_api.NaApiError(code=0)) 

7287 self.mock_object(self.client, 'send_request', mock_send_req) 

7288 

7289 self.assertRaises(netapp_api.NaApiError, 

7290 self.client.abort_snapmirror_vol, 

7291 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

7292 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME) 

7293 

7294 def test_break_snapmirror(self): 

7295 

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

7297 

7298 self.client.break_snapmirror_vol( 

7299 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

7300 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME) 

7301 

7302 snapmirror_break_args = { 

7303 'source-vserver': fake.SM_SOURCE_VSERVER, 

7304 'source-volume': fake.SM_SOURCE_VOLUME, 

7305 'destination-vserver': fake.SM_DEST_VSERVER, 

7306 'destination-volume': fake.SM_DEST_VOLUME, 

7307 } 

7308 self.client.send_request.assert_has_calls([ 

7309 mock.call('snapmirror-break', snapmirror_break_args)]) 

7310 

7311 def test_break_snapmirror_svm(self): 

7312 

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

7314 

7315 self.client.break_snapmirror_svm( 

7316 fake.SM_SOURCE_VSERVER, fake.SM_DEST_VSERVER) 

7317 

7318 snapmirror_break_args = { 

7319 'source-location': fake.SM_SOURCE_VSERVER + ':', 

7320 'destination-location': fake.SM_DEST_VSERVER + ':', 

7321 } 

7322 self.client.send_request.assert_has_calls([ 

7323 mock.call('snapmirror-break', snapmirror_break_args)]) 

7324 

7325 @ddt.data( 

7326 { 

7327 'schedule': 'fake_schedule', 

7328 'policy': 'fake_policy', 

7329 'tries': 5, 

7330 'max_transfer_rate': 1024, 

7331 }, 

7332 { 

7333 'schedule': None, 

7334 'policy': None, 

7335 'tries': None, 

7336 'max_transfer_rate': None, 

7337 } 

7338 ) 

7339 @ddt.unpack 

7340 def test_modify_snapmirror(self, schedule, policy, tries, 

7341 max_transfer_rate): 

7342 

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

7344 

7345 self.client.modify_snapmirror_vol( 

7346 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

7347 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME, 

7348 schedule=schedule, policy=policy, tries=tries, 

7349 max_transfer_rate=max_transfer_rate) 

7350 

7351 snapmirror_modify_args = { 

7352 'source-vserver': fake.SM_SOURCE_VSERVER, 

7353 'source-volume': fake.SM_SOURCE_VOLUME, 

7354 'destination-vserver': fake.SM_DEST_VSERVER, 

7355 'destination-volume': fake.SM_DEST_VOLUME, 

7356 } 

7357 if schedule: 

7358 snapmirror_modify_args['schedule'] = schedule 

7359 if policy: 

7360 snapmirror_modify_args['policy'] = policy 

7361 if tries: 

7362 snapmirror_modify_args['tries'] = tries 

7363 if max_transfer_rate: 

7364 snapmirror_modify_args['max-transfer-rate'] = max_transfer_rate 

7365 self.client.send_request.assert_has_calls([ 

7366 mock.call('snapmirror-modify', snapmirror_modify_args)]) 

7367 

7368 def test_update_snapmirror(self): 

7369 

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

7371 

7372 self.client.update_snapmirror_vol( 

7373 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

7374 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME) 

7375 

7376 snapmirror_update_args = { 

7377 'source-vserver': fake.SM_SOURCE_VSERVER, 

7378 'source-volume': fake.SM_SOURCE_VOLUME, 

7379 'destination-vserver': fake.SM_DEST_VSERVER, 

7380 'destination-volume': fake.SM_DEST_VOLUME, 

7381 } 

7382 self.client.send_request.assert_has_calls([ 

7383 mock.call('snapmirror-update', snapmirror_update_args)]) 

7384 

7385 def test_update_snapmirror_svm(self): 

7386 

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

7388 

7389 self.client.update_snapmirror_svm( 

7390 fake.SM_SOURCE_VSERVER, fake.SM_DEST_VSERVER) 

7391 

7392 snapmirror_update_args = { 

7393 'source-location': fake.SM_SOURCE_VSERVER + ':', 

7394 'destination-location': fake.SM_DEST_VSERVER + ':', 

7395 } 

7396 self.client.send_request.assert_has_calls([ 

7397 mock.call('snapmirror-update', snapmirror_update_args)]) 

7398 

7399 def test_update_snapmirror_already_transferring(self): 

7400 mock_send_req = mock.Mock(side_effect=netapp_api.NaApiError( 

7401 code=netapp_api.ETRANSFER_IN_PROGRESS)) 

7402 self.mock_object(self.client, 'send_request', mock_send_req) 

7403 

7404 self.client.update_snapmirror_vol( 

7405 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

7406 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME) 

7407 

7408 snapmirror_update_args = { 

7409 'source-vserver': fake.SM_SOURCE_VSERVER, 

7410 'source-volume': fake.SM_SOURCE_VOLUME, 

7411 'destination-vserver': fake.SM_DEST_VSERVER, 

7412 'destination-volume': fake.SM_DEST_VOLUME, 

7413 } 

7414 self.client.send_request.assert_has_calls([ 

7415 mock.call('snapmirror-update', snapmirror_update_args)]) 

7416 

7417 def test_update_snapmirror_already_transferring_two(self): 

7418 mock_send_req = mock.Mock(side_effect=netapp_api.NaApiError( 

7419 code=netapp_api.EANOTHER_OP_ACTIVE)) 

7420 self.mock_object(self.client, 'send_request', mock_send_req) 

7421 

7422 self.client.update_snapmirror_vol( 

7423 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

7424 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME) 

7425 

7426 snapmirror_update_args = { 

7427 'source-vserver': fake.SM_SOURCE_VSERVER, 

7428 'source-volume': fake.SM_SOURCE_VOLUME, 

7429 'destination-vserver': fake.SM_DEST_VSERVER, 

7430 'destination-volume': fake.SM_DEST_VOLUME, 

7431 } 

7432 self.client.send_request.assert_has_calls([ 

7433 mock.call('snapmirror-update', snapmirror_update_args)]) 

7434 

7435 def test_update_snapmirror_error(self): 

7436 mock_send_req = mock.Mock(side_effect=netapp_api.NaApiError(code=0)) 

7437 self.mock_object(self.client, 'send_request', mock_send_req) 

7438 

7439 self.assertRaises(netapp_api.NaApiError, 

7440 self.client.update_snapmirror_vol, 

7441 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

7442 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME) 

7443 

7444 def test_delete_snapmirror(self): 

7445 

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

7447 

7448 self.client.delete_snapmirror_vol( 

7449 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

7450 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME) 

7451 

7452 snapmirror_delete_args = { 

7453 'query': { 

7454 'snapmirror-info': { 

7455 'source-vserver': fake.SM_SOURCE_VSERVER, 

7456 'source-volume': fake.SM_SOURCE_VOLUME, 

7457 'destination-vserver': fake.SM_DEST_VSERVER, 

7458 'destination-volume': fake.SM_DEST_VOLUME, 

7459 } 

7460 } 

7461 } 

7462 self.client.send_request.assert_has_calls([ 

7463 mock.call('snapmirror-destroy-iter', snapmirror_delete_args)]) 

7464 

7465 def test_delete_snapmirror_svm(self): 

7466 

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

7468 

7469 self.client.delete_snapmirror_svm( 

7470 fake.SM_SOURCE_VSERVER, fake.SM_DEST_VSERVER) 

7471 

7472 snapmirror_delete_args = { 

7473 'query': { 

7474 'snapmirror-info': { 

7475 'source-location': fake.SM_SOURCE_VSERVER + ':', 

7476 'destination-location': fake.SM_DEST_VSERVER + ':', 

7477 } 

7478 } 

7479 } 

7480 self.client.send_request.assert_has_calls([ 

7481 mock.call('snapmirror-destroy-iter', snapmirror_delete_args)]) 

7482 

7483 def test__get_snapmirrors(self): 

7484 

7485 api_response = netapp_api.NaElement(fake.SNAPMIRROR_GET_ITER_RESPONSE) 

7486 self.mock_object(self.client, 

7487 'send_iter_request', 

7488 mock.Mock(return_value=api_response)) 

7489 

7490 desired_attributes = { 

7491 'snapmirror-info': { 

7492 'source-vserver': None, 

7493 'source-volume': None, 

7494 'destination-vserver': None, 

7495 'destination-volume': None, 

7496 'is-healthy': None, 

7497 } 

7498 } 

7499 

7500 result = self.client._get_snapmirrors( 

7501 source_vserver=fake.SM_SOURCE_VSERVER, 

7502 source_volume=fake.SM_SOURCE_VOLUME, 

7503 dest_vserver=fake.SM_DEST_VSERVER, 

7504 dest_volume=fake.SM_DEST_VOLUME, 

7505 desired_attributes=desired_attributes) 

7506 

7507 snapmirror_get_iter_args = { 

7508 'query': { 

7509 'snapmirror-info': { 

7510 'source-vserver': fake.SM_SOURCE_VSERVER, 

7511 'source-volume': fake.SM_SOURCE_VOLUME, 

7512 'destination-vserver': fake.SM_DEST_VSERVER, 

7513 'destination-volume': fake.SM_DEST_VOLUME, 

7514 }, 

7515 }, 

7516 'desired-attributes': { 

7517 'snapmirror-info': { 

7518 'source-vserver': None, 

7519 'source-volume': None, 

7520 'destination-vserver': None, 

7521 'destination-volume': None, 

7522 'is-healthy': None, 

7523 }, 

7524 }, 

7525 } 

7526 self.client.send_iter_request.assert_has_calls([ 

7527 mock.call('snapmirror-get-iter', snapmirror_get_iter_args)]) 

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

7529 

7530 def test__get_snapmirrors_not_found(self): 

7531 

7532 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

7533 self.mock_object(self.client, 

7534 'send_iter_request', 

7535 mock.Mock(return_value=api_response)) 

7536 

7537 result = self.client._get_snapmirrors() 

7538 

7539 self.client.send_iter_request.assert_has_calls([ 

7540 mock.call('snapmirror-get-iter', {})]) 

7541 

7542 self.assertEqual([], result) 

7543 

7544 def test_get_snapmirrors(self): 

7545 

7546 api_response = netapp_api.NaElement( 

7547 fake.SNAPMIRROR_GET_ITER_FILTERED_RESPONSE) 

7548 self.mock_object(self.client, 

7549 'send_iter_request', 

7550 mock.Mock(return_value=api_response)) 

7551 

7552 desired_attributes = ['source-vserver', 'source-volume', 

7553 'destination-vserver', 'destination-volume', 

7554 'is-healthy', 'mirror-state', 'schedule', 

7555 'relationship-status'] 

7556 

7557 result = self.client.get_snapmirrors( 

7558 source_vserver=fake.SM_SOURCE_VSERVER, 

7559 dest_vserver=fake.SM_DEST_VSERVER, 

7560 source_volume=fake.SM_SOURCE_VOLUME, 

7561 dest_volume=fake.SM_DEST_VOLUME, 

7562 desired_attributes=desired_attributes) 

7563 

7564 snapmirror_get_iter_args = { 

7565 'query': { 

7566 'snapmirror-info': { 

7567 'source-vserver': fake.SM_SOURCE_VSERVER, 

7568 'source-volume': fake.SM_SOURCE_VOLUME, 

7569 'destination-vserver': fake.SM_DEST_VSERVER, 

7570 'destination-volume': fake.SM_DEST_VOLUME, 

7571 }, 

7572 }, 

7573 'desired-attributes': { 

7574 'snapmirror-info': { 

7575 'source-vserver': None, 

7576 'source-volume': None, 

7577 'destination-vserver': None, 

7578 'destination-volume': None, 

7579 'is-healthy': None, 

7580 'mirror-state': None, 

7581 'schedule': None, 

7582 'relationship-status': None, 

7583 }, 

7584 }, 

7585 } 

7586 

7587 expected = [{ 

7588 'source-vserver': fake.SM_SOURCE_VSERVER, 

7589 'source-volume': fake.SM_SOURCE_VOLUME, 

7590 'destination-vserver': fake.SM_DEST_VSERVER, 

7591 'destination-volume': fake.SM_DEST_VOLUME, 

7592 'is-healthy': 'true', 

7593 'mirror-state': 'snapmirrored', 

7594 'schedule': 'daily', 

7595 'relationship-status': 'idle' 

7596 }] 

7597 

7598 self.client.send_iter_request.assert_has_calls([ 

7599 mock.call('snapmirror-get-iter', snapmirror_get_iter_args)]) 

7600 self.assertEqual(expected, result) 

7601 

7602 def test_get_snapmirrors_svm(self): 

7603 

7604 api_response = netapp_api.NaElement( 

7605 fake.SNAPMIRROR_GET_ITER_FILTERED_RESPONSE_2) 

7606 self.mock_object(self.client, 

7607 'send_iter_request', 

7608 mock.Mock(return_value=api_response)) 

7609 

7610 desired_attributes = ['source-vserver', 'destination-vserver', 

7611 'relationship-status', 'mirror-state'] 

7612 

7613 result = self.client.get_snapmirrors_svm( 

7614 source_vserver=fake.SM_SOURCE_VSERVER, 

7615 dest_vserver=fake.SM_DEST_VSERVER, 

7616 desired_attributes=desired_attributes) 

7617 

7618 snapmirror_get_iter_args = { 

7619 'query': { 

7620 'snapmirror-info': { 

7621 'source-location': fake.SM_SOURCE_VSERVER + ':', 

7622 'destination-location': fake.SM_DEST_VSERVER + ':', 

7623 }, 

7624 }, 

7625 'desired-attributes': { 

7626 'snapmirror-info': { 

7627 'source-vserver': None, 

7628 'destination-vserver': None, 

7629 'relationship-status': None, 

7630 'mirror-state': None, 

7631 }, 

7632 }, 

7633 } 

7634 

7635 expected = [{ 

7636 'source-vserver': fake.SM_SOURCE_VSERVER, 

7637 'destination-vserver': fake.SM_DEST_VSERVER, 

7638 'relationship-status': 'idle', 

7639 'mirror-state': 'snapmirrored', 

7640 }] 

7641 

7642 self.client.send_iter_request.assert_has_calls([ 

7643 mock.call('snapmirror-get-iter', snapmirror_get_iter_args)]) 

7644 self.assertEqual(expected, result) 

7645 

7646 @ddt.data(fake.SNAPMIRROR_GET_DESTINATIONS_ITER_FILTERED_RESPONSE, 

7647 fake.NO_RECORDS_RESPONSE) 

7648 def test_get_snapmirror_destinations_svm(self, api_response): 

7649 self.mock_object( 

7650 self.client, 'send_iter_request', 

7651 mock.Mock(return_value=netapp_api.NaElement(api_response))) 

7652 

7653 result = self.client.get_snapmirror_destinations_svm( 

7654 source_vserver=fake.SM_SOURCE_VSERVER, 

7655 dest_vserver=fake.SM_DEST_VSERVER) 

7656 

7657 snapmirror_get_iter_args = { 

7658 'query': { 

7659 'snapmirror-destination-info': { 

7660 'source-location': fake.SM_SOURCE_VSERVER + ':', 

7661 'destination-location': fake.SM_DEST_VSERVER + ':', 

7662 }, 

7663 }, 

7664 } 

7665 

7666 if api_response == fake.NO_RECORDS_RESPONSE: 

7667 expected = [] 

7668 else: 

7669 expected = [{ 

7670 'source-vserver': fake.SM_SOURCE_VSERVER, 

7671 'destination-vserver': fake.SM_DEST_VSERVER, 

7672 'source-location': fake.SM_SOURCE_VSERVER + ':', 

7673 'destination-location': fake.SM_DEST_VSERVER + ':', 

7674 'relationship-id': 'fake_relationship_id', 

7675 }] 

7676 

7677 self.client.send_iter_request.assert_has_calls([ 

7678 mock.call('snapmirror-get-destination-iter', 

7679 snapmirror_get_iter_args)]) 

7680 self.assertEqual(expected, result) 

7681 

7682 def test_resume_snapmirror(self): 

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

7684 

7685 self.client.resume_snapmirror_vol( 

7686 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

7687 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME) 

7688 

7689 snapmirror_resume_args = { 

7690 'source-vserver': fake.SM_SOURCE_VSERVER, 

7691 'source-volume': fake.SM_SOURCE_VOLUME, 

7692 'destination-vserver': fake.SM_DEST_VSERVER, 

7693 'destination-volume': fake.SM_DEST_VOLUME, 

7694 } 

7695 self.client.send_request.assert_has_calls([ 

7696 mock.call('snapmirror-resume', snapmirror_resume_args)]) 

7697 

7698 def test_resume_snapmirror_svm(self): 

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

7700 

7701 self.client.resume_snapmirror_svm( 

7702 fake.SM_SOURCE_VSERVER, fake.SM_DEST_VSERVER) 

7703 

7704 snapmirror_resume_args = { 

7705 'source-location': fake.SM_SOURCE_VSERVER + ':', 

7706 'destination-location': fake.SM_DEST_VSERVER + ':', 

7707 } 

7708 self.client.send_request.assert_has_calls([ 

7709 mock.call('snapmirror-resume', snapmirror_resume_args)]) 

7710 

7711 def test_resume_snapmirror_not_quiesed(self): 

7712 mock_send_req = mock.Mock(side_effect=netapp_api.NaApiError( 

7713 code=netapp_api.ERELATION_NOT_QUIESCED)) 

7714 self.mock_object(self.client, 'send_request', mock_send_req) 

7715 

7716 self.client.resume_snapmirror_vol( 

7717 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

7718 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME) 

7719 

7720 snapmirror_resume_args = { 

7721 'source-vserver': fake.SM_SOURCE_VSERVER, 

7722 'source-volume': fake.SM_SOURCE_VOLUME, 

7723 'destination-vserver': fake.SM_DEST_VSERVER, 

7724 'destination-volume': fake.SM_DEST_VOLUME, 

7725 } 

7726 self.client.send_request.assert_has_calls([ 

7727 mock.call('snapmirror-resume', snapmirror_resume_args)]) 

7728 

7729 def test_resume_snapmirror_error(self): 

7730 mock_send_req = mock.Mock(side_effect=netapp_api.NaApiError(code=0)) 

7731 self.mock_object(self.client, 'send_request', mock_send_req) 

7732 

7733 self.assertRaises(netapp_api.NaApiError, 

7734 self.client.resume_snapmirror_vol, 

7735 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

7736 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME) 

7737 

7738 def test_resync_snapmirror(self): 

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

7740 

7741 self.client.resync_snapmirror_vol( 

7742 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME, 

7743 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME) 

7744 

7745 snapmirror_resync_args = { 

7746 'source-vserver': fake.SM_SOURCE_VSERVER, 

7747 'source-volume': fake.SM_SOURCE_VOLUME, 

7748 'destination-vserver': fake.SM_DEST_VSERVER, 

7749 'destination-volume': fake.SM_DEST_VOLUME, 

7750 } 

7751 self.client.send_request.assert_has_calls([ 

7752 mock.call('snapmirror-resync', snapmirror_resync_args)]) 

7753 

7754 def test_resync_snapmirror_svm(self): 

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

7756 

7757 self.client.resync_snapmirror_svm( 

7758 fake.SM_SOURCE_VSERVER, fake.SM_DEST_VSERVER) 

7759 

7760 snapmirror_resync_args = { 

7761 'source-location': fake.SM_SOURCE_VSERVER + ':', 

7762 'destination-location': fake.SM_DEST_VSERVER + ':', 

7763 } 

7764 self.client.send_request.assert_has_calls([ 

7765 mock.call('snapmirror-resync', snapmirror_resync_args)]) 

7766 

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

7768 def test_volume_has_snapmirror_relationships(self, snapmirror_rel_type): 

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

7770 

7771 vol = fake.FAKE_MANAGE_VOLUME 

7772 snapmirror = { 

7773 'source-vserver': fake.SM_SOURCE_VSERVER, 

7774 'source-volume': fake.SM_SOURCE_VOLUME, 

7775 'destination-vserver': fake.SM_DEST_VSERVER, 

7776 'destination-volume': fake.SM_DEST_VOLUME, 

7777 'is-healthy': 'true', 

7778 'mirror-state': 'snapmirrored', 

7779 'schedule': 'daily', 

7780 } 

7781 expected_get_snapmirrors_call_count = 2 

7782 expected_get_snapmirrors_calls = [ 

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

7784 source_volume=vol['name']), 

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

7786 dest_volume=vol['name']), 

7787 ] 

7788 if snapmirror_rel_type is None: 

7789 side_effect = ([], []) 

7790 elif snapmirror_rel_type == 'source': 

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

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

7793 side_effect = ([snapmirror], None) 

7794 expected_get_snapmirrors_call_count = 1 

7795 expected_get_snapmirrors_calls.pop() 

7796 else: 

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

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

7799 side_effect = (None, [snapmirror]) 

7800 mock_get_snapmirrors_call = self.mock_object( 

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

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

7803 expected_retval = True if snapmirror_rel_type else False 

7804 

7805 retval = self.client.volume_has_snapmirror_relationships(vol) 

7806 

7807 self.assertEqual(expected_retval, retval) 

7808 self.assertEqual(expected_get_snapmirrors_call_count, 

7809 mock_get_snapmirrors_call.call_count) 

7810 mock_get_snapmirrors_call.assert_has_calls( 

7811 expected_get_snapmirrors_calls) 

7812 self.assertFalse(mock_exc_log.called) 

7813 

7814 def test_volume_has_snapmirror_relationships_api_error(self): 

7815 

7816 vol = fake.FAKE_MANAGE_VOLUME 

7817 expected_get_snapmirrors_calls = [ 

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

7819 source_volume=vol['name']), 

7820 ] 

7821 mock_get_snapmirrors_call = self.mock_object( 

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

7823 side_effect=self._mock_api_error(netapp_api.EINTERNALERROR))) 

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

7825 

7826 retval = self.client.volume_has_snapmirror_relationships(vol) 

7827 

7828 self.assertFalse(retval) 

7829 self.assertEqual(1, mock_get_snapmirrors_call.call_count) 

7830 mock_get_snapmirrors_call.assert_has_calls( 

7831 expected_get_snapmirrors_calls) 

7832 self.assertTrue(mock_exc_log.called) 

7833 

7834 @ddt.data(None, '12345') 

7835 def test_list_snapmirror_snapshots(self, newer_than): 

7836 

7837 api_response = netapp_api.NaElement( 

7838 fake.SNAPSHOT_GET_ITER_SNAPMIRROR_RESPONSE) 

7839 self.mock_object(self.client, 

7840 'send_iter_request', 

7841 mock.Mock(return_value=api_response)) 

7842 

7843 result = self.client.list_snapmirror_snapshots(fake.SHARE_NAME, 

7844 newer_than=newer_than) 

7845 

7846 snapshot_get_iter_args = { 

7847 'query': { 

7848 'snapshot-info': { 

7849 'dependency': 'snapmirror', 

7850 'volume': fake.SHARE_NAME, 

7851 }, 

7852 }, 

7853 } 

7854 if newer_than: 

7855 snapshot_get_iter_args['query']['snapshot-info']['access-time'] = ( 

7856 '>' + newer_than) 

7857 self.client.send_iter_request.assert_has_calls([ 

7858 mock.call('snapshot-get-iter', snapshot_get_iter_args)]) 

7859 

7860 expected = [fake.SNAPSHOT_NAME] 

7861 self.assertEqual(expected, result) 

7862 

7863 @ddt.data( 

7864 {'method_name': 'start_volume_move', 'ontapi_version': (1, 20)}, 

7865 {'method_name': 'start_volume_move', 'ontapi_version': (1, 110)}, 

7866 {'method_name': 'check_volume_move', 'ontapi_version': (1, 20)}, 

7867 {'method_name': 'check_volume_move', 'ontapi_version': (1, 110)} 

7868 ) 

7869 @ddt.unpack 

7870 def test_volume_move_method(self, method_name, ontapi_version): 

7871 self.mock_object(client_base.NetAppBaseClient, 

7872 'get_ontapi_version', 

7873 mock.Mock(return_value=ontapi_version)) 

7874 

7875 self.client._init_features() 

7876 

7877 method = getattr(self.client, method_name) 

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

7879 

7880 retval = method(fake.SHARE_NAME, fake.VSERVER_NAME, 

7881 fake.SHARE_AGGREGATE_NAME) 

7882 

7883 expected_api_args = { 

7884 'source-volume': fake.SHARE_NAME, 

7885 'vserver': fake.VSERVER_NAME, 

7886 'dest-aggr': fake.SHARE_AGGREGATE_NAME, 

7887 'cutover-action': 'wait', 

7888 } 

7889 

7890 if ontapi_version >= (1, 110): 

7891 expected_api_args['encrypt-destination'] = 'false' 

7892 self.assertTrue(self.client.features.FLEXVOL_ENCRYPTION) 

7893 else: 

7894 self.assertFalse(self.client.features.FLEXVOL_ENCRYPTION) 

7895 

7896 if method_name.startswith('check'): 

7897 expected_api_args['perform-validation-only'] = 'true' 

7898 

7899 self.assertIsNone(retval) 

7900 self.client.send_request.assert_called_once_with( 

7901 'volume-move-start', expected_api_args) 

7902 

7903 def test_abort_volume_move(self): 

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

7905 

7906 retval = self.client.abort_volume_move( 

7907 fake.SHARE_NAME, fake.VSERVER_NAME) 

7908 

7909 expected_api_args = { 

7910 'source-volume': fake.SHARE_NAME, 

7911 'vserver': fake.VSERVER_NAME, 

7912 } 

7913 self.assertIsNone(retval) 

7914 self.client.send_request.assert_called_once_with( 

7915 'volume-move-trigger-abort', expected_api_args) 

7916 

7917 @ddt.data(True, False) 

7918 def test_trigger_volume_move_cutover_force(self, forced): 

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

7920 

7921 retval = self.client.trigger_volume_move_cutover( 

7922 fake.SHARE_NAME, fake.VSERVER_NAME, force=forced) 

7923 

7924 expected_api_args = { 

7925 'source-volume': fake.SHARE_NAME, 

7926 'vserver': fake.VSERVER_NAME, 

7927 'force': 'true' if forced else 'false', 

7928 } 

7929 self.assertIsNone(retval) 

7930 self.client.send_request.assert_called_once_with( 

7931 'volume-move-trigger-cutover', expected_api_args) 

7932 

7933 def test_get_volume_move_status_no_records(self): 

7934 self.mock_object(self.client, 'send_iter_request') 

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

7936 mock.Mock(return_value=False)) 

7937 

7938 self.assertRaises(exception.NetAppException, 

7939 self.client.get_volume_move_status, 

7940 fake.SHARE_NAME, fake.VSERVER_NAME) 

7941 

7942 expected_api_args = { 

7943 'query': { 

7944 'volume-move-info': { 

7945 'volume': fake.SHARE_NAME, 

7946 'vserver': fake.VSERVER_NAME, 

7947 }, 

7948 }, 

7949 'desired-attributes': { 

7950 'volume-move-info': { 

7951 'percent-complete': None, 

7952 'estimated-completion-time': None, 

7953 'state': None, 

7954 'details': None, 

7955 'cutover-action': None, 

7956 'phase': None, 

7957 }, 

7958 }, 

7959 } 

7960 self.client.send_iter_request.assert_called_once_with( 

7961 'volume-move-get-iter', expected_api_args) 

7962 

7963 def test_get_volume_move_status(self): 

7964 move_status = netapp_api.NaElement(fake.VOLUME_MOVE_GET_ITER_RESULT) 

7965 self.mock_object(self.client, 'send_iter_request', 

7966 mock.Mock(return_value=move_status)) 

7967 

7968 actual_status_info = self.client.get_volume_move_status( 

7969 fake.SHARE_NAME, fake.VSERVER_NAME) 

7970 

7971 expected_api_args = { 

7972 'query': { 

7973 'volume-move-info': { 

7974 'volume': fake.SHARE_NAME, 

7975 'vserver': fake.VSERVER_NAME, 

7976 }, 

7977 }, 

7978 'desired-attributes': { 

7979 'volume-move-info': { 

7980 'percent-complete': None, 

7981 'estimated-completion-time': None, 

7982 'state': None, 

7983 'details': None, 

7984 'cutover-action': None, 

7985 'phase': None, 

7986 }, 

7987 }, 

7988 } 

7989 expected_status_info = { 

7990 'percent-complete': '82', 

7991 'estimated-completion-time': '1481919246', 

7992 'state': 'healthy', 

7993 'details': 'Cutover Completed::Volume move job finishing move', 

7994 'cutover-action': 'retry_on_failure', 

7995 'phase': 'finishing', 

7996 } 

7997 

7998 self.assertDictEqual(expected_status_info, actual_status_info) 

7999 self.client.send_iter_request.assert_called_once_with( 

8000 'volume-move-get-iter', expected_api_args) 

8001 

8002 def test_qos_policy_group_exists_no_records(self): 

8003 self.mock_object(self.client, 'qos_policy_group_get', mock.Mock( 

8004 side_effect=exception.NetAppException)) 

8005 

8006 policy_exists = self.client.qos_policy_group_exists( 

8007 'i-dont-exist-but-i-am') 

8008 

8009 self.assertIs(False, policy_exists) 

8010 

8011 def test_qos_policy_group_exists(self): 

8012 self.mock_object(self.client, 'qos_policy_group_get', 

8013 mock.Mock(return_value=fake.QOS_POLICY_GROUP)) 

8014 

8015 policy_exists = self.client.qos_policy_group_exists( 

8016 fake.QOS_POLICY_GROUP_NAME) 

8017 

8018 self.assertIs(True, policy_exists) 

8019 

8020 def test_qos_policy_group_get_no_permissions_to_execute_zapi(self): 

8021 naapi_error = self._mock_api_error(code=netapp_api.EAPINOTFOUND, 

8022 message='13005:Unable to find API') 

8023 self.mock_object(self.client, 'send_request', naapi_error) 

8024 

8025 self.assertRaises(exception.NetAppException, 

8026 self.client.qos_policy_group_get, 

8027 'possibly-valid-qos-policy') 

8028 

8029 def test_qos_policy_group_get_other_zapi_errors(self): 

8030 naapi_error = self._mock_api_error(code=netapp_api.EINTERNALERROR, 

8031 message='13114:Internal error') 

8032 self.mock_object(self.client, 'send_request', naapi_error) 

8033 

8034 self.assertRaises(netapp_api.NaApiError, 

8035 self.client.qos_policy_group_get, 

8036 'possibly-valid-qos-policy') 

8037 

8038 def test_qos_policy_group_get_none_found(self): 

8039 no_records_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

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

8041 mock.Mock(return_value=no_records_response)) 

8042 

8043 self.assertRaises(exception.NetAppException, 

8044 self.client.qos_policy_group_get, 

8045 'non-existent-qos-policy') 

8046 

8047 qos_policy_group_get_iter_args = { 

8048 'query': { 

8049 'qos-policy-group-info': { 

8050 'policy-group': 'non-existent-qos-policy', 

8051 }, 

8052 }, 

8053 'desired-attributes': { 

8054 'qos-policy-group-info': { 

8055 'policy-group': None, 

8056 'vserver': None, 

8057 'max-throughput': None, 

8058 'min-throughput': None, 

8059 'num-workloads': None 

8060 }, 

8061 }, 

8062 } 

8063 

8064 self.client.send_request.assert_called_once_with( 

8065 'qos-policy-group-get-iter', qos_policy_group_get_iter_args, False) 

8066 

8067 def test_qos_policy_group_get(self): 

8068 api_response = netapp_api.NaElement( 

8069 fake.QOS_POLICY_GROUP_GET_ITER_RESPONSE) 

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

8071 mock.Mock(return_value=api_response)) 

8072 

8073 qos_info = self.client.qos_policy_group_get(fake.QOS_POLICY_GROUP_NAME) 

8074 

8075 qos_policy_group_get_iter_args = { 

8076 'query': { 

8077 'qos-policy-group-info': { 

8078 'policy-group': fake.QOS_POLICY_GROUP_NAME, 

8079 }, 

8080 }, 

8081 'desired-attributes': { 

8082 'qos-policy-group-info': { 

8083 'policy-group': None, 

8084 'vserver': None, 

8085 'max-throughput': None, 

8086 'min-throughput': None, 

8087 'num-workloads': None 

8088 }, 

8089 }, 

8090 } 

8091 self.client.send_request.assert_called_once_with( 

8092 'qos-policy-group-get-iter', qos_policy_group_get_iter_args, False) 

8093 self.assertDictEqual(fake.QOS_POLICY_GROUP, qos_info) 

8094 

8095 @ddt.data( 

8096 {'max_throughput': None, 'min_throughput': None}, 

8097 {'max_throughput': fake.QOS_MAX_THROUGHPUT, 'min_throughput': None}, 

8098 {'max_throughput': None, 'min_throughput': fake.QOS_MIN_THROUGHPUT}, 

8099 {'max_throughput': fake.QOS_MAX_THROUGHPUT, 

8100 'min_throughput': fake.QOS_MIN_THROUGHPUT}) 

8101 @ddt.unpack 

8102 def test_qos_policy_group_create(self, max_throughput, min_throughput): 

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

8104 mock.Mock(return_value=fake.PASSED_RESPONSE)) 

8105 

8106 self.client.qos_policy_group_create( 

8107 fake.QOS_POLICY_GROUP_NAME, fake.VSERVER_NAME, 

8108 max_throughput=max_throughput, 

8109 min_throughput=min_throughput) 

8110 

8111 qos_policy_group_create_args = { 

8112 'policy-group': fake.QOS_POLICY_GROUP_NAME, 

8113 'vserver': fake.VSERVER_NAME, 

8114 } 

8115 if max_throughput: 

8116 qos_policy_group_create_args.update( 

8117 {'max-throughput': max_throughput}) 

8118 if min_throughput: 

8119 qos_policy_group_create_args.update( 

8120 {'min-throughput': min_throughput}) 

8121 

8122 self.client.send_request.assert_called_once_with( 

8123 'qos-policy-group-create', qos_policy_group_create_args, False) 

8124 

8125 def test_qos_policy_group_modify(self): 

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

8127 mock.Mock(return_value=fake.PASSED_RESPONSE)) 

8128 

8129 self.client.qos_policy_group_modify(fake.QOS_POLICY_GROUP_NAME, 

8130 '3000iops', '20iops') 

8131 

8132 qos_policy_group_modify_args = { 

8133 'policy-group': fake.QOS_POLICY_GROUP_NAME, 

8134 'max-throughput': '3000iops', 

8135 'min-throughput': '20iops', 

8136 } 

8137 

8138 self.client.send_request.assert_called_once_with( 

8139 'qos-policy-group-modify', qos_policy_group_modify_args, False) 

8140 

8141 def test_qos_policy_group_delete(self): 

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

8143 mock.Mock(return_value=fake.PASSED_RESPONSE)) 

8144 

8145 self.client.qos_policy_group_delete(fake.QOS_POLICY_GROUP_NAME) 

8146 

8147 qos_policy_group_delete_args = { 

8148 'policy-group': fake.QOS_POLICY_GROUP_NAME, 

8149 } 

8150 

8151 self.client.send_request.assert_called_once_with( 

8152 'qos-policy-group-delete', qos_policy_group_delete_args, False) 

8153 

8154 def test_qos_policy_group_rename(self): 

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

8156 mock.Mock(return_value=fake.PASSED_RESPONSE)) 

8157 

8158 self.client.qos_policy_group_rename( 

8159 fake.QOS_POLICY_GROUP_NAME, 'new_' + fake.QOS_POLICY_GROUP_NAME) 

8160 

8161 qos_policy_group_rename_args = { 

8162 'policy-group-name': fake.QOS_POLICY_GROUP_NAME, 

8163 'new-name': 'new_' + fake.QOS_POLICY_GROUP_NAME, 

8164 } 

8165 

8166 self.client.send_request.assert_called_once_with( 

8167 'qos-policy-group-rename', qos_policy_group_rename_args, False) 

8168 

8169 def test_qos_policy_group_rename_noop(self): 

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

8171 

8172 # rename to same name = no-op 

8173 self.client.qos_policy_group_rename( 

8174 fake.QOS_POLICY_GROUP_NAME, fake.QOS_POLICY_GROUP_NAME) 

8175 

8176 self.assertFalse(self.client.send_request.called) 

8177 

8178 def test_mark_qos_policy_group_for_deletion_rename_failure(self): 

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

8180 mock.Mock(return_value=True)) 

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

8182 mock.Mock(side_effect=netapp_api.NaApiError)) 

8183 self.mock_object(client_cmode.LOG, 'warning') 

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

8185 

8186 retval = self.client.mark_qos_policy_group_for_deletion( 

8187 fake.QOS_POLICY_GROUP_NAME) 

8188 

8189 self.assertIsNone(retval) 

8190 client_cmode.LOG.warning.assert_called_once() 

8191 self.client.qos_policy_group_exists.assert_called_once_with( 

8192 fake.QOS_POLICY_GROUP_NAME) 

8193 self.client.qos_policy_group_rename.assert_called_once_with( 

8194 fake.QOS_POLICY_GROUP_NAME, 

8195 client_cmode.DELETED_PREFIX + fake.QOS_POLICY_GROUP_NAME) 

8196 self.client.remove_unused_qos_policy_groups.assert_called_once_with() 

8197 

8198 @ddt.data(True, False) 

8199 def test_mark_qos_policy_group_for_deletion_policy_exists(self, exists): 

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

8201 mock.Mock(return_value=exists)) 

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

8203 mock_remove_unused_policies = self.mock_object( 

8204 self.client, 'remove_unused_qos_policy_groups') 

8205 self.mock_object(client_cmode.LOG, 'warning') 

8206 

8207 retval = self.client.mark_qos_policy_group_for_deletion( 

8208 fake.QOS_POLICY_GROUP_NAME) 

8209 

8210 self.assertIsNone(retval) 

8211 

8212 if exists: 

8213 self.client.qos_policy_group_rename.assert_called_once_with( 

8214 fake.QOS_POLICY_GROUP_NAME, 

8215 client_cmode.DELETED_PREFIX + fake.QOS_POLICY_GROUP_NAME) 

8216 mock_remove_unused_policies.assert_called_once_with() 

8217 else: 

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

8219 self.assertFalse( 

8220 self.client.remove_unused_qos_policy_groups.called) 

8221 self.assertFalse(client_cmode.LOG.warning.called) 

8222 

8223 @ddt.data(True, False) 

8224 def test_remove_unused_qos_policy_groups_with_failure(self, failed): 

8225 

8226 if failed: 

8227 args = mock.Mock(side_effect=netapp_api.NaApiError) 

8228 else: 

8229 args = mock.Mock(return_value=fake.PASSED_FAILED_ITER_RESPONSE) 

8230 

8231 self.mock_object(self.client, 'send_request', args) 

8232 self.mock_object(client_cmode.LOG, 'debug') 

8233 

8234 retval = self.client.remove_unused_qos_policy_groups() 

8235 

8236 qos_policy_group_delete_iter_args = { 

8237 'query': { 

8238 'qos-policy-group-info': { 

8239 'policy-group': '%s*' % client_cmode.DELETED_PREFIX, 

8240 } 

8241 }, 

8242 'max-records': 3500, 

8243 'continue-on-failure': 'true', 

8244 'return-success-list': 'false', 

8245 'return-failure-list': 'false', 

8246 } 

8247 

8248 self.assertIsNone(retval) 

8249 self.client.send_request.assert_called_once_with( 

8250 'qos-policy-group-delete-iter', 

8251 qos_policy_group_delete_iter_args, False) 

8252 self.assertIs(failed, client_cmode.LOG.debug.called) 

8253 

8254 def test_get_cluster_name(self): 

8255 api_response = netapp_api.NaElement( 

8256 fake.CLUSTER_GET_CLUSTER_NAME) 

8257 self.mock_object(self.client, 

8258 'send_request', 

8259 mock.Mock(return_value=api_response)) 

8260 api_args = { 

8261 'desired-attributes': { 

8262 'cluster-identity-info': { 

8263 'cluster-name': None, 

8264 } 

8265 } 

8266 } 

8267 result = self.client.get_cluster_name() 

8268 

8269 self.assertEqual(fake.CLUSTER_NAME, result) 

8270 self.client.send_request.assert_called_once_with( 

8271 'cluster-identity-get', api_args, enable_tunneling=False) 

8272 

8273 @ddt.data('fake_snapshot_name', None) 

8274 def test_check_volume_clone_split_completed(self, get_clone_parent): 

8275 volume_name = fake.SHARE_NAME 

8276 mock_get_vol_clone_parent = self.mock_object( 

8277 self.client, 'get_volume_clone_parent_snaphot', 

8278 mock.Mock(return_value=get_clone_parent)) 

8279 

8280 result = self.client.check_volume_clone_split_completed(volume_name) 

8281 

8282 mock_get_vol_clone_parent.assert_called_once_with(volume_name) 

8283 expected_result = get_clone_parent is None 

8284 self.assertEqual(expected_result, result) 

8285 

8286 def test_rehost_volume(self): 

8287 volume_name = fake.SHARE_NAME 

8288 vserver = fake.VSERVER_NAME 

8289 dest_vserver = fake.VSERVER_NAME_2 

8290 api_args = { 

8291 'volume': volume_name, 

8292 'vserver': vserver, 

8293 'destination-vserver': dest_vserver, 

8294 } 

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

8296 

8297 self.client.rehost_volume(volume_name, vserver, dest_vserver) 

8298 

8299 self.client.send_request.assert_called_once_with('volume-rehost', 

8300 api_args) 

8301 

8302 @ddt.data( 

8303 {'fake_api_response': fake.VOLUME_GET_ITER_PARENT_SNAP_EMPTY_RESPONSE, 

8304 'expected_snapshot_name': None}, 

8305 {'fake_api_response': fake.VOLUME_GET_ITER_PARENT_SNAP_RESPONSE, 

8306 'expected_snapshot_name': fake.SNAPSHOT_NAME}, 

8307 {'fake_api_response': fake.NO_RECORDS_RESPONSE, 

8308 'expected_snapshot_name': None}) 

8309 @ddt.unpack 

8310 def test_get_volume_clone_parent_snaphot(self, fake_api_response, 

8311 expected_snapshot_name): 

8312 

8313 api_response = netapp_api.NaElement(fake_api_response) 

8314 self.mock_object(self.client, 

8315 'send_iter_request', 

8316 mock.Mock(return_value=api_response)) 

8317 

8318 result = self.client.get_volume_clone_parent_snaphot(fake.SHARE_NAME) 

8319 

8320 expected_api_args = { 

8321 'query': { 

8322 'volume-attributes': { 

8323 'volume-id-attributes': { 

8324 'name': fake.SHARE_NAME 

8325 } 

8326 } 

8327 }, 

8328 'desired-attributes': { 

8329 'volume-attributes': { 

8330 'volume-clone-attributes': { 

8331 'volume-clone-parent-attributes': { 

8332 'snapshot-name': '' 

8333 } 

8334 } 

8335 } 

8336 } 

8337 } 

8338 self.client.send_iter_request.assert_called_once_with( 

8339 'volume-get-iter', expected_api_args) 

8340 self.assertEqual(expected_snapshot_name, result) 

8341 

8342 def test_set_qos_adaptive_policy_group_for_volume(self): 

8343 

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

8345 

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

8347 

8348 self.client.set_qos_adaptive_policy_group_for_volume( 

8349 fake.SHARE_NAME, 

8350 fake.QOS_POLICY_GROUP_NAME) 

8351 

8352 volume_modify_iter_args = { 

8353 'query': { 

8354 'volume-attributes': { 

8355 'volume-id-attributes': { 

8356 'name': fake.SHARE_NAME, 

8357 }, 

8358 }, 

8359 }, 

8360 'attributes': { 

8361 'volume-attributes': { 

8362 'volume-qos-attributes': { 

8363 'adaptive-policy-group-name': 

8364 fake.QOS_POLICY_GROUP_NAME, 

8365 }, 

8366 }, 

8367 }, 

8368 } 

8369 self.client.send_request.assert_called_once_with( 

8370 'volume-modify-iter', volume_modify_iter_args) 

8371 

8372 def test_get_nfs_config(self): 

8373 api_args = { 

8374 'query': { 

8375 'nfs-info': { 

8376 'vserver': 'vserver', 

8377 }, 

8378 }, 

8379 'desired-attributes': { 

8380 'nfs-info': { 

8381 'field': None, 

8382 }, 

8383 }, 

8384 } 

8385 api_response = netapp_api.NaElement( 

8386 fake.NFS_CONFIG_SERVER_RESULT) 

8387 self.mock_object(self.client, 

8388 'send_request', 

8389 mock.Mock(return_value=api_response)) 

8390 self.mock_object(self.client, 

8391 'parse_nfs_config', 

8392 mock.Mock(return_value=None)) 

8393 

8394 self.client.get_nfs_config(['field'], 'vserver') 

8395 

8396 self.client.send_request.assert_called_once_with( 

8397 'nfs-service-get-iter', api_args) 

8398 

8399 def test_get_nfs_config_default(self): 

8400 api_response = netapp_api.NaElement( 

8401 fake.NFS_CONFIG_DEFAULT_RESULT) 

8402 self.mock_object(self.client, 

8403 'send_request', 

8404 mock.Mock(return_value=api_response)) 

8405 self.mock_object(self.client, 

8406 'parse_nfs_config', 

8407 mock.Mock(return_value=None)) 

8408 

8409 self.client.get_nfs_config_default(['field']) 

8410 

8411 self.client.send_request.assert_called_once_with( 

8412 'nfs-service-get-create-defaults', None) 

8413 

8414 @ddt.data( 

8415 {'nfs_info': fake.NFS_CONFIG_SERVER_RESULT, 

8416 'desired_args': ['tcp-max-xfer-size'], 

8417 'expected_nfs': { 

8418 'tcp-max-xfer-size': '65536', 

8419 }}, 

8420 {'nfs_info': fake.NFS_CONFIG_SERVER_RESULT, 

8421 'desired_args': ['udp-max-xfer-size'], 

8422 'expected_nfs': { 

8423 'udp-max-xfer-size': '32768', 

8424 }}, 

8425 {'nfs_info': fake.NFS_CONFIG_SERVER_RESULT, 

8426 'desired_args': ['tcp-max-xfer-size', 'udp-max-xfer-size'], 

8427 'expected_nfs': { 

8428 'tcp-max-xfer-size': '65536', 

8429 'udp-max-xfer-size': '32768', 

8430 }}, 

8431 {'nfs_info': fake.NFS_CONFIG_SERVER_RESULT, 

8432 'desired_args': [], 

8433 'expected_nfs': {}}) 

8434 @ddt.unpack 

8435 def test_parse_nfs_config(self, nfs_info, desired_args, expected_nfs): 

8436 parent_elem = netapp_api.NaElement(nfs_info).get_child_by_name( 

8437 'attributes-list') 

8438 

8439 nfs_config = self.client.parse_nfs_config(parent_elem, desired_args) 

8440 

8441 self.assertDictEqual(nfs_config, expected_nfs) 

8442 

8443 @ddt.data(fake.NO_RECORDS_RESPONSE, 

8444 fake.VSERVER_GET_ITER_RESPONSE_INFO) 

8445 def test_get_vserver_info(self, api_response): 

8446 self.mock_object(self.client, 'send_iter_request', 

8447 mock.Mock( 

8448 return_value=netapp_api.NaElement( 

8449 api_response))) 

8450 

8451 result = self.client.get_vserver_info(fake.VSERVER_NAME) 

8452 

8453 expected_api_args = { 

8454 'query': { 

8455 'vserver-info': { 

8456 'vserver-name': fake.VSERVER_NAME, 

8457 }, 

8458 }, 

8459 'desired-attributes': { 

8460 'vserver-info': { 

8461 'vserver-name': None, 

8462 'vserver-subtype': None, 

8463 'state': None, 

8464 'operational-state': None, 

8465 }, 

8466 }, 

8467 } 

8468 self.client.send_iter_request.assert_called_once_with( 

8469 'vserver-get-iter', expected_api_args) 

8470 if api_response == fake.NO_RECORDS_RESPONSE: 

8471 self.assertIsNone(result) 

8472 else: 

8473 self.assertDictEqual(fake.VSERVER_INFO, result) 

8474 

8475 @ddt.data({'discard_network': True, 'preserve_snapshots': False}, 

8476 {'discard_network': False, 'preserve_snapshots': True}) 

8477 @ddt.unpack 

8478 def test_create_snapmirror_policy(self, discard_network, 

8479 preserve_snapshots): 

8480 api_response = netapp_api.NaElement(fake.PASSED_RESPONSE) 

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

8482 mock.Mock(return_value=api_response)) 

8483 

8484 self.client.create_snapmirror_policy( 

8485 fake.SNAPMIRROR_POLICY_NAME, discard_network_info=discard_network, 

8486 snapmirror_label="backup", preserve_snapshots=preserve_snapshots) 

8487 expected_create_api_args = { 

8488 'policy-name': fake.SNAPMIRROR_POLICY_NAME, 

8489 'type': 'async_mirror', 

8490 } 

8491 if discard_network: 

8492 expected_create_api_args['discard-configs'] = { 

8493 'svmdr-config-obj': 'network' 

8494 } 

8495 expected_calls = [ 

8496 mock.call('snapmirror-policy-create', expected_create_api_args) 

8497 ] 

8498 

8499 if preserve_snapshots: 

8500 expected_add_rules = { 

8501 'policy-name': fake.SNAPMIRROR_POLICY_NAME, 

8502 'snapmirror-label': 'backup', 

8503 'keep': 1, 

8504 'preserve': 'false' 

8505 } 

8506 expected_calls.append(mock.call('snapmirror-policy-add-rule', 

8507 expected_add_rules)) 

8508 

8509 self.client.send_request.assert_has_calls(expected_calls) 

8510 

8511 def test_delete_snapmirror_policy(self): 

8512 api_response = netapp_api.NaElement(fake.PASSED_RESPONSE) 

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

8514 mock.Mock(return_value=api_response)) 

8515 

8516 self.client.delete_snapmirror_policy(fake.SNAPMIRROR_POLICY_NAME) 

8517 

8518 expected_api_args = { 

8519 'policy-name': fake.SNAPMIRROR_POLICY_NAME, 

8520 } 

8521 

8522 self.client.send_request.assert_called_once_with( 

8523 'snapmirror-policy-delete', expected_api_args) 

8524 

8525 def test_delete_snapmirror_policy_not_found(self): 

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

8527 self._mock_api_error(code=netapp_api.EOBJECTNOTFOUND)) 

8528 

8529 self.client.delete_snapmirror_policy(fake.SNAPMIRROR_POLICY_NAME) 

8530 

8531 expected_api_args = { 

8532 'policy-name': fake.SNAPMIRROR_POLICY_NAME, 

8533 } 

8534 

8535 self.client.send_request.assert_called_once_with( 

8536 'snapmirror-policy-delete', expected_api_args) 

8537 

8538 def test_get_snapmirror_policies(self): 

8539 api_response = netapp_api.NaElement( 

8540 fake.SNAPMIRROR_POLICY_GET_ITER_RESPONSE) 

8541 self.mock_object(self.client, 'send_iter_request', 

8542 mock.Mock(return_value=api_response)) 

8543 result_elem = [fake.SNAPMIRROR_POLICY_NAME] 

8544 

8545 result = self.client.get_snapmirror_policies( 

8546 fake.VSERVER_NAME) 

8547 

8548 expected_api_args = { 

8549 'query': { 

8550 'snapmirror-policy-info': { 

8551 'vserver-name': fake.VSERVER_NAME, 

8552 }, 

8553 }, 

8554 'desired-attributes': { 

8555 'snapmirror-policy-info': { 

8556 'policy-name': None, 

8557 }, 

8558 }, 

8559 } 

8560 

8561 self.client.send_iter_request.assert_called_once_with( 

8562 'snapmirror-policy-get-iter', expected_api_args) 

8563 self.assertEqual(result_elem, result) 

8564 

8565 @ddt.data(True, False, None) 

8566 def test_start_vserver(self, force): 

8567 api_response = netapp_api.NaElement(fake.PASSED_RESPONSE) 

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

8569 mock.Mock(return_value=api_response)) 

8570 

8571 self.client.start_vserver(fake.VSERVER_NAME, force=force) 

8572 

8573 expected_api_args = { 

8574 'vserver-name': fake.VSERVER_NAME, 

8575 } 

8576 if force is not None: 

8577 expected_api_args['force'] = 'true' if force is True else 'false' 

8578 

8579 self.client.send_request.assert_called_once_with( 

8580 'vserver-start', expected_api_args, enable_tunneling=False) 

8581 

8582 def test_start_vserver_already_started(self): 

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

8584 self._mock_api_error( 

8585 code=netapp_api.EVSERVERALREADYSTARTED)) 

8586 

8587 self.client.start_vserver(fake.VSERVER_NAME) 

8588 

8589 expected_api_args = { 

8590 'vserver-name': fake.VSERVER_NAME, 

8591 } 

8592 

8593 self.client.send_request.assert_called_once_with( 

8594 'vserver-start', expected_api_args, enable_tunneling=False) 

8595 

8596 def test_stop_vserver(self): 

8597 api_response = netapp_api.NaElement(fake.PASSED_RESPONSE) 

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

8599 mock.Mock(return_value=api_response)) 

8600 

8601 self.client.stop_vserver(fake.VSERVER_NAME) 

8602 

8603 expected_api_args = { 

8604 'vserver-name': fake.VSERVER_NAME, 

8605 } 

8606 

8607 self.client.send_request.assert_called_once_with( 

8608 'vserver-stop', expected_api_args, enable_tunneling=False) 

8609 

8610 def test_is_svm_dr_supported(self): 

8611 self.client.features.add_feature('SVM_DR') 

8612 

8613 result = self.client.is_svm_dr_supported() 

8614 

8615 self.assertTrue(result) 

8616 

8617 @ddt.data({'get_iter_response': fake.CIFS_SHARE_GET_ITER_RESPONSE, 

8618 'expected_result': True}, 

8619 {'get_iter_response': fake.NO_RECORDS_RESPONSE, 

8620 'expected_result': False}) 

8621 @ddt.unpack 

8622 def test_cifs_share_exists(self, get_iter_response, expected_result): 

8623 api_response = netapp_api.NaElement(get_iter_response) 

8624 self.mock_object(self.client, 

8625 'send_iter_request', 

8626 mock.Mock(return_value=api_response)) 

8627 fake_share_path = '/%s' % fake.SHARE_NAME 

8628 

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

8630 

8631 cifs_share_get_iter_args = { 

8632 'query': { 

8633 'cifs-share': { 

8634 'share-name': fake.SHARE_NAME, 

8635 'path': fake_share_path, 

8636 }, 

8637 }, 

8638 'desired-attributes': { 

8639 'cifs-share': { 

8640 'share-name': None 

8641 } 

8642 }, 

8643 } 

8644 self.assertEqual(expected_result, result) 

8645 self.client.send_iter_request.assert_called_once_with( 

8646 'cifs-share-get-iter', cifs_share_get_iter_args) 

8647 

8648 def test_get_volume_autosize_attributes(self): 

8649 api_response = netapp_api.NaElement(fake.VOLUME_AUTOSIZE_GET_RESPONSE) 

8650 self.mock_object(self.client, 

8651 'send_request', 

8652 mock.Mock(return_value=api_response)) 

8653 

8654 result = self.client.get_volume_autosize_attributes(fake.SHARE_NAME) 

8655 

8656 expected_result = {} 

8657 expected_keys = ['mode', 'grow-threshold-percent', 'minimum-size', 

8658 'shrink-threshold-percent', 'maximum-size'] 

8659 for key in expected_keys: 

8660 expected_result[key] = fake.VOLUME_AUTOSIZE_ATTRS[key] 

8661 

8662 self.assertEqual(expected_result, result) 

8663 self.client.send_request.assert_called_once_with( 

8664 'volume-autosize-get', {'volume': fake.SHARE_NAME}) 

8665 

8666 @ddt.data('server_to_server', 

8667 'server_to_default_ad_site', 

8668 'default_ad_site_to_default_ad_site', 

8669 'default_ad_site_to_server') 

8670 def test_modify_active_directory_security_service(self, 

8671 modify_ad_direction): 

8672 if modify_ad_direction == 'server_to_server': 

8673 curr_sec_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE) 

8674 new_sec_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE_2) 

8675 if modify_ad_direction == 'server_to_default_ad_site': 

8676 curr_sec_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE) 

8677 new_sec_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE_3) 

8678 if modify_ad_direction == 'default_ad_site_to_default_ad_site': 

8679 curr_sec_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE_3) 

8680 new_sec_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE_4) 

8681 if modify_ad_direction == 'default_ad_site_to_server': 

8682 curr_sec_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE_4) 

8683 new_sec_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE_2) 

8684 

8685 # we don't support domain change, but this validation isn't made in 

8686 # within this method 

8687 new_sec_service['domain'] = curr_sec_service['domain'] 

8688 api_responses = [fake.PASSED_RESPONSE, fake.PASSED_RESPONSE, 

8689 fake.PASSED_RESPONSE] 

8690 

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

8692 mock.Mock(side_effect=api_responses)) 

8693 self.mock_object(self.client, 'remove_preferred_dcs') 

8694 self.mock_object(self.client, 'set_preferred_dc') 

8695 self.mock_object(self.client, 'configure_cifs_options') 

8696 differing_keys = {'password', 'user', 'server', 'default_ad_site'} 

8697 

8698 self.client.modify_active_directory_security_service( 

8699 fake.VSERVER_NAME, differing_keys, new_sec_service, 

8700 curr_sec_service) 

8701 

8702 cifs_server = self.client._get_cifs_server_name(fake.VSERVER_NAME) 

8703 current_cifs_username = cifs_server + '\\' + curr_sec_service['user'] 

8704 set_pass_api_args = { 

8705 'user-name': current_cifs_username, 

8706 'user-password': new_sec_service['password'] 

8707 } 

8708 user_rename_api_args = { 

8709 'user-name': current_cifs_username, 

8710 'new-user-name': new_sec_service['user'] 

8711 } 

8712 

8713 self.client.send_request.assert_has_calls([ 

8714 mock.call('cifs-local-user-set-password', set_pass_api_args), 

8715 mock.call('cifs-local-user-rename', user_rename_api_args)]) 

8716 

8717 if modify_ad_direction in ('default_ad_site_to_default_ad_site', 

8718 'server_to_default_ad_site'): 

8719 cifs_server_modify_args = { 

8720 'admin-username': new_sec_service['user'], 

8721 'admin-password': new_sec_service['password'], 

8722 'force-account-overwrite': 'true', 

8723 'cifs-server': cifs_server, 

8724 'default-site': new_sec_service['default_ad_site'], 

8725 } 

8726 self.client.send_request.assert_has_calls([ 

8727 mock.call('cifs-server-modify', cifs_server_modify_args)]) 

8728 self.client.configure_cifs_options.assert_has_calls([ 

8729 mock.call(new_sec_service)]) 

8730 if modify_ad_direction in ('server_to_server', 

8731 'server_to_default_ad_site'): 

8732 self.client.remove_preferred_dcs.assert_called_once_with( 

8733 curr_sec_service) 

8734 if modify_ad_direction in ('server_to_server', 

8735 'default_ad_site_to_server'): 

8736 self.client.set_preferred_dc.assert_called_once_with( 

8737 new_sec_service) 

8738 self.client.configure_cifs_options.assert_has_calls([ 

8739 mock.call(new_sec_service)]) 

8740 

8741 @ddt.data(True, False) 

8742 def test_modify_active_directory_security_service_error( 

8743 self, cifs_set_password_failure): 

8744 curr_sec_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE) 

8745 new_sec_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE_2) 

8746 # we don't support domain change, but this validation isn't made in 

8747 # within this method 

8748 new_sec_service['domain'] = curr_sec_service['domain'] 

8749 if cifs_set_password_failure: 

8750 api_responses = [netapp_api.NaApiError(code='fake'), 

8751 fake.PASSED_RESPONSE] 

8752 else: 

8753 api_responses = [fake.PASSED_RESPONSE, 

8754 netapp_api.NaApiError(code='fake')] 

8755 

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

8757 mock.Mock(side_effect=api_responses)) 

8758 differing_keys = {'password', 'user', 'server'} 

8759 

8760 self.assertRaises( 

8761 exception.NetAppException, 

8762 self.client.modify_active_directory_security_service, 

8763 fake.VSERVER_NAME, differing_keys, new_sec_service, 

8764 curr_sec_service) 

8765 

8766 cifs_server = self.client._get_cifs_server_name(fake.VSERVER_NAME) 

8767 current_cifs_username = cifs_server + '\\' + curr_sec_service['user'] 

8768 set_pass_api_args = { 

8769 'user-name': current_cifs_username, 

8770 'user-password': new_sec_service['password'] 

8771 } 

8772 user_rename_api_args = { 

8773 'user-name': current_cifs_username, 

8774 'new-user-name': new_sec_service['user'] 

8775 } 

8776 

8777 if cifs_set_password_failure: 

8778 send_request_calls = [ 

8779 mock.call('cifs-local-user-set-password', set_pass_api_args)] 

8780 else: 

8781 send_request_calls = [ 

8782 mock.call('cifs-local-user-set-password', set_pass_api_args), 

8783 mock.call('cifs-local-user-rename', user_rename_api_args) 

8784 ] 

8785 

8786 self.client.send_request.assert_has_calls(send_request_calls) 

8787 

8788 @ddt.data(False, True) 

8789 def test_modify_ldap(self, api_not_found): 

8790 current_ldap_service = fake.LDAP_AD_SECURITY_SERVICE 

8791 new_ldap_service = fake.LDAP_LINUX_SECURITY_SERVICE 

8792 config_name = hashlib.md5( 

8793 new_ldap_service['id'].encode("latin-1")).hexdigest() 

8794 api_result = (self._mock_api_error(code=netapp_api.EOBJECTNOTFOUND) 

8795 if api_not_found else mock.Mock()) 

8796 mock_create_client = self.mock_object( 

8797 self.client, '_create_ldap_client') 

8798 mock_send_request = self.mock_object( 

8799 self.client, 'send_request', 

8800 mock.Mock(return_value=api_result)) 

8801 mock_delete_client = self.mock_object( 

8802 self.client, '_delete_ldap_client', 

8803 mock.Mock(return_value=api_result)) 

8804 

8805 self.client.modify_ldap(new_ldap_service, current_ldap_service) 

8806 

8807 api_args = {'client-config': config_name, 'client-enabled': 'true'} 

8808 mock_create_client.assert_called_once_with(new_ldap_service) 

8809 mock_send_request.assert_has_calls([ 

8810 mock.call('ldap-config-delete'), 

8811 mock.call('ldap-config-create', api_args)]) 

8812 mock_delete_client.assert_called_once_with(current_ldap_service) 

8813 

8814 def test_modify_ldap_config_delete_failure(self): 

8815 current_ldap_service = fake.LDAP_AD_SECURITY_SERVICE 

8816 new_ldap_service = fake.LDAP_LINUX_SECURITY_SERVICE 

8817 mock_create_client = self.mock_object( 

8818 self.client, '_create_ldap_client') 

8819 mock_send_request = self.mock_object( 

8820 self.client, 'send_request', mock.Mock( 

8821 side_effect=netapp_api.NaApiError(code=netapp_api.EAPIERROR))) 

8822 mock_delete_client = self.mock_object( 

8823 self.client, '_delete_ldap_client') 

8824 

8825 self.assertRaises(exception.NetAppException, 

8826 self.client.modify_ldap, 

8827 new_ldap_service, 

8828 current_ldap_service) 

8829 

8830 mock_create_client.assert_called_once_with(new_ldap_service) 

8831 mock_send_request.assert_called_once_with('ldap-config-delete') 

8832 mock_delete_client.assert_called_once_with(new_ldap_service) 

8833 

8834 def test_modify_ldap_current_config_delete_error(self): 

8835 current_ldap_service = fake.LDAP_AD_SECURITY_SERVICE 

8836 new_ldap_service = fake.LDAP_LINUX_SECURITY_SERVICE 

8837 config_name = hashlib.md5( 

8838 new_ldap_service['id'].encode("latin-1")).hexdigest() 

8839 mock_create_client = self.mock_object( 

8840 self.client, '_create_ldap_client') 

8841 mock_send_request = self.mock_object( 

8842 self.client, 'send_request') 

8843 mock_delete_client = self.mock_object( 

8844 self.client, '_delete_ldap_client', mock.Mock( 

8845 side_effect=netapp_api.NaApiError(code=netapp_api.EAPIERROR))) 

8846 

8847 self.client.modify_ldap(new_ldap_service, current_ldap_service) 

8848 

8849 api_args = {'client-config': config_name, 'client-enabled': 'true'} 

8850 mock_create_client.assert_called_once_with(new_ldap_service) 

8851 mock_send_request.assert_has_calls([ 

8852 mock.call('ldap-config-delete'), 

8853 mock.call('ldap-config-create', api_args)]) 

8854 mock_delete_client.assert_called_once_with(current_ldap_service) 

8855 

8856 def test_create_fpolicy_event(self): 

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

8858 

8859 self.client.create_fpolicy_event(fake.SHARE_NAME, 

8860 fake.FPOLICY_EVENT_NAME, 

8861 fake.FPOLICY_PROTOCOL, 

8862 fake.FPOLICY_FILE_OPERATIONS_LIST) 

8863 

8864 expected_args = { 

8865 'event-name': fake.FPOLICY_EVENT_NAME, 

8866 'protocol': fake.FPOLICY_PROTOCOL, 

8867 'file-operations': [], 

8868 } 

8869 for file_op in fake.FPOLICY_FILE_OPERATIONS_LIST: 

8870 expected_args['file-operations'].append( 

8871 {'fpolicy-operation': file_op}) 

8872 

8873 self.client.send_request.assert_called_once_with( 

8874 'fpolicy-policy-event-create', expected_args) 

8875 

8876 @ddt.data(None, netapp_api.EEVENTNOTFOUND) 

8877 def test_delete_fpolicy_event(self, send_request_error): 

8878 if send_request_error: 

8879 send_request_mock = mock.Mock( 

8880 side_effect=self._mock_api_error(code=send_request_error)) 

8881 else: 

8882 send_request_mock = mock.Mock() 

8883 self.mock_object(self.client, 'send_request', send_request_mock) 

8884 

8885 self.client.delete_fpolicy_event(fake.SHARE_NAME, 

8886 fake.FPOLICY_EVENT_NAME) 

8887 

8888 self.client.send_request.assert_called_once_with( 

8889 'fpolicy-policy-event-delete', 

8890 {'event-name': fake.FPOLICY_EVENT_NAME}) 

8891 

8892 def test_delete_fpolicy_event_error(self): 

8893 eapi_error = self._mock_api_error(code=netapp_api.EAPIERROR) 

8894 self.mock_object( 

8895 self.client, 'send_request', mock.Mock(side_effect=eapi_error)) 

8896 

8897 self.assertRaises(exception.NetAppException, 

8898 self.client.delete_fpolicy_event, 

8899 fake.SHARE_NAME, 

8900 fake.FPOLICY_EVENT_NAME) 

8901 

8902 self.client.send_request.assert_called_once_with( 

8903 'fpolicy-policy-event-delete', 

8904 {'event-name': fake.FPOLICY_EVENT_NAME}) 

8905 

8906 def test_get_fpolicy_events(self): 

8907 api_response = netapp_api.NaElement( 

8908 fake.FPOLICY_EVENT_GET_ITER_RESPONSE) 

8909 self.mock_object(self.client, 'send_iter_request', 

8910 mock.Mock(return_value=api_response)) 

8911 

8912 result = self.client.get_fpolicy_events( 

8913 event_name=fake.FPOLICY_EVENT_NAME, 

8914 protocol=fake.FPOLICY_PROTOCOL, 

8915 file_operations=fake.FPOLICY_FILE_OPERATIONS_LIST) 

8916 

8917 expected_options = { 

8918 'event-name': fake.FPOLICY_EVENT_NAME, 

8919 'protocol': fake.FPOLICY_PROTOCOL, 

8920 'file-operations': [] 

8921 } 

8922 for file_op in fake.FPOLICY_FILE_OPERATIONS_LIST: 

8923 expected_options['file-operations'].append( 

8924 {'fpolicy-operation': file_op}) 

8925 

8926 expected_args = { 

8927 'query': { 

8928 'fpolicy-event-options-config': expected_options, 

8929 }, 

8930 } 

8931 expected = [{ 

8932 'event-name': fake.FPOLICY_EVENT_NAME, 

8933 'protocol': fake.FPOLICY_PROTOCOL, 

8934 'file-operations': fake.FPOLICY_FILE_OPERATIONS_LIST 

8935 }] 

8936 

8937 self.assertEqual(expected, result) 

8938 self.client.send_iter_request.assert_called_once_with( 

8939 'fpolicy-policy-event-get-iter', expected_args) 

8940 

8941 def test_create_fpolicy_policy(self): 

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

8943 

8944 self.client.create_fpolicy_policy(fake.FPOLICY_POLICY_NAME, 

8945 fake.SHARE_NAME, 

8946 [fake.FPOLICY_EVENT_NAME], 

8947 engine=fake.FPOLICY_ENGINE) 

8948 

8949 expected_args = { 

8950 'policy-name': fake.FPOLICY_POLICY_NAME, 

8951 'events': [], 

8952 'engine-name': fake.FPOLICY_ENGINE 

8953 } 

8954 for event in [fake.FPOLICY_EVENT_NAME]: 

8955 expected_args['events'].append( 

8956 {'event-name': event}) 

8957 

8958 self.client.send_request.assert_called_once_with( 

8959 'fpolicy-policy-create', expected_args) 

8960 

8961 @ddt.data(None, netapp_api.EPOLICYNOTFOUND) 

8962 def test_delete_fpolicy_policy(self, send_request_error): 

8963 if send_request_error: 

8964 send_request_mock = mock.Mock( 

8965 side_effect=self._mock_api_error(code=send_request_error)) 

8966 else: 

8967 send_request_mock = mock.Mock() 

8968 self.mock_object(self.client, 'send_request', send_request_mock) 

8969 

8970 self.client.delete_fpolicy_policy( 

8971 fake.SHARE_NAME, fake.FPOLICY_POLICY_NAME) 

8972 

8973 self.client.send_request.assert_called_once_with( 

8974 'fpolicy-policy-delete', 

8975 {'policy-name': fake.FPOLICY_POLICY_NAME}) 

8976 

8977 def test_delete_fpolicy_policy_error(self): 

8978 eapi_error = self._mock_api_error(code=netapp_api.EAPIERROR) 

8979 self.mock_object( 

8980 self.client, 'send_request', mock.Mock(side_effect=eapi_error)) 

8981 

8982 self.assertRaises(exception.NetAppException, 

8983 self.client.delete_fpolicy_policy, 

8984 fake.SHARE_NAME, 

8985 fake.FPOLICY_POLICY_NAME) 

8986 

8987 self.client.send_request.assert_called_once_with( 

8988 'fpolicy-policy-delete', 

8989 {'policy-name': fake.FPOLICY_POLICY_NAME}) 

8990 

8991 def test_get_fpolicy_policies(self): 

8992 api_response = netapp_api.NaElement( 

8993 fake.FPOLICY_POLICY_GET_ITER_RESPONSE) 

8994 self.mock_object(self.client, 'send_iter_request', 

8995 mock.Mock(return_value=api_response)) 

8996 

8997 result = self.client.get_fpolicy_policies( 

8998 share_name=fake.SHARE_NAME, 

8999 policy_name=fake.FPOLICY_POLICY_NAME, 

9000 engine_name=fake.FPOLICY_ENGINE, 

9001 event_names=[fake.FPOLICY_EVENT_NAME]) 

9002 

9003 expected_options = { 

9004 'policy-name': fake.FPOLICY_POLICY_NAME, 

9005 'engine-name': fake.FPOLICY_ENGINE, 

9006 'events': [] 

9007 } 

9008 for policy in [fake.FPOLICY_EVENT_NAME]: 

9009 expected_options['events'].append( 

9010 {'event-name': policy}) 

9011 

9012 expected_args = { 

9013 'query': { 

9014 'fpolicy-policy-info': expected_options, 

9015 }, 

9016 } 

9017 expected = [{ 

9018 'policy-name': fake.FPOLICY_POLICY_NAME, 

9019 'engine-name': fake.FPOLICY_ENGINE, 

9020 'events': [fake.FPOLICY_EVENT_NAME] 

9021 }] 

9022 

9023 self.assertEqual(expected, result) 

9024 self.client.send_iter_request.assert_called_once_with( 

9025 'fpolicy-policy-get-iter', expected_args) 

9026 

9027 def test_create_fpolicy_scope(self): 

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

9029 

9030 self.client.create_fpolicy_scope( 

9031 fake.FPOLICY_POLICY_NAME, 

9032 fake.SHARE_NAME, 

9033 extensions_to_include=fake.FPOLICY_EXT_TO_INCLUDE, 

9034 extensions_to_exclude=fake.FPOLICY_EXT_TO_EXCLUDE) 

9035 

9036 expected_args = { 

9037 'policy-name': fake.FPOLICY_POLICY_NAME, 

9038 'shares-to-include': { 

9039 'string': fake.SHARE_NAME, 

9040 }, 

9041 'file-extensions-to-include': [], 

9042 'file-extensions-to-exclude': [], 

9043 } 

9044 for file_ext in fake.FPOLICY_EXT_TO_INCLUDE_LIST: 

9045 expected_args['file-extensions-to-include'].append( 

9046 {'string': file_ext}) 

9047 for file_ext in fake.FPOLICY_EXT_TO_EXCLUDE_LIST: 

9048 expected_args['file-extensions-to-exclude'].append( 

9049 {'string': file_ext}) 

9050 

9051 self.client.send_request.assert_called_once_with( 

9052 'fpolicy-policy-scope-create', expected_args) 

9053 

9054 def test_modify_fpolicy_scope(self): 

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

9056 

9057 self.client.modify_fpolicy_scope( 

9058 fake.SHARE_NAME, 

9059 fake.FPOLICY_POLICY_NAME, 

9060 shares_to_include=[fake.SHARE_NAME], 

9061 extensions_to_include=fake.FPOLICY_EXT_TO_INCLUDE, 

9062 extensions_to_exclude=fake.FPOLICY_EXT_TO_EXCLUDE) 

9063 

9064 expected_args = { 

9065 'policy-name': fake.FPOLICY_POLICY_NAME, 

9066 'file-extensions-to-include': [], 

9067 'file-extensions-to-exclude': [], 

9068 'shares-to-include': [{ 

9069 'string': fake.SHARE_NAME, 

9070 }], 

9071 } 

9072 for file_ext in fake.FPOLICY_EXT_TO_INCLUDE_LIST: 

9073 expected_args['file-extensions-to-include'].append( 

9074 {'string': file_ext}) 

9075 for file_ext in fake.FPOLICY_EXT_TO_EXCLUDE_LIST: 

9076 expected_args['file-extensions-to-exclude'].append( 

9077 {'string': file_ext}) 

9078 

9079 self.client.send_request.assert_called_once_with( 

9080 'fpolicy-policy-scope-modify', expected_args) 

9081 

9082 @ddt.data(None, netapp_api.ESCOPENOTFOUND) 

9083 def test_delete_fpolicy_scope(self, send_request_error): 

9084 if send_request_error: 

9085 send_request_mock = mock.Mock( 

9086 side_effect=self._mock_api_error(code=send_request_error)) 

9087 else: 

9088 send_request_mock = mock.Mock() 

9089 self.mock_object(self.client, 'send_request', send_request_mock) 

9090 

9091 self.client.delete_fpolicy_scope(fake.FPOLICY_POLICY_NAME) 

9092 

9093 self.client.send_request.assert_called_once_with( 

9094 'fpolicy-policy-scope-delete', 

9095 {'policy-name': fake.FPOLICY_POLICY_NAME}) 

9096 

9097 def test_delete_fpolicy_scope_error(self): 

9098 eapi_error = self._mock_api_error(code=netapp_api.EAPIERROR) 

9099 self.mock_object( 

9100 self.client, 'send_request', mock.Mock(side_effect=eapi_error)) 

9101 

9102 self.assertRaises(exception.NetAppException, 

9103 self.client.delete_fpolicy_scope, 

9104 fake.FPOLICY_POLICY_NAME) 

9105 

9106 self.client.send_request.assert_called_once_with( 

9107 'fpolicy-policy-scope-delete', 

9108 {'policy-name': fake.FPOLICY_POLICY_NAME}) 

9109 

9110 def test_get_fpolicy_scopes(self): 

9111 api_response = netapp_api.NaElement( 

9112 fake.FPOLICY_SCOPE_GET_ITER_RESPONSE) 

9113 self.mock_object(self.client, 'send_iter_request', 

9114 mock.Mock(return_value=api_response)) 

9115 

9116 result = self.client.get_fpolicy_scopes( 

9117 share_name=fake.SHARE_NAME, 

9118 policy_name=fake.FPOLICY_POLICY_NAME, 

9119 extensions_to_include=fake.FPOLICY_EXT_TO_INCLUDE, 

9120 extensions_to_exclude=fake.FPOLICY_EXT_TO_EXCLUDE, 

9121 shares_to_include=[fake.SHARE_NAME]) 

9122 

9123 expected_options = { 

9124 'policy-name': fake.FPOLICY_POLICY_NAME, 

9125 'shares-to-include': [{ 

9126 'string': fake.SHARE_NAME, 

9127 }], 

9128 'file-extensions-to-include': [], 

9129 'file-extensions-to-exclude': [], 

9130 } 

9131 for file_ext in fake.FPOLICY_EXT_TO_INCLUDE_LIST: 

9132 expected_options['file-extensions-to-include'].append( 

9133 {'string': file_ext}) 

9134 for file_ext in fake.FPOLICY_EXT_TO_EXCLUDE_LIST: 

9135 expected_options['file-extensions-to-exclude'].append( 

9136 {'string': file_ext}) 

9137 

9138 expected_args = { 

9139 'query': { 

9140 'fpolicy-scope-config': expected_options, 

9141 }, 

9142 } 

9143 expected = [{ 

9144 'policy-name': fake.FPOLICY_POLICY_NAME, 

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

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

9147 'shares-to-include': [fake.SHARE_NAME], 

9148 }] 

9149 

9150 self.assertEqual(expected, result) 

9151 self.client.send_iter_request.assert_called_once_with( 

9152 'fpolicy-policy-scope-get-iter', expected_args) 

9153 

9154 def test_enable_fpolicy_policy(self): 

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

9156 

9157 self.client.enable_fpolicy_policy( 

9158 fake.SHARE_NAME, fake.FPOLICY_POLICY_NAME, 10) 

9159 

9160 expected_args = { 

9161 'policy-name': fake.FPOLICY_POLICY_NAME, 

9162 'sequence-number': 10, 

9163 } 

9164 self.client.send_request.assert_called_once_with( 

9165 'fpolicy-enable-policy', expected_args) 

9166 

9167 @ddt.data(None, netapp_api.EPOLICYNOTFOUND) 

9168 def test_disable_fpolicy_policy(self, send_request_error): 

9169 if send_request_error: 

9170 send_request_mock = mock.Mock( 

9171 side_effect=self._mock_api_error(code=send_request_error)) 

9172 else: 

9173 send_request_mock = mock.Mock() 

9174 self.mock_object(self.client, 'send_request', send_request_mock) 

9175 

9176 self.client.disable_fpolicy_policy(fake.FPOLICY_POLICY_NAME) 

9177 

9178 expected_args = { 

9179 'policy-name': fake.FPOLICY_POLICY_NAME, 

9180 } 

9181 self.client.send_request.assert_called_once_with( 

9182 'fpolicy-disable-policy', expected_args) 

9183 

9184 def test_disable_fpolicy_policy_error(self): 

9185 eapi_error = self._mock_api_error(code=netapp_api.EAPIERROR) 

9186 self.mock_object( 

9187 self.client, 'send_request', mock.Mock(side_effect=eapi_error)) 

9188 

9189 self.assertRaises(exception.NetAppException, 

9190 self.client.disable_fpolicy_policy, 

9191 fake.FPOLICY_POLICY_NAME) 

9192 

9193 self.client.send_request.assert_called_once_with( 

9194 'fpolicy-disable-policy', 

9195 {'policy-name': fake.FPOLICY_POLICY_NAME}) 

9196 

9197 def test_get_fpolicy_status(self): 

9198 api_response = netapp_api.NaElement( 

9199 fake.FPOLICY_POLICY_STATUS_GET_ITER_RESPONSE) 

9200 self.mock_object(self.client, 'send_iter_request', 

9201 mock.Mock(return_value=api_response)) 

9202 

9203 result = self.client.get_fpolicy_policies_status( 

9204 share_name=fake.SHARE_NAME, 

9205 policy_name=fake.FPOLICY_POLICY_NAME) 

9206 

9207 expected_args = { 

9208 'query': { 

9209 'fpolicy-policy-status-info': { 

9210 'policy-name': fake.FPOLICY_POLICY_NAME, 

9211 'status': 'true' 

9212 }, 

9213 }, 

9214 } 

9215 expected = [{ 

9216 'policy-name': fake.FPOLICY_POLICY_NAME, 

9217 'status': True, 

9218 'sequence-number': '1' 

9219 }] 

9220 

9221 self.assertEqual(expected, result) 

9222 self.client.send_iter_request.assert_called_once_with( 

9223 'fpolicy-policy-status-get-iter', expected_args) 

9224 

9225 def test_is_svm_migrate_supported(self): 

9226 self.client.features.add_feature('SVM_MIGRATE') 

9227 

9228 result = self.client.is_svm_migrate_supported() 

9229 

9230 self.assertTrue(result) 

9231 

9232 @ddt.data( 

9233 {"body": fake.FAKE_HTTP_BODY, 

9234 "headers": fake.FAKE_HTTP_HEADER, 

9235 "query": {}, 

9236 "url_params": fake.FAKE_URL_PARAMS 

9237 }, 

9238 {"body": {}, 

9239 "headers": fake.FAKE_HTTP_HEADER, 

9240 "query": fake.FAKE_HTTP_QUERY, 

9241 "url_params": fake.FAKE_URL_PARAMS 

9242 }, 

9243 ) 

9244 @ddt.unpack 

9245 def test__format_request(self, body, headers, query, url_params): 

9246 expected_result = { 

9247 "body": body, 

9248 "headers": headers, 

9249 "query": query, 

9250 "url_params": url_params 

9251 } 

9252 

9253 result = self.client._format_request( 

9254 body, headers=headers, query=query, url_params=url_params) 

9255 

9256 for k, v in expected_result.items(): 

9257 self.assertIn(k, result) 

9258 self.assertEqual(result.get(k), v) 

9259 

9260 @ddt.data( 

9261 {"dest_ipspace": None, "check_only": True}, 

9262 {"dest_ipspace": "fake_dest_ipspace", "check_only": False}, 

9263 ) 

9264 @ddt.unpack 

9265 def test_svm_migration_start(self, dest_ipspace, check_only): 

9266 api_args = { 

9267 "auto_cutover": False, 

9268 "auto_source_cleanup": True, 

9269 "check_only": check_only, 

9270 "source": { 

9271 "cluster": {"name": fake.CLUSTER_NAME}, 

9272 "svm": {"name": fake.VSERVER_NAME}, 

9273 }, 

9274 "destination": { 

9275 "volume_placement": { 

9276 "aggregates": [fake.SHARE_AGGREGATE_NAME], 

9277 }, 

9278 }, 

9279 } 

9280 if dest_ipspace: 

9281 ipspace_data = { 

9282 "ipspace": {"name": dest_ipspace} 

9283 } 

9284 api_args['destination'].update(ipspace_data) 

9285 

9286 self.mock_object(self.client, '_format_request', 

9287 mock.Mock(return_value=api_args)) 

9288 self.mock_object( 

9289 self.client, 'send_request', 

9290 mock.Mock(return_value=fake.FAKE_MIGRATION_RESPONSE_WITH_JOB)) 

9291 

9292 result = self.client.svm_migration_start( 

9293 fake.CLUSTER_NAME, fake.VSERVER_NAME, [fake.SHARE_AGGREGATE_NAME], 

9294 dest_ipspace=dest_ipspace, check_only=check_only) 

9295 

9296 self.client._format_request.assert_called_once_with(api_args) 

9297 self.client.send_request.assert_called_once_with( 

9298 'svm-migration-start', api_args=api_args, use_zapi=False) 

9299 

9300 self.assertEqual(result, fake.FAKE_MIGRATION_RESPONSE_WITH_JOB) 

9301 

9302 @ddt.data({"check_only": False}, {"check_only": True}) 

9303 def test_share_server_migration_start_failed(self, check_only): 

9304 api_args = {} 

9305 

9306 self.mock_object(self.client, '_format_request', 

9307 mock.Mock(return_value=api_args)) 

9308 self.mock_object( 

9309 self.client, 'send_request', 

9310 mock.Mock(side_effect=netapp_api.NaApiError(message='fake'))) 

9311 

9312 self.assertRaises( 

9313 netapp_api.NaApiError, 

9314 self.client.svm_migration_start, 

9315 fake.CLUSTER_NAME, fake.VSERVER_NAME, 

9316 [fake.SHARE_AGGREGATE_NAME], 

9317 check_only=check_only 

9318 ) 

9319 

9320 def test_svm_migrate_complete(self): 

9321 migration_id = 'ongoing_migration_id' 

9322 request = { 

9323 'action': 'cutover' 

9324 } 

9325 expected_url_params = { 

9326 'svm_migration_id': migration_id 

9327 } 

9328 

9329 self.mock_object(self.client, '_format_request', 

9330 mock.Mock(return_value=request)) 

9331 self.mock_object( 

9332 self.client, 'send_request', 

9333 mock.Mock(return_value=fake.FAKE_MIGRATION_RESPONSE_WITH_JOB)) 

9334 

9335 self.client.svm_migrate_complete(migration_id) 

9336 

9337 self.client._format_request.assert_called_once_with( 

9338 request, url_params=expected_url_params) 

9339 self.client.send_request.assert_called_once_with( 

9340 'svm-migration-complete', api_args=request, use_zapi=False) 

9341 

9342 def test_get_job(self): 

9343 request = {} 

9344 job_uuid = 'fake_job_uuid' 

9345 url_params = { 

9346 'job_uuid': job_uuid 

9347 } 

9348 

9349 self.mock_object(self.client, '_format_request', 

9350 mock.Mock(return_value=request)) 

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

9352 mock.Mock(return_value=fake.FAKE_JOB_SUCCESS_STATE)) 

9353 

9354 result = self.client.get_job(job_uuid) 

9355 

9356 self.assertEqual(fake.FAKE_JOB_SUCCESS_STATE, result) 

9357 self.client._format_request.assert_called_once_with( 

9358 request, url_params=url_params) 

9359 self.client.send_request.assert_called_once_with( 

9360 'get-job', api_args=request, use_zapi=False) 

9361 

9362 def test_svm_migrate_cancel(self): 

9363 request = {} 

9364 migration_id = 'fake_migration_uuid' 

9365 url_params = { 

9366 "svm_migration_id": migration_id 

9367 } 

9368 

9369 self.mock_object(self.client, '_format_request', 

9370 mock.Mock(return_value=request)) 

9371 self.mock_object( 

9372 self.client, 'send_request', 

9373 mock.Mock(return_value=fake.FAKE_MIGRATION_RESPONSE_WITH_JOB)) 

9374 

9375 result = self.client.svm_migrate_cancel(migration_id) 

9376 

9377 self.assertEqual(fake.FAKE_MIGRATION_RESPONSE_WITH_JOB, result) 

9378 self.client._format_request.assert_called_once_with( 

9379 request, url_params=url_params) 

9380 self.client.send_request.assert_called_once_with( 

9381 'svm-migration-cancel', api_args=request, use_zapi=False) 

9382 

9383 def test_svm_migration_get(self): 

9384 request = {} 

9385 migration_id = 'fake_migration_uuid' 

9386 url_params = { 

9387 "svm_migration_id": migration_id 

9388 } 

9389 

9390 self.mock_object(self.client, '_format_request', 

9391 mock.Mock(return_value=request)) 

9392 self.mock_object( 

9393 self.client, 'send_request', 

9394 mock.Mock(return_value=fake.FAKE_MIGRATION_JOB_SUCCESS)) 

9395 

9396 result = self.client.svm_migration_get(migration_id) 

9397 

9398 self.assertEqual(fake.FAKE_MIGRATION_JOB_SUCCESS, result) 

9399 self.client._format_request.assert_called_once_with( 

9400 request, url_params=url_params) 

9401 self.client.send_request.assert_called_once_with( 

9402 'svm-migration-get', api_args=request, use_zapi=False) 

9403 

9404 def test_svm_migrate_pause(self): 

9405 request = { 

9406 "action": "pause" 

9407 } 

9408 migration_id = 'fake_migration_uuid' 

9409 url_params = { 

9410 "svm_migration_id": migration_id 

9411 } 

9412 

9413 self.mock_object(self.client, '_format_request', 

9414 mock.Mock(return_value=request)) 

9415 self.mock_object( 

9416 self.client, 'send_request', 

9417 mock.Mock(return_value=fake.FAKE_MIGRATION_RESPONSE_WITH_JOB)) 

9418 

9419 result = self.client.svm_migrate_pause(migration_id) 

9420 

9421 self.assertEqual(fake.FAKE_MIGRATION_RESPONSE_WITH_JOB, result) 

9422 self.client._format_request.assert_called_once_with( 

9423 request, url_params=url_params) 

9424 self.client.send_request.assert_called_once_with( 

9425 'svm-migration-pause', api_args=request, use_zapi=False) 

9426 

9427 def test_migration_check_job_state(self): 

9428 self.mock_object(self.client, 'get_job', 

9429 mock.Mock(return_value=fake.FAKE_JOB_SUCCESS_STATE)) 

9430 

9431 result = self.client.get_migration_check_job_state( 

9432 fake.FAKE_JOB_ID 

9433 ) 

9434 

9435 self.assertEqual(result, fake.FAKE_JOB_SUCCESS_STATE) 

9436 self.client.get_job.assert_called_once_with(fake.FAKE_JOB_ID) 

9437 

9438 @ddt.data(netapp_api.ENFS_V4_0_ENABLED_MIGRATION_FAILURE, 

9439 netapp_api.EVSERVER_MIGRATION_TO_NON_AFF_CLUSTER) 

9440 def test_migration_check_job_state_failed(self, error_code): 

9441 

9442 self.mock_object( 

9443 self.client, 'get_job', 

9444 mock.Mock(side_effect=netapp_api.NaApiError(code=error_code))) 

9445 

9446 self.assertRaises( 

9447 exception.NetAppException, 

9448 self.client.get_migration_check_job_state, 

9449 fake.FAKE_JOB_ID 

9450 ) 

9451 self.client.get_job.assert_called_once_with(fake.FAKE_JOB_ID) 

9452 

9453 @ddt.data(True, False) 

9454 def test_get_volume_state(self, has_record): 

9455 

9456 api_response = netapp_api.NaElement( 

9457 fake.VOLUME_GET_ITER_STATE_RESPONSE) 

9458 mock_send_iter_request = self.mock_object( 

9459 self.client, 'send_iter_request', 

9460 mock.Mock(return_value=api_response)) 

9461 mock_has_record = self.mock_object(self.client, 

9462 '_has_records', 

9463 mock.Mock(return_value=has_record)) 

9464 

9465 state = self.client.get_volume_state(fake.SHARE_NAME) 

9466 

9467 volume_get_iter_args = { 

9468 'query': { 

9469 'volume-attributes': { 

9470 'volume-id-attributes': { 

9471 'name': fake.SHARE_NAME, 

9472 }, 

9473 }, 

9474 }, 

9475 'desired-attributes': { 

9476 'volume-attributes': { 

9477 'volume-state-attributes': { 

9478 'state': None 

9479 } 

9480 } 

9481 }, 

9482 } 

9483 mock_send_iter_request.assert_called_once_with( 

9484 'volume-get-iter', volume_get_iter_args) 

9485 mock_has_record.assert_called_once_with(api_response) 

9486 if has_record: 

9487 self.assertEqual('online', state) 

9488 else: 

9489 self.assertEqual('', state) 

9490 

9491 @ddt.data(True, False) 

9492 def test_is_flexgroup_volume(self, is_flexgroup): 

9493 

9494 self.client.features.add_feature('FLEXGROUP', supported=True) 

9495 api_response = netapp_api.NaElement( 

9496 fake.VOLUME_GET_ITER_STYLE_FLEXGROUP_RESPONSE 

9497 if is_flexgroup else fake.VOLUME_GET_ITER_STYLE_FLEXVOL_RESPONSE) 

9498 mock_send_iter_request = self.mock_object( 

9499 self.client, 'send_request', 

9500 mock.Mock(return_value=api_response)) 

9501 mock_has_record = self.mock_object(self.client, 

9502 '_has_records', 

9503 mock.Mock(return_value=True)) 

9504 mock_is_style_extended_flexgroup = self.mock_object( 

9505 na_utils, 'is_style_extended_flexgroup', 

9506 mock.Mock(return_value=is_flexgroup)) 

9507 

9508 is_flexgroup_res = self.client.is_flexgroup_volume(fake.SHARE_NAME) 

9509 

9510 volume_get_iter_args = { 

9511 'query': { 

9512 'volume-attributes': { 

9513 'volume-id-attributes': { 

9514 'name': fake.SHARE_NAME, 

9515 }, 

9516 }, 

9517 }, 

9518 'desired-attributes': { 

9519 'volume-attributes': { 

9520 'volume-id-attributes': { 

9521 'style-extended': None, 

9522 }, 

9523 }, 

9524 }, 

9525 } 

9526 mock_send_iter_request.assert_called_once_with( 

9527 'volume-get-iter', volume_get_iter_args) 

9528 mock_has_record.assert_called_once_with(api_response) 

9529 mock_is_style_extended_flexgroup.assert_called_once_with( 

9530 fake.FLEXGROUP_STYLE_EXTENDED 

9531 if is_flexgroup else fake.FLEXVOL_STYLE_EXTENDED) 

9532 self.assertEqual(is_flexgroup, is_flexgroup_res) 

9533 

9534 def test_is_flexgroup_volume_not_found(self): 

9535 

9536 self.client.features.add_feature('FLEXGROUP', supported=True) 

9537 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

9538 self.mock_object(self.client, 

9539 'send_request', 

9540 mock.Mock(return_value=api_response)) 

9541 

9542 self.assertRaises(exception.StorageResourceNotFound, 

9543 self.client.is_flexgroup_volume, 

9544 fake.SHARE_NAME) 

9545 

9546 def test_is_flexgroup_volume_not_unique(self): 

9547 

9548 self.client.features.add_feature('FLEXGROUP', supported=True) 

9549 api_response = netapp_api.NaElement( 

9550 fake.VOLUME_GET_ITER_NOT_UNIQUE_RESPONSE) 

9551 self.mock_object(self.client, 

9552 'send_request', 

9553 mock.Mock(return_value=api_response)) 

9554 

9555 self.assertRaises(exception.NetAppException, 

9556 self.client.is_flexgroup_volume, 

9557 fake.SHARE_NAME) 

9558 

9559 def test_is_flexgroup_volume_unsupported(self): 

9560 

9561 self.client.features.add_feature('FLEXGROUP', supported=False) 

9562 

9563 result = self.client.is_flexgroup_volume(fake.SHARE_NAME) 

9564 

9565 self.assertFalse(result) 

9566 

9567 def test_is_flexgroup_supported(self): 

9568 self.client.features.add_feature('FLEXGROUP') 

9569 

9570 result = self.client.is_flexgroup_supported() 

9571 

9572 self.assertTrue(result) 

9573 

9574 def test_is_flexgroup_fan_out_supported(self): 

9575 self.client.features.add_feature('FLEXGROUP_FAN_OUT') 

9576 

9577 result = self.client.is_flexgroup_fan_out_supported() 

9578 

9579 self.assertTrue(result) 

9580 

9581 def test_get_job_state(self): 

9582 

9583 api_response = netapp_api.NaElement(fake.JOB_GET_STATE_RESPONSE) 

9584 mock_send_iter_request = self.mock_object( 

9585 self.client, 'send_iter_request', 

9586 mock.Mock(return_value=api_response)) 

9587 mock_has_record = self.mock_object(self.client, 

9588 '_has_records', 

9589 mock.Mock(return_value=True)) 

9590 

9591 job_state_res = self.client.get_job_state(fake.JOB_ID) 

9592 

9593 job_get_iter_args = { 

9594 'query': { 

9595 'job-info': { 

9596 'job-id': fake.JOB_ID, 

9597 }, 

9598 }, 

9599 'desired-attributes': { 

9600 'job-info': { 

9601 'job-state': None, 

9602 }, 

9603 }, 

9604 } 

9605 mock_send_iter_request.assert_called_once_with( 

9606 'job-get-iter', job_get_iter_args, enable_tunneling=False) 

9607 mock_has_record.assert_called_once_with(api_response) 

9608 self.assertEqual(fake.JOB_STATE, job_state_res) 

9609 

9610 def test_get_job_state_not_found(self): 

9611 

9612 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE) 

9613 self.mock_object(self.client, 

9614 '_has_records', 

9615 mock.Mock(return_value=False)) 

9616 self.mock_object(self.client, 

9617 'send_iter_request', 

9618 mock.Mock(return_value=api_response)) 

9619 

9620 self.assertRaises(exception.NetAppException, 

9621 self.client.get_job_state, 

9622 fake.JOB_ID) 

9623 

9624 def test_get_job_state_not_unique(self): 

9625 

9626 api_response = netapp_api.NaElement( 

9627 fake.JOB_GET_STATE_NOT_UNIQUE_RESPONSE) 

9628 self.mock_object(self.client, 

9629 '_has_records', 

9630 mock.Mock(return_value=True)) 

9631 self.mock_object(self.client, 

9632 'send_iter_request', 

9633 mock.Mock(return_value=api_response)) 

9634 

9635 self.assertRaises(exception.NetAppException, 

9636 self.client.get_job_state, 

9637 fake.JOB_ID) 

9638 

9639 def test_check_snaprestore_license_svm_scoped_notfound(self): 

9640 self.mock_object(self.client, 

9641 'restore_snapshot', 

9642 mock.Mock(side_effect=netapp_api.NaApiError( 

9643 code=netapp_api.EAPIERROR, 

9644 message=fake.NO_SNAPRESTORE_LICENSE))) 

9645 result = self.client.check_snaprestore_license() 

9646 self.assertIs(False, result) 

9647 

9648 def test_check_snaprestore_license_svm_scoped_found(self): 

9649 self.mock_object(self.client, 

9650 'restore_snapshot', 

9651 mock.Mock(side_effect=netapp_api.NaApiError( 

9652 code=netapp_api.EAPIERROR, 

9653 message='Other error'))) 

9654 result = self.client.check_snaprestore_license() 

9655 self.assertIs(True, result) 

9656 

9657 def test_check_snaprestore_license_svm_scoped_found_exception(self): 

9658 self.mock_object(client_cmode.LOG, 'exception') 

9659 self.mock_object(self.client, 

9660 'restore_snapshot', 

9661 mock.Mock(return_value=None)) 

9662 

9663 self.assertRaises( 

9664 exception.NetAppException, 

9665 self.client.check_snaprestore_license) 

9666 client_cmode.LOG.exception.assert_called_once() 

9667 

9668 def test_get_svm_volumes_total_size(self): 

9669 expected = 1 

9670 

9671 request = {} 

9672 

9673 api_args = { 

9674 'svm.name': fake.VSERVER_NAME, 

9675 'fields': 'size' 

9676 } 

9677 

9678 self.mock_object(self.client, '_format_request', 

9679 mock.Mock(return_value=api_args)) 

9680 

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

9682 mock.Mock(return_value=fake.FAKE_GET_VOLUME)) 

9683 

9684 result = self.client.get_svm_volumes_total_size(fake.VSERVER_NAME) 

9685 

9686 self.client._format_request.assert_called_once_with(request, 

9687 query=api_args) 

9688 self.client.send_request.assert_called_once_with( 

9689 'svm-migration-get-progress', api_args=api_args, use_zapi=False) 

9690 

9691 self.assertEqual(expected, result) 

9692 

9693 def test_configure_active_directory_credential_error(self): 

9694 msg = "could not authenticate" 

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

9696 self._mock_api_error(code=netapp_api.EAPIERROR, 

9697 message=msg)) 

9698 self.mock_object(self.client, 'configure_dns') 

9699 self.mock_object(self.client, 'configure_cifs_aes_encryption') 

9700 self.mock_object(self.client, 'set_preferred_dc') 

9701 self.mock_object(self.client, '_get_cifs_server_name') 

9702 self.assertRaises(exception.SecurityServiceFailedAuth, 

9703 self.client.configure_active_directory, 

9704 fake.CIFS_SECURITY_SERVICE, 

9705 fake.VSERVER_NAME, 

9706 False) 

9707 

9708 def test_configure_active_directory_user_privilege_error(self): 

9709 msg = "insufficient access" 

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

9711 self._mock_api_error(code=netapp_api.EAPIERROR, 

9712 message=msg)) 

9713 self.mock_object(self.client, 'configure_dns') 

9714 self.mock_object(self.client, 'configure_cifs_aes_encryption') 

9715 self.mock_object(self.client, 'set_preferred_dc') 

9716 self.mock_object(self.client, '_get_cifs_server_name') 

9717 self.assertRaises(exception.SecurityServiceFailedAuth, 

9718 self.client.configure_active_directory, 

9719 fake.CIFS_SECURITY_SERVICE, 

9720 fake.VSERVER_NAME, 

9721 False) 

9722 

9723 def test_snapmirror_restore_vol(self): 

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

9725 self.client.snapmirror_restore_vol(source_path=fake.SM_SOURCE_PATH, 

9726 dest_path=fake.SM_DEST_PATH, 

9727 source_snapshot=fake.SNAPSHOT_NAME, 

9728 ) 

9729 snapmirror_restore_args = { 

9730 'source-location': fake.SM_SOURCE_PATH, 

9731 'destination-location': fake.SM_DEST_PATH, 

9732 'source-snapshot': fake.SNAPSHOT_NAME, 

9733 

9734 } 

9735 self.client.send_request.assert_has_calls([ 

9736 mock.call('snapmirror-restore', snapmirror_restore_args)]) 

9737 

9738 @ddt.data({'snapmirror_label': None, 'newer_than': '2345'}, 

9739 {'snapmirror_label': "fake_backup", 'newer_than': None}) 

9740 @ddt.unpack 

9741 def test_list_volume_snapshots(self, snapmirror_label, newer_than): 

9742 api_response = netapp_api.NaElement( 

9743 fake.SNAPSHOT_GET_ITER_SNAPMIRROR_RESPONSE) 

9744 self.mock_object(self.client, 

9745 'send_iter_request', 

9746 mock.Mock(return_value=api_response)) 

9747 

9748 result = self.client.list_volume_snapshots( 

9749 fake.SHARE_NAME, 

9750 snapmirror_label=snapmirror_label, 

9751 newer_than=newer_than) 

9752 snapshot_get_iter_args = { 

9753 'query': { 

9754 'snapshot-info': { 

9755 'volume': fake.SHARE_NAME, 

9756 }, 

9757 }, 

9758 } 

9759 if newer_than: 

9760 snapshot_get_iter_args['query']['snapshot-info'][ 

9761 'access-time'] = '>' + newer_than 

9762 if snapmirror_label: 

9763 snapshot_get_iter_args['query']['snapshot-info'][ 

9764 'snapmirror-label'] = snapmirror_label 

9765 self.client.send_iter_request.assert_has_calls([ 

9766 mock.call('snapshot-get-iter', snapshot_get_iter_args)]) 

9767 

9768 expected = [fake.SNAPSHOT_NAME] 

9769 self.assertEqual(expected, result) 

9770 

9771 def test_is_snaplock_compliance_clock_configured(self): 

9772 api_response = netapp_api.NaElement(fake.SNAPLOCK_CLOCK_CONFIG_1) 

9773 self.mock_object(self.client, 

9774 'send_request', 

9775 mock.Mock(return_value=api_response)) 

9776 result = self.client.is_snaplock_compliance_clock_configured( 

9777 "fake_node", 

9778 ) 

9779 self.assertIs(True, result) 

9780 

9781 def test_is_snaplock_compliance_clock_configured_negative(self): 

9782 api_response = netapp_api.NaElement(fake.SNAPLOCK_CLOCK_CONFIG_2) 

9783 self.mock_object(self.client, 

9784 'send_request', 

9785 mock.Mock(return_value=api_response)) 

9786 result = self.client.is_snaplock_compliance_clock_configured( 

9787 "fake_node" 

9788 ) 

9789 self.assertIs(False, result) 

9790 

9791 def test_is_snaplock_compliance_clock_configured_none(self): 

9792 api_response = netapp_api.NaElement(fake.SNAPLOCK_CLOCK_CONFIG_1) 

9793 self.mock_object(self.client, 

9794 'send_request', 

9795 mock.Mock(return_value=api_response)) 

9796 self.mock_object(api_response, 

9797 'get_child_by_name', 

9798 mock.Mock(return_value=None)) 

9799 self.assertRaises( 

9800 exception.NetAppException, 

9801 self.client.is_snaplock_compliance_clock_configured, 

9802 "node1" 

9803 ) 

9804 

9805 @ddt.data({'options': {'snaplock_autocommit_period': "4hours", 

9806 'snaplock_min_retention_period': "6days", 

9807 'snaplock_max_retention_period': "8months", 

9808 'snaplock_default_retention_period': "8days"}, 

9809 }, 

9810 {'options': {'snaplock_autocommit_period': "4hours", 

9811 'snaplock_min_retention_period': "6days", 

9812 'snaplock_max_retention_period': "8months", 

9813 'snaplock_default_retention_period': "min"}, 

9814 }, 

9815 {'options': {'snaplock_autocommit_period': "4hours", 

9816 'snaplock_min_retention_period': "6days", 

9817 'snaplock_max_retention_period': "8months", 

9818 'snaplock_default_retention_period': "max"}, 

9819 }, 

9820 ) 

9821 @ddt.unpack 

9822 def test_set_snaplock_attributes(self, options): 

9823 api_args = { 

9824 'volume': fake.SHARE_NAME, 

9825 'autocommit-period': options.get('snaplock_autocommit_period'), 

9826 'minimum-retention-period': options.get( 

9827 'snaplock_min_retention_period'), 

9828 'maximum-retention-period': options.get( 

9829 'snaplock_max_retention_period'), 

9830 'default-retention-period': options.get( 

9831 'snaplock_default_retention_period'), 

9832 } 

9833 if options.get('snaplock_default_retention_period') == "min": 

9834 api_args['default-retention-period'] = options.get( 

9835 'snaplock_min_retention_period') 

9836 elif options.get('snaplock_default_retention_period') == 'max': 

9837 api_args['default-retention-period'] = options.get( 

9838 'snaplock_max_retention_period') 

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

9840 self.client.set_snaplock_attributes(fake.SHARE_NAME, **options) 

9841 self.client.send_request.assert_has_calls([ 

9842 mock.call('volume-set-snaplock-attrs', api_args)]) 

9843 

9844 def test_set_snaplock_attributes_all_none(self): 

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

9846 options = {'snaplock_autocommit_period': None, 

9847 'snaplock_min_retention_period': None, 

9848 'snaplock_max_retention_period': None, 

9849 'snaplock_default_retention_period': None, 

9850 } 

9851 self.client.set_snaplock_attributes(fake.SHARE_NAME, **options) 

9852 self.client.send_request.assert_not_called() 

9853 

9854 def test_get_vserver_aggr_snaplock_type(self): 

9855 self.client.features.SNAPLOCK = True 

9856 api_response = netapp_api.NaElement( 

9857 fake.VSERVER_SHOW_AGGR_GET_RESPONSE, 

9858 ) 

9859 self.mock_object(self.client, 

9860 'send_iter_request', 

9861 mock.Mock(return_value=api_response)) 

9862 result = self.client.get_vserver_aggr_snaplock_type( 

9863 fake.SHARE_AGGREGATE_NAMES 

9864 ) 

9865 self.assertEqual("compliance", result) 

9866 

9867 def test_get_vserver_aggr_snaplock_type_negative(self): 

9868 self.client.features.SNAPLOCK = False 

9869 api_response = netapp_api.NaElement( 

9870 fake.VSERVER_SHOW_AGGR_GET_RESPONSE, 

9871 ) 

9872 self.mock_object(self.client, 

9873 'send_iter_request', 

9874 mock.Mock(return_value=api_response)) 

9875 result = self.client.get_vserver_aggr_snaplock_type( 

9876 fake.SHARE_AGGREGATE_NAMES 

9877 ) 

9878 self.assertIsNone(result) 

9879 

9880 @ddt.data("compliance", "enterprise") 

9881 def test__is_snaplock_enabled_volume_true(self, snaplock_type): 

9882 vol_attr = {'snaplock-type': snaplock_type} 

9883 self.mock_object(self.client, 

9884 'get_volume', 

9885 mock.Mock(return_value=vol_attr)) 

9886 result = self.client._is_snaplock_enabled_volume( 

9887 fake.SHARE_AGGREGATE_NAMES 

9888 ) 

9889 self.assertIs(True, result) 

9890 

9891 def test__is_snaplock_enabled_volume_false(self): 

9892 vol_attr = {'snaplock-type': 'non-snaplock'} 

9893 self.mock_object(self.client, 

9894 'get_volume', 

9895 mock.Mock(return_value=vol_attr)) 

9896 result = self.client._is_snaplock_enabled_volume( 

9897 fake.SHARE_AGGREGATE_NAMES 

9898 ) 

9899 self.assertIs(False, result) 

9900 

9901 def test_get_storage_failover_partner(self): 

9902 api_response = netapp_api.NaElement(fake.STORAGE_FAIL_OVER_PARTNER) 

9903 self.mock_object(self.client, 

9904 'send_request', 

9905 mock.Mock(return_value=api_response)) 

9906 

9907 result = self.client.get_storage_failover_partner("fake_node") 

9908 self.assertEqual("fake_partner_node", result) 

9909 

9910 def test_get_migratable_data_lif_for_node(self): 

9911 api_response = netapp_api.NaElement( 

9912 fake.NET_INTERFACE_GET_ITER_RESPONSE) 

9913 self.mock_object(self.client, 

9914 'send_iter_request', 

9915 mock.Mock(return_value=api_response)) 

9916 failover_policy = ['system-defined', 'sfo-partner-only'] 

9917 protocols = ['nfs', 'cifs'] 

9918 api_args = { 

9919 'query': { 

9920 'net-interface-info': { 

9921 'failover-policy': '|'.join(failover_policy), 

9922 'home-node': "fake_node", 

9923 'data-protocols': { 

9924 'data-protocol': '|'.join(protocols), 

9925 } 

9926 } 

9927 } 

9928 } 

9929 result = self.client.get_migratable_data_lif_for_node("fake_node") 

9930 self.client.send_iter_request.assert_has_calls([ 

9931 mock.call('net-interface-get-iter', api_args)]) 

9932 self.assertEqual(list(fake.LIF_NAMES), result) 

9933 

9934 def test_get_data_lif_details_for_nodes(self): 

9935 api_response = netapp_api.NaElement( 

9936 fake.DATA_LIF_CAPACITY_DETAILS) 

9937 self.mock_object(self.client, 

9938 'send_iter_request', 

9939 mock.Mock(return_value=api_response)) 

9940 api_args = { 

9941 'desired-attributes': { 

9942 'data-lif-capacity-details-info': { 

9943 'limit-for-node': None, 

9944 'count-for-node': None, 

9945 'node': None 

9946 }, 

9947 }, 

9948 } 

9949 expected_result = [{'limit-for-node': '512', 

9950 'count-for-node': '44', 

9951 'node': 'fake_node', 

9952 }] 

9953 result = self.client.get_data_lif_details_for_nodes() 

9954 self.client.send_iter_request.assert_has_calls([ 

9955 mock.call('data-lif-capacity-details', api_args)]) 

9956 self.assertEqual(expected_result, result)