Coverage for manila/tests/share/drivers/tegile/test_tegile.py: 100%

262 statements  

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

1# Copyright (c) 2016 by Tegile Systems, Inc. 

2# All Rights Reserved. 

3# 

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

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

6# a copy of the License at 

7# 

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

9# 

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

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

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

13# License for the specific language governing permissions and limitations 

14# under the License. 

15""" 

16Share driver Test for Tegile storage. 

17""" 

18 

19from unittest import mock 

20 

21import ddt 

22from oslo_config import cfg 

23import requests 

24 

25from manila.common import constants as const 

26from manila import context 

27from manila import exception 

28from manila.share import configuration 

29from manila.share.drivers.tegile import tegile 

30from manila import test 

31 

32 

33CONF = cfg.CONF 

34 

35test_config = configuration.Configuration(None) 

36test_config.tegile_nas_server = 'some-ip' 

37test_config.tegile_nas_login = 'some-user' 

38test_config.tegile_nas_password = 'some-password' 

39test_config.reserved_share_percentage = 10 

40test_config.reserved_share_from_snapshot_percentage = 5 

41test_config.reserved_share_extend_percentage = 5 

42test_config.max_over_subscription_ratio = 30.0 

43 

44test_share = { 

45 'host': 'node#fake_pool', 

46 'name': 'testshare', 

47 'id': 'a24c2ee8-525a-4406-8ccd-8d38688f8e9e', 

48 'share_proto': 'NFS', 

49 'size': 10, 

50} 

51 

52test_share_cifs = { 

53 'host': 'node#fake_pool', 

54 'name': 'testshare', 

55 'id': 'a24c2ee8-525a-4406-8ccd-8d38688f8e9e', 

56 'share_proto': 'CIFS', 

57 'size': 10, 

58} 

59 

60test_share_fail = { 

61 'host': 'node#fake_pool', 

62 'name': 'testshare', 

63 'id': 'a24c2ee8-525a-4406-8ccd-8d38688f8e9e', 

64 'share_proto': 'OTHER', 

65 'size': 10, 

66} 

67 

68test_snapshot = { 

69 'name': 'testSnap', 

70 'id': '07ae9978-5445-405e-8881-28f2adfee732', 

71 'share': test_share, 

72 'share_name': 'snapshotted', 

73 'display_name': 'disp', 

74 'display_description': 'disp-desc', 

75} 

76 

77array_stats = { 

78 'total_capacity_gb': 4569.199686084874, 

79 'free_capacity_gb': 4565.381390112452, 

80 'pools': [ 

81 { 

82 'total_capacity_gb': 913.5, 

83 'QoS_support': False, 

84 'free_capacity_gb': 911.812650680542, 

85 'reserved_percentage': 0, 

86 'reserved_snapshot_percentage': 0, 

87 'reserved_share_extend_percentage': 0, 

88 'pool_name': 'pyramid', 

89 }, 

90 { 

91 'total_capacity_gb': 2742.1996604874, 

92 'QoS_support': False, 

93 'free_capacity_gb': 2740.148867149747, 

94 'reserved_percentage': 0, 

95 'reserved_snapshot_percentage': 0, 

96 'reserved_share_extend_percentage': 0, 

97 'pool_name': 'cobalt', 

98 }, 

99 { 

100 'total_capacity_gb': 913.5, 

101 'QoS_support': False, 

102 'free_capacity_gb': 913.4198722839355, 

103 'reserved_percentage': 0, 

104 'reserved_snapshot_percentage': 0, 

105 'reserved_share_extend_percentage': 0, 

106 'pool_name': 'test', 

107 }, 

108 ], 

109} 

110 

111 

112fake_tegile_backend_fail = mock.Mock( 

113 side_effect=exception.TegileAPIException(response="Fake Exception")) 

114 

115 

116class FakeResponse(object): 

117 def __init__(self, status, json_output): 

118 self.status_code = status 

119 self.text = 'Random text' 

120 self._json = json_output 

121 

122 def json(self): 

123 return self._json 

124 

125 def close(self): 

126 pass 

127 

128 

129@ddt.ddt 

130class TegileShareDriverTestCase(test.TestCase): 

131 def __init__(self, *args, **kwds): 

132 super(TegileShareDriverTestCase, self).__init__(*args, **kwds) 

133 self._ctxt = context.get_admin_context() 

134 self.configuration = test_config 

135 

136 def setUp(self): 

137 CONF.set_default('driver_handles_share_servers', False) 

138 self._driver = tegile.TegileShareDriver( 

139 configuration=self.configuration) 

140 self._driver._default_project = 'fake_project' 

141 super(TegileShareDriverTestCase, self).setUp() 

142 

143 def test_create_share(self): 

144 api_return_value = (test_config.tegile_nas_server + 

145 " " + test_share['name']) 

146 mock_api = self.mock_object(self._driver, '_api', 

147 mock.Mock( 

148 return_value=api_return_value)) 

149 

150 result = self._driver.create_share(self._ctxt, test_share) 

151 

152 expected = { 

153 'is_admin_only': False, 

154 'metadata': { 

155 'preferred': True, 

156 }, 

157 'path': 'some-ip:testshare', 

158 } 

159 self.assertEqual(expected, result) 

160 

161 create_params = ( 

162 'fake_pool', 

163 'fake_project', 

164 test_share['name'], 

165 test_share['share_proto'], 

166 ) 

167 mock_api.assert_called_once_with('createShare', create_params) 

168 

169 def test_create_share_fail(self): 

170 mock_api = self.mock_object(self._driver, '_api', 

171 mock.Mock( 

172 side_effect=( 

173 exception.TegileAPIException( 

174 response="Fake Exception")))) 

175 

176 self.assertRaises(exception.TegileAPIException, 

177 self._driver.create_share, 

178 self._ctxt, 

179 test_share) 

180 

181 create_params = ( 

182 'fake_pool', 

183 'fake_project', 

184 test_share['name'], 

185 test_share['share_proto'], 

186 ) 

187 mock_api.assert_called_once_with('createShare', create_params) 

188 

189 def test_delete_share(self): 

190 fake_share_info = ('fake_pool', 'fake_project', test_share['name']) 

191 mock_params = self.mock_object(self._driver, 

192 '_get_pool_project_share_name', 

193 mock.Mock(return_value=fake_share_info)) 

194 mock_api = self.mock_object(self._driver, '_api') 

195 

196 self._driver.delete_share(self._ctxt, test_share) 

197 

198 delete_path = '%s/%s/%s/%s' % ( 

199 'fake_pool', 'Local', 'fake_project', test_share['name']) 

200 delete_params = (delete_path, True, False) 

201 mock_api.assert_called_once_with('deleteShare', delete_params) 

202 mock_params.assert_called_once_with(test_share) 

203 

204 def test_delete_share_fail(self): 

205 mock_api = self.mock_object(self._driver, '_api', 

206 mock.Mock( 

207 side_effect=( 

208 exception.TegileAPIException( 

209 response="Fake Exception")))) 

210 

211 self.assertRaises(exception.TegileAPIException, 

212 self._driver.delete_share, 

213 self._ctxt, 

214 test_share) 

215 

216 delete_path = '%s/%s/%s/%s' % ( 

217 'fake_pool', 'Local', 'fake_project', test_share['name']) 

218 delete_params = (delete_path, True, False) 

219 mock_api.assert_called_once_with('deleteShare', delete_params) 

220 

221 def test_create_snapshot(self): 

222 mock_api = self.mock_object(self._driver, '_api') 

223 fake_share_info = ('fake_pool', 'fake_project', test_share['name']) 

224 mock_params = self.mock_object(self._driver, 

225 '_get_pool_project_share_name', 

226 mock.Mock(return_value=fake_share_info)) 

227 

228 self._driver.create_snapshot(self._ctxt, test_snapshot) 

229 

230 share = { 

231 'poolName': 'fake_pool', 

232 'projectName': 'fake_project', 

233 'name': test_share['name'], 

234 'availableSize': 0, 

235 'totalSize': 0, 

236 'datasetPath': '%s/%s/%s' % ( 

237 'fake_pool', 

238 'Local', 

239 'fake_project', 

240 ), 

241 'mountpoint': test_share['name'], 

242 'local': 'true', 

243 } 

244 create_params = (share, test_snapshot['name'], False) 

245 mock_api.assert_called_once_with('createShareSnapshot', create_params) 

246 mock_params.assert_called_once_with(test_share) 

247 

248 def test_create_snapshot_fail(self): 

249 mock_api = self.mock_object(self._driver, '_api', 

250 mock.Mock( 

251 side_effect=( 

252 exception.TegileAPIException( 

253 response="Fake Exception")))) 

254 

255 self.assertRaises(exception.TegileAPIException, 

256 self._driver.create_snapshot, 

257 self._ctxt, 

258 test_snapshot) 

259 

260 share = { 

261 'poolName': 'fake_pool', 

262 'projectName': 'fake_project', 

263 'name': test_share['name'], 

264 'availableSize': 0, 

265 'totalSize': 0, 

266 'datasetPath': '%s/%s/%s' % ( 

267 'fake_pool', 

268 'Local', 

269 'fake_project', 

270 ), 

271 'mountpoint': test_share['name'], 

272 'local': 'true', 

273 } 

274 create_params = (share, test_snapshot['name'], False) 

275 mock_api.assert_called_once_with('createShareSnapshot', create_params) 

276 

277 def test_delete_snapshot(self): 

278 fake_share_info = ('fake_pool', 'fake_project', test_share['name']) 

279 mock_params = self.mock_object(self._driver, 

280 '_get_pool_project_share_name', 

281 mock.Mock(return_value=fake_share_info)) 

282 mock_api = self.mock_object(self._driver, '_api') 

283 

284 self._driver.delete_snapshot(self._ctxt, test_snapshot) 

285 

286 delete_snap_path = ('%s/%s/%s/%s@%s%s' % ( 

287 'fake_pool', 

288 'Local', 

289 'fake_project', 

290 test_share['name'], 

291 'Manual-S-', 

292 test_snapshot['name'], 

293 )) 

294 

295 delete_params = (delete_snap_path, False) 

296 mock_api.assert_called_once_with('deleteShareSnapshot', delete_params) 

297 mock_params.assert_called_once_with(test_share) 

298 

299 def test_delete_snapshot_fail(self): 

300 mock_api = self.mock_object(self._driver, '_api', 

301 mock.Mock( 

302 side_effect=( 

303 exception.TegileAPIException( 

304 response="Fake Exception")))) 

305 

306 self.assertRaises(exception.TegileAPIException, 

307 self._driver.delete_snapshot, 

308 self._ctxt, 

309 test_snapshot) 

310 

311 delete_snap_path = ('%s/%s/%s/%s@%s%s' % ( 

312 'fake_pool', 

313 'Local', 

314 'fake_project', 

315 test_share['name'], 

316 'Manual-S-', 

317 test_snapshot['name'], 

318 )) 

319 delete_params = (delete_snap_path, False) 

320 mock_api.assert_called_once_with('deleteShareSnapshot', delete_params) 

321 

322 def test_create_share_from_snapshot(self): 

323 api_return_value = (test_config.tegile_nas_server + 

324 " " + test_share['name']) 

325 mock_api = self.mock_object(self._driver, '_api', 

326 mock.Mock( 

327 return_value=api_return_value)) 

328 fake_share_info = ('fake_pool', 'fake_project', test_share['name']) 

329 mock_params = self.mock_object(self._driver, 

330 '_get_pool_project_share_name', 

331 mock.Mock(return_value=fake_share_info)) 

332 

333 result = self._driver.create_share_from_snapshot(self._ctxt, 

334 test_share, 

335 test_snapshot) 

336 

337 expected = { 

338 'is_admin_only': False, 

339 'metadata': { 

340 'preferred': True, 

341 }, 

342 'path': 'some-ip:testshare', 

343 } 

344 self.assertEqual(expected, result) 

345 

346 create_params = ( 

347 '%s/%s/%s/%s@%s%s' % ( 

348 'fake_pool', 

349 'Local', 

350 'fake_project', 

351 test_snapshot['share_name'], 

352 'Manual-S-', 

353 test_snapshot['name'], 

354 ), 

355 test_share['name'], 

356 True, 

357 ) 

358 mock_api.assert_called_once_with('cloneShareSnapshot', create_params) 

359 mock_params.assert_called_once_with(test_share) 

360 

361 def test_create_share_from_snapshot_fail(self): 

362 mock_api = self.mock_object(self._driver, '_api', 

363 mock.Mock( 

364 side_effect=( 

365 exception.TegileAPIException( 

366 response="Fake Exception")))) 

367 

368 self.assertRaises(exception.TegileAPIException, 

369 self._driver.create_share_from_snapshot, 

370 self._ctxt, 

371 test_share, 

372 test_snapshot) 

373 

374 create_params = ( 

375 '%s/%s/%s/%s@%s%s' % ( 

376 'fake_pool', 

377 'Local', 

378 'fake_project', 

379 test_snapshot['share_name'], 

380 'Manual-S-', 

381 test_snapshot['name'], 

382 ), 

383 test_share['name'], 

384 True, 

385 ) 

386 mock_api.assert_called_once_with('cloneShareSnapshot', create_params) 

387 

388 def test_ensure_share(self): 

389 api_return_value = (test_config.tegile_nas_server + 

390 " " + test_share['name']) 

391 mock_api = self.mock_object(self._driver, '_api', 

392 mock.Mock( 

393 return_value=api_return_value)) 

394 fake_share_info = ('fake_pool', 'fake_project', test_share['name']) 

395 mock_params = self.mock_object(self._driver, 

396 '_get_pool_project_share_name', 

397 mock.Mock(return_value=fake_share_info)) 

398 

399 result = self._driver.ensure_share(self._ctxt, test_share) 

400 

401 expected = [ 

402 { 

403 'is_admin_only': False, 

404 'metadata': { 

405 'preferred': 

406 True, 

407 }, 

408 'path': 'some-ip:testshare', 

409 }, 

410 ] 

411 self.assertEqual(expected, result) 

412 

413 ensure_params = [ 

414 '%s/%s/%s/%s' % ( 

415 'fake_pool', 'Local', 'fake_project', test_share['name'])] 

416 mock_api.assert_called_once_with('getShareIPAndMountPoint', 

417 ensure_params) 

418 mock_params.assert_called_once_with(test_share) 

419 

420 def test_ensure_share_fail(self): 

421 mock_api = self.mock_object(self._driver, '_api', 

422 mock.Mock( 

423 side_effect=( 

424 exception.TegileAPIException( 

425 response="Fake Exception")))) 

426 self.assertRaises(exception.TegileAPIException, 

427 self._driver.ensure_share, 

428 self._ctxt, 

429 test_share) 

430 

431 ensure_params = [ 

432 '%s/%s/%s/%s' % ( 

433 'fake_pool', 'Local', 'fake_project', test_share['name'])] 

434 mock_api.assert_called_once_with('getShareIPAndMountPoint', 

435 ensure_params) 

436 

437 def test_get_share_stats(self): 

438 mock_api = self.mock_object(self._driver, '_api', 

439 mock.Mock( 

440 return_value=array_stats)) 

441 

442 result_dict = self._driver.get_share_stats(True) 

443 

444 expected_dict = { 

445 'driver_handles_share_servers': False, 

446 'driver_version': '1.0.0', 

447 'free_capacity_gb': 4565.381390112452, 

448 'pools': [ 

449 { 

450 'allocated_capacity_gb': 0.0, 

451 'compression': True, 

452 'dedupe': True, 

453 'free_capacity_gb': 911.812650680542, 

454 'pool_name': 'pyramid', 

455 'qos': False, 

456 'reserved_percentage': 10, 

457 'reserved_snapshot_percentage': 5, 

458 'reserved_share_extend_percentage': 5, 

459 'thin_provisioning': True, 

460 'max_over_subscription_ratio': 30.0, 

461 'total_capacity_gb': 913.5}, 

462 { 

463 'allocated_capacity_gb': 0.0, 

464 'compression': True, 

465 'dedupe': True, 

466 'free_capacity_gb': 2740.148867149747, 

467 'pool_name': 'cobalt', 

468 'qos': False, 

469 'reserved_percentage': 10, 

470 'reserved_snapshot_percentage': 5, 

471 'reserved_share_extend_percentage': 5, 

472 'thin_provisioning': True, 

473 'max_over_subscription_ratio': 30.0, 

474 'total_capacity_gb': 2742.1996604874 

475 }, 

476 { 

477 'allocated_capacity_gb': 0.0, 

478 'compression': True, 

479 'dedupe': True, 

480 'free_capacity_gb': 913.4198722839355, 

481 'pool_name': 'test', 

482 'qos': False, 

483 'reserved_percentage': 10, 

484 'reserved_snapshot_percentage': 5, 

485 'reserved_share_extend_percentage': 5, 

486 'thin_provisioning': True, 

487 'max_over_subscription_ratio': 30.0, 

488 'total_capacity_gb': 913.5}, ], 

489 'qos': False, 

490 'reserved_percentage': 0, 

491 'reserved_snapshot_percentage': 0, 

492 'reserved_share_extend_percentage': 0, 

493 'replication_domain': None, 

494 'share_backend_name': 'Tegile', 

495 'snapshot_support': True, 

496 'storage_protocol': 'NFS_CIFS', 

497 'total_capacity_gb': 4569.199686084874, 

498 'vendor_name': 'Tegile Systems Inc.', 

499 } 

500 self.assertSubDictMatch(expected_dict, result_dict) 

501 

502 mock_api.assert_called_once_with(fine_logging=False, 

503 method='getArrayStats', 

504 request_type='get') 

505 

506 def test_get_share_stats_fail(self): 

507 mock_api = self.mock_object(self._driver, '_api', 

508 mock.Mock( 

509 side_effect=( 

510 exception.TegileAPIException( 

511 response="Fake Exception")))) 

512 

513 self.assertRaises(exception.TegileAPIException, 

514 self._driver.get_share_stats, 

515 True) 

516 

517 mock_api.assert_called_once_with(fine_logging=False, 

518 method='getArrayStats', 

519 request_type='get') 

520 

521 def test_get_pool(self): 

522 result = self._driver.get_pool(test_share) 

523 

524 expected = 'fake_pool' 

525 self.assertEqual(expected, result) 

526 

527 def test_extend_share(self): 

528 fake_share_info = ('fake_pool', 'fake_project', test_share['name']) 

529 mock_params = self.mock_object(self._driver, 

530 '_get_pool_project_share_name', 

531 mock.Mock(return_value=fake_share_info)) 

532 mock_api = self.mock_object(self._driver, '_api') 

533 

534 self._driver.extend_share(test_share, 12) 

535 

536 extend_path = '%s/%s/%s/%s' % ( 

537 'fake_pool', 'Local', 'fake_project', test_share['name']) 

538 extend_params = (extend_path, str(12), 'GB') 

539 mock_api.assert_called_once_with('resizeShare', extend_params) 

540 mock_params.assert_called_once_with(test_share) 

541 

542 def test_extend_share_fail(self): 

543 mock_api = self.mock_object(self._driver, '_api', 

544 mock.Mock( 

545 side_effect=( 

546 exception.TegileAPIException( 

547 response="Fake Exception")))) 

548 

549 self.assertRaises(exception.TegileAPIException, 

550 self._driver.extend_share, 

551 test_share, 30) 

552 

553 extend_path = '%s/%s/%s/%s' % ( 

554 'fake_pool', 'Local', 'fake_project', test_share['name']) 

555 extend_params = (extend_path, str(30), 'GB') 

556 mock_api.assert_called_once_with('resizeShare', extend_params) 

557 

558 def test_shrink_share(self): 

559 fake_share_info = ('fake_pool', 'fake_project', test_share['name']) 

560 mock_params = self.mock_object(self._driver, 

561 '_get_pool_project_share_name', 

562 mock.Mock(return_value=fake_share_info)) 

563 mock_api = self.mock_object(self._driver, '_api') 

564 

565 self._driver.shrink_share(test_share, 15) 

566 

567 shrink_path = '%s/%s/%s/%s' % ( 

568 'fake_pool', 'Local', 'fake_project', test_share['name']) 

569 shrink_params = (shrink_path, str(15), 'GB') 

570 mock_api.assert_called_once_with('resizeShare', shrink_params) 

571 mock_params.assert_called_once_with(test_share) 

572 

573 def test_shrink_share_fail(self): 

574 mock_api = self.mock_object(self._driver, '_api', 

575 mock.Mock( 

576 side_effect=( 

577 exception.TegileAPIException( 

578 response="Fake Exception")))) 

579 

580 self.assertRaises(exception.TegileAPIException, 

581 self._driver.shrink_share, 

582 test_share, 30) 

583 

584 shrink_path = '%s/%s/%s/%s' % ( 

585 'fake_pool', 'Local', 'fake_project', test_share['name']) 

586 shrink_params = (shrink_path, str(30), 'GB') 

587 mock_api.assert_called_once_with('resizeShare', shrink_params) 

588 

589 @ddt.data('ip', 'user') 

590 def test_allow_access(self, access_type): 

591 fake_share_info = ('fake_pool', 'fake_project', test_share['name']) 

592 mock_params = self.mock_object(self._driver, 

593 '_get_pool_project_share_name', 

594 mock.Mock(return_value=fake_share_info)) 

595 mock_api = self.mock_object(self._driver, '_api') 

596 

597 access = { 

598 'access_type': access_type, 

599 'access_level': const.ACCESS_LEVEL_RW, 

600 'access_to': 'some-ip', 

601 } 

602 

603 self._driver._allow_access(self._ctxt, test_share, access) 

604 

605 allow_params = ( 

606 '%s/%s/%s/%s' % ( 

607 'fake_pool', 

608 'Local', 

609 'fake_project', 

610 test_share['name'], 

611 ), 

612 test_share['share_proto'], 

613 access_type, 

614 access['access_to'], 

615 access['access_level'], 

616 ) 

617 mock_api.assert_called_once_with('shareAllowAccess', allow_params) 

618 mock_params.assert_called_once_with(test_share) 

619 

620 @ddt.data({'access_type': 'other', 'to': 'some-ip', 'share': test_share, 

621 'exception_type': exception.InvalidShareAccess}, 

622 {'access_type': 'ip', 'to': 'some-ip', 'share': test_share, 

623 'exception_type': exception.TegileAPIException}, 

624 {'access_type': 'ip', 'to': 'some-ip', 'share': test_share_cifs, 

625 'exception_type': exception.InvalidShareAccess}, 

626 {'access_type': 'ip', 'to': 'some-ip', 'share': test_share_fail, 

627 'exception_type': exception.InvalidShareAccess}) 

628 @ddt.unpack 

629 def test_allow_access_fail(self, access_type, to, share, exception_type): 

630 self.mock_object(self._driver, '_api', 

631 mock.Mock( 

632 side_effect=exception.TegileAPIException( 

633 response="Fake Exception"))) 

634 

635 access = { 

636 'access_type': access_type, 

637 'access_level': const.ACCESS_LEVEL_RW, 

638 'access_to': to, 

639 } 

640 

641 self.assertRaises(exception_type, 

642 self._driver._allow_access, 

643 self._ctxt, 

644 share, 

645 access) 

646 

647 @ddt.data('ip', 'user') 

648 def test_deny_access(self, access_type): 

649 fake_share_info = ('fake_pool', 'fake_project', test_share['name']) 

650 mock_params = self.mock_object(self._driver, 

651 '_get_pool_project_share_name', 

652 mock.Mock(return_value=fake_share_info)) 

653 mock_api = self.mock_object(self._driver, '_api') 

654 

655 access = { 

656 'access_type': access_type, 

657 'access_level': const.ACCESS_LEVEL_RW, 

658 'access_to': 'some-ip', 

659 } 

660 

661 self._driver._deny_access(self._ctxt, test_share, access) 

662 

663 deny_params = ( 

664 '%s/%s/%s/%s' % ( 

665 'fake_pool', 

666 'Local', 

667 'fake_project', 

668 test_share['name'], 

669 ), 

670 test_share['share_proto'], 

671 access_type, 

672 access['access_to'], 

673 access['access_level'], 

674 ) 

675 mock_api.assert_called_once_with('shareDenyAccess', deny_params) 

676 mock_params.assert_called_once_with(test_share) 

677 

678 @ddt.data({'access_type': 'other', 'to': 'some-ip', 'share': test_share, 

679 'exception_type': exception.InvalidShareAccess}, 

680 {'access_type': 'ip', 'to': 'some-ip', 'share': test_share, 

681 'exception_type': exception.TegileAPIException}, 

682 {'access_type': 'ip', 'to': 'some-ip', 'share': test_share_cifs, 

683 'exception_type': exception.InvalidShareAccess}, 

684 {'access_type': 'ip', 'to': 'some-ip', 'share': test_share_fail, 

685 'exception_type': exception.InvalidShareAccess}) 

686 @ddt.unpack 

687 def test_deny_access_fail(self, access_type, to, share, exception_type): 

688 self.mock_object(self._driver, '_api', 

689 mock.Mock( 

690 side_effect=exception.TegileAPIException( 

691 response="Fake Exception"))) 

692 

693 access = { 

694 'access_type': access_type, 

695 'access_level': const.ACCESS_LEVEL_RW, 

696 'access_to': to, 

697 } 

698 

699 self.assertRaises(exception_type, 

700 self._driver._deny_access, 

701 self._ctxt, 

702 share, 

703 access) 

704 

705 @ddt.data({'access_rules': [{'access_type': 'ip', 

706 'access_level': const.ACCESS_LEVEL_RW, 

707 'access_to': 'some-ip', 

708 }, ], 'add_rules': None, 

709 'delete_rules': None, 'call_name': 'shareAllowAccess'}, 

710 {'access_rules': [], 'add_rules': 

711 [{'access_type': 'ip', 

712 'access_level': const.ACCESS_LEVEL_RW, 

713 'access_to': 'some-ip'}, ], 'delete_rules': [], 

714 'call_name': 'shareAllowAccess'}, 

715 {'access_rules': [], 'add_rules': [], 'delete_rules': 

716 [{'access_type': 'ip', 

717 'access_level': const.ACCESS_LEVEL_RW, 

718 'access_to': 'some-ip', }, ], 

719 'call_name': 'shareDenyAccess'}) 

720 @ddt.unpack 

721 def test_update_access(self, access_rules, add_rules, 

722 delete_rules, call_name): 

723 fake_share_info = ('fake_pool', 'fake_project', test_share['name']) 

724 mock_params = self.mock_object(self._driver, 

725 '_get_pool_project_share_name', 

726 mock.Mock(return_value=fake_share_info)) 

727 mock_api = self.mock_object(self._driver, '_api') 

728 

729 self._driver.update_access(self._ctxt, 

730 test_share, 

731 access_rules=access_rules, 

732 add_rules=add_rules, 

733 delete_rules=delete_rules, 

734 update_rules=None) 

735 

736 allow_params = ( 

737 '%s/%s/%s/%s' % ( 

738 'fake_pool', 

739 'Local', 

740 'fake_project', 

741 test_share['name'], 

742 ), 

743 test_share['share_proto'], 

744 'ip', 

745 'some-ip', 

746 const.ACCESS_LEVEL_RW, 

747 ) 

748 if not (add_rules or delete_rules): 

749 clear_params = ( 

750 '%s/%s/%s/%s' % ( 

751 'fake_pool', 

752 'Local', 

753 'fake_project', 

754 test_share['name'], 

755 ), 

756 test_share['share_proto'], 

757 ) 

758 mock_api.assert_has_calls([mock.call('clearAccessRules', 

759 clear_params), 

760 mock.call(call_name, 

761 allow_params)]) 

762 mock_params.assert_called_with(test_share) 

763 else: 

764 mock_api.assert_called_once_with(call_name, allow_params) 

765 mock_params.assert_called_once_with(test_share) 

766 

767 @ddt.data({'path': r'\\some-ip\shareName', 'share_proto': 'CIFS', 

768 'host': 'some-ip'}, 

769 {'path': 'some-ip:shareName', 'share_proto': 'NFS', 

770 'host': 'some-ip'}, 

771 {'path': 'some-ip:shareName', 'share_proto': 'NFS', 

772 'host': None}) 

773 @ddt.unpack 

774 def test_get_location_path(self, path, share_proto, host): 

775 self._driver._hostname = 'some-ip' 

776 

777 result = self._driver._get_location_path('shareName', 

778 share_proto, 

779 host) 

780 expected = { 

781 'is_admin_only': False, 

782 'metadata': { 

783 'preferred': True, 

784 }, 

785 'path': path, 

786 } 

787 self.assertEqual(expected, result) 

788 

789 def test_get_location_path_fail(self): 

790 self.assertRaises(exception.InvalidInput, 

791 self._driver._get_location_path, 

792 'shareName', 

793 'SOME', 

794 'some-ip') 

795 

796 def test_get_network_allocations_number(self): 

797 result = self._driver.get_network_allocations_number() 

798 

799 expected = 0 

800 self.assertEqual(expected, result) 

801 

802 

803class TegileAPIExecutorTestCase(test.TestCase): 

804 def setUp(self): 

805 self._api = tegile.TegileAPIExecutor("TestCase", 

806 test_config.tegile_nas_server, 

807 test_config.tegile_nas_login, 

808 test_config.tegile_nas_password) 

809 super(TegileAPIExecutorTestCase, self).setUp() 

810 

811 def test_send_api_post(self): 

812 json_output = {'value': 'abc'} 

813 

814 self.mock_object(requests, 'post', 

815 mock.Mock(return_value=FakeResponse(200, 

816 json_output))) 

817 result = self._api(method="Test", request_type='post', params='[]', 

818 fine_logging=True) 

819 

820 self.assertEqual(json_output, result) 

821 

822 def test_send_api_get(self): 

823 json_output = {'value': 'abc'} 

824 

825 self.mock_object(requests, 'get', 

826 mock.Mock(return_value=FakeResponse(200, 

827 json_output))) 

828 

829 result = self._api(method="Test", 

830 request_type='get', 

831 fine_logging=False) 

832 

833 self.assertEqual(json_output, result) 

834 

835 def test_send_api_get_fail(self): 

836 self.mock_object(requests, 'get', 

837 mock.Mock(return_value=FakeResponse(404, []))) 

838 

839 self.assertRaises(exception.TegileAPIException, 

840 self._api, 

841 method="Test", 

842 request_type='get', 

843 fine_logging=False) 

844 

845 def test_send_api_value_error_fail(self): 

846 json_output = {'value': 'abc'} 

847 

848 self.mock_object(requests, 'post', 

849 mock.Mock(return_value=FakeResponse(200, 

850 json_output))) 

851 self.mock_object(FakeResponse, 'json', 

852 mock.Mock(side_effect=ValueError)) 

853 

854 result = self._api(method="Test", 

855 request_type='post', 

856 fine_logging=False) 

857 

858 expected = '' 

859 self.assertEqual(expected, result)