Coverage for manila/tests/share/drivers/nexenta/ns5/test_jsonrpc.py: 99%

930 statements  

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

1# Copyright 2019 Nexenta by DDN, 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""" 

16Unit tests for NexentaStor 5 REST API helper 

17""" 

18 

19import copy 

20import hashlib 

21import json 

22import posixpath 

23from unittest import mock 

24from urllib import parse as urlparse 

25import uuid 

26 

27import requests 

28 

29from manila.share import configuration as conf 

30from manila.share.drivers.nexenta.ns5 import jsonrpc 

31from manila import test 

32 

33 

34class FakeNefProxy(object): 

35 

36 def __init__(self): 

37 self.scheme = 'https' 

38 self.port = 8443 

39 self.hosts = ['1.1.1.1', '2.2.2.2'] 

40 self.host = self.hosts[0] 

41 self.root = 'pool/share' 

42 self.username = 'username' 

43 self.password = 'password' 

44 self.retries = 3 

45 self.timeout = 5 

46 self.session = mock.Mock() 

47 self.session.headers = {} 

48 

49 def __getattr__(self, name): 

50 pass 

51 

52 def delay(self, interval): 

53 pass 

54 

55 def delete_bearer(self): 

56 pass 

57 

58 def update_lock(self): 

59 pass 

60 

61 def update_token(self, token): 

62 pass 

63 

64 def update_host(self, host): 

65 pass 

66 

67 def url(self, path): 

68 return '%s://%s:%s/%s' % (self.scheme, self.host, self.port, path) 

69 

70 

71class TestNefException(test.TestCase): 

72 

73 def test_message(self): 

74 message = 'test message 1' 

75 result = jsonrpc.NefException(message) 

76 self.assertIn(message, result.msg) 

77 

78 def test_message_kwargs(self): 

79 code = 'EAGAIN' 

80 message = 'test message 2' 

81 result = jsonrpc.NefException(message, code=code) 

82 self.assertEqual(code, result.code) 

83 self.assertIn(message, result.msg) 

84 

85 def test_no_message_kwargs(self): 

86 code = 'ESRCH' 

87 message = 'test message 3' 

88 result = jsonrpc.NefException(None, code=code, message=message) 

89 self.assertEqual(code, result.code) 

90 self.assertIn(message, result.msg) 

91 

92 def test_message_plus_kwargs(self): 

93 code = 'ENODEV' 

94 message1 = 'test message 4' 

95 message2 = 'test message 5' 

96 result = jsonrpc.NefException(message1, code=code, message=message2) 

97 self.assertEqual(code, result.code) 

98 self.assertIn(message2, result.msg) 

99 

100 def test_dict(self): 

101 code = 'ENOENT' 

102 message = 'test message 4' 

103 result = jsonrpc.NefException({'code': code, 'message': message}) 

104 self.assertEqual(code, result.code) 

105 self.assertIn(message, result.msg) 

106 

107 def test_kwargs(self): 

108 code = 'EPERM' 

109 message = 'test message 5' 

110 result = jsonrpc.NefException(code=code, message=message) 

111 self.assertEqual(code, result.code) 

112 self.assertIn(message, result.msg) 

113 

114 def test_dict_kwargs(self): 

115 code = 'EINVAL' 

116 message = 'test message 6' 

117 result = jsonrpc.NefException({'code': code}, message=message) 

118 self.assertEqual(code, result.code) 

119 self.assertIn(message, result.msg) 

120 

121 def test_defaults(self): 

122 code = 'EBADMSG' 

123 message = 'NexentaError' 

124 result = jsonrpc.NefException() 

125 self.assertEqual(code, result.code) 

126 self.assertIn(message, result.msg) 

127 

128 

129class TestNefRequest(test.TestCase): 

130 

131 def setUp(self): 

132 super(TestNefRequest, self).setUp() 

133 self.proxy = FakeNefProxy() 

134 

135 def fake_response(self, method, path, payload, code, content): 

136 request = requests.PreparedRequest() 

137 request.method = method 

138 request.url = self.proxy.url(path) 

139 request.headers = {'Content-Type': 'application/json'} 

140 request.body = None 

141 if method in ['get', 'delete']: 

142 request.params = payload 

143 elif method in ['put', 'post']: 143 ↛ 145line 143 didn't jump to line 145 because the condition on line 143 was always true

144 request.data = json.dumps(payload) 

145 response = requests.Response() 

146 response.request = request 

147 response.status_code = code 

148 response._content = json.dumps(content) if content else '' 

149 return response 

150 

151 def test___call___invalid_method(self): 

152 method = 'unsupported' 

153 instance = jsonrpc.NefRequest(self.proxy, method) 

154 path = 'parent/child' 

155 self.assertRaises(jsonrpc.NefException, instance, path) 

156 

157 def test___call___none_path(self): 

158 method = 'get' 

159 instance = jsonrpc.NefRequest(self.proxy, method) 

160 self.assertRaises(jsonrpc.NefException, instance, None) 

161 

162 def test___call___empty_path(self): 

163 method = 'get' 

164 instance = jsonrpc.NefRequest(self.proxy, method) 

165 self.assertRaises(jsonrpc.NefException, instance, '') 

166 

167 @mock.patch('manila.share.drivers.nexenta.ns5.' 

168 'jsonrpc.NefRequest.request') 

169 def test___call___get(self, request): 

170 method = 'get' 

171 instance = jsonrpc.NefRequest(self.proxy, method) 

172 path = 'parent/child' 

173 payload = {} 

174 content = {'name': 'snapshot'} 

175 response = self.fake_response(method, path, payload, 200, content) 

176 request.return_value = response 

177 result = instance(path, payload) 

178 request.assert_called_with(method, path) 

179 self.assertEqual(content, result) 

180 

181 @mock.patch('manila.share.drivers.nexenta.ns5.' 

182 'jsonrpc.NefRequest.request') 

183 def test___call___get_payload(self, request): 

184 method = 'get' 

185 instance = jsonrpc.NefRequest(self.proxy, method) 

186 path = 'parent/child' 

187 payload = {'key': 'value'} 

188 content = {'name': 'snapshot'} 

189 response = self.fake_response(method, path, payload, 200, content) 

190 request.return_value = response 

191 result = instance(path, payload) 

192 params = {'params': payload} 

193 request.assert_called_with(method, path, **params) 

194 self.assertEqual(content, result) 

195 

196 @mock.patch('manila.share.drivers.nexenta.ns5.' 

197 'jsonrpc.NefRequest.request') 

198 def test___call___get_data_payload(self, request): 

199 method = 'get' 

200 instance = jsonrpc.NefRequest(self.proxy, method) 

201 path = 'parent/child' 

202 payload = {'key': 'value'} 

203 data = [ 

204 { 

205 'name': 'fs1', 

206 'path': 'pool/fs1' 

207 }, 

208 { 

209 'name': 'fs2', 

210 'path': 'pool/fs2' 

211 } 

212 ] 

213 content = {'data': data} 

214 response = self.fake_response(method, path, payload, 200, content) 

215 request.return_value = response 

216 instance.data = data 

217 result = instance(path, payload) 

218 params = {'params': payload} 

219 request.assert_called_with(method, path, **params) 

220 self.assertEqual(data, result) 

221 

222 def test___call___get_invalid_payload(self): 

223 method = 'get' 

224 instance = jsonrpc.NefRequest(self.proxy, method) 

225 path = 'parent/child' 

226 payload = 'bad data' 

227 self.assertRaises(jsonrpc.NefException, instance, path, payload) 

228 

229 @mock.patch('manila.share.drivers.nexenta.ns5.' 

230 'jsonrpc.NefRequest.request') 

231 def test___call___delete(self, request): 

232 method = 'delete' 

233 instance = jsonrpc.NefRequest(self.proxy, method) 

234 path = 'parent/child' 

235 payload = {} 

236 content = {'name': 'snapshot'} 

237 response = self.fake_response(method, path, payload, 200, content) 

238 request.return_value = response 

239 result = instance(path, payload) 

240 request.assert_called_with(method, path) 

241 self.assertEqual(content, result) 

242 

243 @mock.patch('manila.share.drivers.nexenta.ns5.' 

244 'jsonrpc.NefRequest.request') 

245 def test___call___delete_payload(self, request): 

246 method = 'delete' 

247 instance = jsonrpc.NefRequest(self.proxy, method) 

248 path = 'parent/child' 

249 payload = {'key': 'value'} 

250 content = {'name': 'snapshot'} 

251 response = self.fake_response(method, path, payload, 200, content) 

252 request.return_value = response 

253 result = instance(path, payload) 

254 params = {'params': payload} 

255 request.assert_called_with(method, path, **params) 

256 self.assertEqual(content, result) 

257 

258 def test___call___delete_invalid_payload(self): 

259 method = 'delete' 

260 instance = jsonrpc.NefRequest(self.proxy, method) 

261 path = 'parent/child' 

262 payload = 'bad data' 

263 self.assertRaises(jsonrpc.NefException, instance, path, payload) 

264 

265 @mock.patch('manila.share.drivers.nexenta.ns5.' 

266 'jsonrpc.NefRequest.request') 

267 def test___call___post(self, request): 

268 method = 'post' 

269 instance = jsonrpc.NefRequest(self.proxy, method) 

270 path = 'parent/child' 

271 payload = {} 

272 content = None 

273 response = self.fake_response(method, path, payload, 200, content) 

274 request.return_value = response 

275 result = instance(path, payload) 

276 request.assert_called_with(method, path) 

277 self.assertEqual(content, result) 

278 

279 @mock.patch('manila.share.drivers.nexenta.ns5.' 

280 'jsonrpc.NefRequest.request') 

281 def test___call___post_payload(self, request): 

282 method = 'post' 

283 instance = jsonrpc.NefRequest(self.proxy, method) 

284 path = 'parent/child' 

285 payload = {'key': 'value'} 

286 content = None 

287 response = self.fake_response(method, path, payload, 200, content) 

288 request.return_value = response 

289 result = instance(path, payload) 

290 params = {'data': json.dumps(payload)} 

291 request.assert_called_with(method, path, **params) 

292 self.assertEqual(content, result) 

293 

294 def test___call___post_invalid_payload(self): 

295 method = 'post' 

296 instance = jsonrpc.NefRequest(self.proxy, method) 

297 path = 'parent/child' 

298 payload = 'bad data' 

299 self.assertRaises(jsonrpc.NefException, instance, path, payload) 

300 

301 @mock.patch('manila.share.drivers.nexenta.ns5.' 

302 'jsonrpc.NefRequest.request') 

303 def test___call___put(self, request): 

304 method = 'put' 

305 instance = jsonrpc.NefRequest(self.proxy, method) 

306 path = 'parent/child' 

307 payload = {} 

308 content = None 

309 response = self.fake_response(method, path, payload, 200, content) 

310 request.return_value = response 

311 result = instance(path, payload) 

312 request.assert_called_with(method, path) 

313 self.assertEqual(content, result) 

314 

315 @mock.patch('manila.share.drivers.nexenta.ns5.' 

316 'jsonrpc.NefRequest.request') 

317 def test___call___put_payload(self, request): 

318 method = 'put' 

319 instance = jsonrpc.NefRequest(self.proxy, method) 

320 path = 'parent/child' 

321 payload = {'key': 'value'} 

322 content = None 

323 response = self.fake_response(method, path, payload, 200, content) 

324 request.return_value = response 

325 result = instance(path, payload) 

326 params = {'data': json.dumps(payload)} 

327 request.assert_called_with(method, path, **params) 

328 self.assertEqual(content, result) 

329 

330 def test___call___put_invalid_payload(self): 

331 method = 'put' 

332 instance = jsonrpc.NefRequest(self.proxy, method) 

333 path = 'parent/child' 

334 payload = 'bad data' 

335 self.assertRaises(jsonrpc.NefException, instance, path, payload) 

336 

337 @mock.patch('manila.share.drivers.nexenta.ns5.' 

338 'jsonrpc.NefRequest.request') 

339 def test___call___non_ok_response(self, request): 

340 method = 'get' 

341 instance = jsonrpc.NefRequest(self.proxy, method) 

342 path = 'parent/child' 

343 payload = {'key': 'value'} 

344 content = {'code': 'ENOENT', 'message': 'error'} 

345 response = self.fake_response(method, path, payload, 500, content) 

346 request.return_value = response 

347 self.assertRaises(jsonrpc.NefException, instance, path, payload) 

348 

349 @mock.patch('manila.share.drivers.nexenta.ns5.' 

350 'jsonrpc.NefRequest.failover') 

351 @mock.patch('manila.share.drivers.nexenta.ns5.' 

352 'jsonrpc.NefRequest.request') 

353 def test___call___request_after_failover(self, request, failover): 

354 method = 'post' 

355 instance = jsonrpc.NefRequest(self.proxy, method) 

356 path = 'parent/child' 

357 payload = {'key': 'value'} 

358 content = None 

359 response = self.fake_response(method, path, payload, 200, content) 

360 request.side_effect = [requests.exceptions.Timeout, response] 

361 failover.return_value = True 

362 result = instance(path, payload) 

363 params = {'data': json.dumps(payload)} 

364 request.assert_called_with(method, path, **params) 

365 self.assertEqual(content, result) 

366 

367 @mock.patch('manila.share.drivers.nexenta.ns5.' 

368 'jsonrpc.NefRequest.failover') 

369 @mock.patch('manila.share.drivers.nexenta.ns5.' 

370 'jsonrpc.NefRequest.request') 

371 def test___call___request_failover_error(self, request, failover): 

372 method = 'put' 

373 instance = jsonrpc.NefRequest(self.proxy, method) 

374 path = 'parent/child' 

375 payload = {'key': 'value'} 

376 request.side_effect = requests.exceptions.Timeout 

377 failover.return_value = False 

378 self.assertRaises(requests.exceptions.Timeout, instance, path, payload) 

379 

380 def test_hook_default(self): 

381 method = 'post' 

382 instance = jsonrpc.NefRequest(self.proxy, method) 

383 path = 'parent/child' 

384 payload = {'key': 'value'} 

385 content = {'name': 'dataset'} 

386 response = self.fake_response(method, path, payload, 303, content) 

387 result = instance.hook(response) 

388 self.assertEqual(response, result) 

389 

390 def test_hook_200_empty(self): 

391 method = 'delete' 

392 instance = jsonrpc.NefRequest(self.proxy, method) 

393 path = 'storage/filesystems' 

394 payload = {'force': True} 

395 content = None 

396 response = self.fake_response(method, path, payload, 200, content) 

397 result = instance.hook(response) 

398 self.assertEqual(response, result) 

399 

400 def test_hook_201_empty(self): 

401 method = 'post' 

402 instance = jsonrpc.NefRequest(self.proxy, method) 

403 path = 'storage/snapshots' 

404 payload = {'path': 'parent/child@name'} 

405 content = None 

406 response = self.fake_response(method, path, payload, 201, content) 

407 result = instance.hook(response) 

408 self.assertEqual(response, result) 

409 

410 def test_hook_500_empty(self): 

411 method = 'get' 

412 instance = jsonrpc.NefRequest(self.proxy, method) 

413 path = 'storage/pools' 

414 payload = {'poolName': 'tank'} 

415 content = None 

416 response = self.fake_response(method, path, payload, 500, content) 

417 self.assertRaises(jsonrpc.NefException, instance.hook, response) 

418 

419 def test_hook_200_bad_content(self): 

420 method = 'get' 

421 instance = jsonrpc.NefRequest(self.proxy, method) 

422 path = 'storage/volumes' 

423 payload = {'name': 'test'} 

424 content = None 

425 response = self.fake_response(method, path, payload, 200, content) 

426 response._content = 'bad_content' 

427 self.assertRaises(jsonrpc.NefException, instance.hook, response) 

428 

429 @mock.patch('manila.share.drivers.nexenta.ns5.' 

430 'jsonrpc.NefRequest.request') 

431 @mock.patch('manila.share.drivers.nexenta.ns5.' 

432 'jsonrpc.NefRequest.auth') 

433 def test_hook_401(self, auth, request): 

434 method = 'get' 

435 instance = jsonrpc.NefRequest(self.proxy, method) 

436 path = 'parent/child' 

437 payload = {'key': 'value'} 

438 content = {'code': 'EAUTH'} 

439 response = self.fake_response(method, path, payload, 401, content) 

440 auth.return_value = True 

441 content2 = {'name': 'test'} 

442 response2 = self.fake_response(method, path, payload, 200, content2) 

443 request.return_value = response2 

444 self.proxy.session.send.return_value = content2 

445 result = instance.hook(response) 

446 self.assertEqual(content2, result) 

447 

448 def test_hook_401_max_retries(self): 

449 method = 'get' 

450 instance = jsonrpc.NefRequest(self.proxy, method) 

451 instance.stat[401] = self.proxy.retries 

452 path = 'parent/child' 

453 payload = {'key': 'value'} 

454 content = {'code': 'EAUTH'} 

455 response = self.fake_response(method, path, payload, 401, content) 

456 self.assertRaises(jsonrpc.NefException, instance.hook, response) 

457 

458 def test_hook_404_nested(self): 

459 method = 'get' 

460 instance = jsonrpc.NefRequest(self.proxy, method) 

461 instance.lock = True 

462 path = 'parent/child' 

463 payload = {'key': 'value'} 

464 content = {'code': 'ENOENT'} 

465 response = self.fake_response(method, path, payload, 404, content) 

466 result = instance.hook(response) 

467 self.assertEqual(response, result) 

468 

469 def test_hook_404_max_retries(self): 

470 method = 'get' 

471 instance = jsonrpc.NefRequest(self.proxy, method) 

472 instance.stat[404] = self.proxy.retries 

473 path = 'parent/child' 

474 payload = {'key': 'value'} 

475 content = {'code': 'ENOENT'} 

476 response = self.fake_response(method, path, payload, 404, content) 

477 self.assertRaises(jsonrpc.NefException, instance.hook, response) 

478 

479 @mock.patch('manila.share.drivers.nexenta.ns5.' 

480 'jsonrpc.NefRequest.failover') 

481 def test_hook_404_failover_error(self, failover): 

482 method = 'get' 

483 instance = jsonrpc.NefRequest(self.proxy, method) 

484 path = 'parent/child' 

485 payload = {'key': 'value'} 

486 content = {'code': 'ENOENT'} 

487 response = self.fake_response(method, path, payload, 404, content) 

488 failover.return_value = False 

489 result = instance.hook(response) 

490 self.assertEqual(response, result) 

491 

492 @mock.patch('manila.share.drivers.nexenta.ns5.' 

493 'jsonrpc.NefRequest.request') 

494 @mock.patch('manila.share.drivers.nexenta.ns5.' 

495 'jsonrpc.NefRequest.failover') 

496 def test_hook_404_failover_ok(self, failover, request): 

497 method = 'get' 

498 instance = jsonrpc.NefRequest(self.proxy, method) 

499 path = 'parent/child' 

500 payload = {'key': 'value'} 

501 content = {'code': 'ENOENT'} 

502 response = self.fake_response(method, path, payload, 404, content) 

503 failover.return_value = True 

504 content2 = {'name': 'test'} 

505 response2 = self.fake_response(method, path, payload, 200, content2) 

506 request.return_value = response2 

507 result = instance.hook(response) 

508 self.assertEqual(response2, result) 

509 

510 def test_hook_500_permanent(self): 

511 method = 'get' 

512 instance = jsonrpc.NefRequest(self.proxy, method) 

513 path = 'parent/child' 

514 payload = {'key': 'value'} 

515 content = {'code': 'EINVAL'} 

516 response = self.fake_response(method, path, payload, 500, content) 

517 self.assertRaises(jsonrpc.NefException, instance.hook, response) 

518 

519 def test_hook_500_busy_max_retries(self): 

520 method = 'get' 

521 instance = jsonrpc.NefRequest(self.proxy, method) 

522 instance.stat[500] = self.proxy.retries 

523 path = 'parent/child' 

524 payload = {'key': 'value'} 

525 content = {'code': 'EBUSY'} 

526 response = self.fake_response(method, path, payload, 500, content) 

527 self.assertRaises(jsonrpc.NefException, instance.hook, response) 

528 

529 @mock.patch('manila.share.drivers.nexenta.ns5.' 

530 'jsonrpc.NefRequest.request') 

531 def test_hook_500_busy_ok(self, request): 

532 method = 'get' 

533 instance = jsonrpc.NefRequest(self.proxy, method) 

534 path = 'parent/child' 

535 payload = {'key': 'value'} 

536 content = {'code': 'EBUSY'} 

537 response = self.fake_response(method, path, payload, 500, content) 

538 content2 = {'name': 'test'} 

539 response2 = self.fake_response(method, path, payload, 200, content2) 

540 request.return_value = response2 

541 result = instance.hook(response) 

542 self.assertEqual(response2, result) 

543 

544 def test_hook_201_no_monitor(self): 

545 method = 'get' 

546 instance = jsonrpc.NefRequest(self.proxy, method) 

547 path = 'parent/child' 

548 payload = {'key': 'value'} 

549 content = {'monitor': 'unknown'} 

550 response = self.fake_response(method, path, payload, 202, content) 

551 self.assertRaises(jsonrpc.NefException, instance.hook, response) 

552 

553 @mock.patch('manila.share.drivers.nexenta.ns5.' 

554 'jsonrpc.NefRequest.request') 

555 def test_hook_201_ok(self, request): 

556 method = 'delete' 

557 instance = jsonrpc.NefRequest(self.proxy, method) 

558 path = 'parent/child' 

559 payload = {'key': 'value'} 

560 content = { 

561 'links': [{ 

562 'rel': 'monitor', 

563 'href': '/jobStatus/jobID' 

564 }] 

565 } 

566 response = self.fake_response(method, path, payload, 202, content) 

567 content2 = None 

568 response2 = self.fake_response(method, path, payload, 201, content2) 

569 request.return_value = response2 

570 result = instance.hook(response) 

571 self.assertEqual(response2, result) 

572 

573 def test_200_no_data(self): 

574 method = 'get' 

575 instance = jsonrpc.NefRequest(self.proxy, method) 

576 path = 'parent/child' 

577 payload = {'key': 'value'} 

578 content = {'name': 'test'} 

579 response = self.fake_response(method, path, payload, 200, content) 

580 result = instance.hook(response) 

581 self.assertEqual(response, result) 

582 

583 def test_200_pagination_end(self): 

584 method = 'get' 

585 instance = jsonrpc.NefRequest(self.proxy, method) 

586 path = 'parent/child' 

587 payload = {'key': 'value'} 

588 content = {'data': 'value'} 

589 response = self.fake_response(method, path, payload, 200, content) 

590 result = instance.hook(response) 

591 self.assertEqual(response, result) 

592 

593 @mock.patch('manila.share.drivers.nexenta.ns5.' 

594 'jsonrpc.NefRequest.request') 

595 def test_200_pagination_next(self, request): 

596 method = 'get' 

597 instance = jsonrpc.NefRequest(self.proxy, method) 

598 path = 'parent/child' 

599 payload = {'key': 'value'} 

600 content = { 

601 'data': [{ 

602 'name': 'test' 

603 }], 

604 'links': [{ 

605 'rel': 'next', 

606 'href': path 

607 }] 

608 } 

609 response = self.fake_response(method, path, payload, 200, content) 

610 response2 = self.fake_response(method, path, payload, 200, content) 

611 request.return_value = response2 

612 result = instance.hook(response) 

613 self.assertEqual(response2, result) 

614 

615 def test_request(self): 

616 method = 'get' 

617 instance = jsonrpc.NefRequest(self.proxy, method) 

618 path = 'parent/child' 

619 payload = {'key': 'value'} 

620 expected = {'name': 'dataset'} 

621 url = self.proxy.url(path) 

622 kwargs = payload.copy() 

623 kwargs['timeout'] = self.proxy.timeout 

624 kwargs['hooks'] = {'response': instance.hook} 

625 self.proxy.session.request.return_value = expected 

626 result = instance.request(method, path, **payload) 

627 self.proxy.session.request.assert_called_with(method, url, **kwargs) 

628 self.assertEqual(expected, result) 

629 

630 @mock.patch('manila.share.drivers.nexenta.ns5.' 

631 'jsonrpc.NefRequest.request') 

632 def test_auth(self, request): 

633 method = 'get' 

634 instance = jsonrpc.NefRequest(self.proxy, method) 

635 method = 'post' 

636 path = 'auth/login' 

637 payload = { 

638 'data': json.dumps({ 

639 'username': self.proxy.username, 

640 'password': self.proxy.password 

641 }) 

642 } 

643 content = {'token': 'test'} 

644 response = self.fake_response(method, path, payload, 200, content) 

645 request.return_value = response 

646 instance.auth() 

647 request.assert_called_once_with(method, path, **payload) 

648 

649 @mock.patch('manila.share.drivers.nexenta.ns5.' 

650 'jsonrpc.NefRequest.request') 

651 def test_auth_error(self, request): 

652 method = 'get' 

653 instance = jsonrpc.NefRequest(self.proxy, method) 

654 method = 'post' 

655 path = 'auth/login' 

656 payload = { 

657 'data': json.dumps({ 

658 'username': self.proxy.username, 

659 'password': self.proxy.password 

660 }) 

661 } 

662 content = {'data': 'noauth'} 

663 response = self.fake_response(method, path, payload, 200, content) 

664 request.return_value = response 

665 self.assertRaises(jsonrpc.NefException, instance.auth) 

666 

667 @mock.patch('manila.share.drivers.nexenta.ns5.' 

668 'jsonrpc.NefRequest.request') 

669 def test_failover(self, request): 

670 method = 'get' 

671 instance = jsonrpc.NefRequest(self.proxy, method) 

672 path = self.proxy.root 

673 payload = {} 

674 content = {'path': path} 

675 response = self.fake_response(method, path, payload, 200, content) 

676 request.return_value = response 

677 result = instance.failover() 

678 request.assert_called_once_with(method, path) 

679 expected = True 

680 self.assertEqual(expected, result) 

681 

682 @mock.patch('manila.share.drivers.nexenta.ns5.' 

683 'jsonrpc.NefRequest.request') 

684 def test_failover_timeout(self, request): 

685 method = 'get' 

686 instance = jsonrpc.NefRequest(self.proxy, method) 

687 path = self.proxy.root 

688 payload = {} 

689 content = {'path': path} 

690 response = self.fake_response(method, path, payload, 200, content) 

691 request.side_effect = [requests.exceptions.Timeout, response] 

692 result = instance.failover() 

693 request.assert_called_once_with(method, path) 

694 expected = False 

695 self.assertEqual(expected, result) 

696 

697 @mock.patch('manila.share.drivers.nexenta.ns5.' 

698 'jsonrpc.NefRequest.request') 

699 def test_failover_404(self, request): 

700 method = 'get' 

701 instance = jsonrpc.NefRequest(self.proxy, method) 

702 path = self.proxy.root 

703 payload = {} 

704 content = {} 

705 response = self.fake_response(method, path, payload, 404, content) 

706 request.side_effect = [response, response] 

707 result = instance.failover() 

708 request.assert_called_once_with(method, path) 

709 expected = False 

710 self.assertEqual(expected, result) 

711 

712 @mock.patch('manila.share.drivers.nexenta.ns5.' 

713 'jsonrpc.NefRequest.request') 

714 def test_failover_error(self, request): 

715 method = 'get' 

716 instance = jsonrpc.NefRequest(self.proxy, method) 

717 path = self.proxy.root 

718 request.side_effect = [ 

719 requests.exceptions.Timeout, 

720 requests.exceptions.ConnectionError 

721 ] 

722 result = instance.failover() 

723 request.assert_called_with(method, path) 

724 expected = False 

725 self.assertEqual(expected, result) 

726 

727 def test_getpath(self): 

728 method = 'get' 

729 rel = 'monitor' 

730 href = 'jobStatus/jobID' 

731 content = { 

732 'links': [ 

733 [1, 2], 

734 'bad link', 

735 { 

736 'rel': 'next', 

737 'href': href 

738 }, 

739 { 

740 'rel': rel, 

741 'href': href 

742 } 

743 ] 

744 } 

745 instance = jsonrpc.NefRequest(self.proxy, method) 

746 result = instance.getpath(content, rel) 

747 expected = href 

748 self.assertEqual(expected, result) 

749 

750 def test_getpath_no_content(self): 

751 method = 'get' 

752 rel = 'next' 

753 content = None 

754 instance = jsonrpc.NefRequest(self.proxy, method) 

755 result = instance.getpath(content, rel) 

756 self.assertIsNone(result) 

757 

758 def test_getpath_no_links(self): 

759 method = 'get' 

760 rel = 'next' 

761 content = {'a': 'b'} 

762 instance = jsonrpc.NefRequest(self.proxy, method) 

763 result = instance.getpath(content, rel) 

764 self.assertIsNone(result) 

765 

766 def test_getpath_no_rel(self): 

767 method = 'get' 

768 rel = 'next' 

769 content = { 

770 'links': [ 

771 { 

772 'rel': 'monitor', 

773 'href': '/jobs/jobID' 

774 } 

775 ] 

776 } 

777 instance = jsonrpc.NefRequest(self.proxy, method) 

778 result = instance.getpath(content, rel) 

779 self.assertIsNone(result) 

780 

781 def test_getpath_no_href(self): 

782 method = 'get' 

783 rel = 'next' 

784 content = { 

785 'links': [ 

786 { 

787 'rel': rel 

788 } 

789 ] 

790 } 

791 instance = jsonrpc.NefRequest(self.proxy, method) 

792 result = instance.getpath(content, rel) 

793 self.assertIsNone(result) 

794 

795 

796class TestNefCollections(test.TestCase): 

797 

798 def setUp(self): 

799 super(TestNefCollections, self).setUp() 

800 self.proxy = mock.Mock() 

801 self.instance = jsonrpc.NefCollections(self.proxy) 

802 

803 def test_path(self): 

804 path = 'path/to/item name + - & # $ = 0' 

805 result = self.instance.path(path) 

806 quoted_path = urlparse.quote_plus(path) 

807 expected = posixpath.join(self.instance.root, quoted_path) 

808 self.assertEqual(expected, result) 

809 

810 def test_get(self): 

811 name = 'parent/child' 

812 payload = {'key': 'value'} 

813 expected = {'name': 'dataset'} 

814 path = self.instance.path(name) 

815 self.proxy.get.return_value = expected 

816 result = self.instance.get(name, payload) 

817 self.proxy.get.assert_called_with(path, payload) 

818 self.assertEqual(expected, result) 

819 

820 def test_set(self): 

821 name = 'parent/child' 

822 payload = {'key': 'value'} 

823 expected = None 

824 path = self.instance.path(name) 

825 self.proxy.put.return_value = expected 

826 result = self.instance.set(name, payload) 

827 self.proxy.put.assert_called_with(path, payload) 

828 self.assertIsNone(result) 

829 

830 def test_list(self): 

831 payload = {'key': 'value'} 

832 expected = [{'name': 'dataset'}] 

833 self.proxy.get.return_value = expected 

834 result = self.instance.list(payload) 

835 self.proxy.get.assert_called_with(self.instance.root, payload) 

836 self.assertEqual(expected, result) 

837 

838 def test_create(self): 

839 payload = {'key': 'value'} 

840 expected = None 

841 self.proxy.post.return_value = expected 

842 result = self.instance.create(payload) 

843 self.proxy.post.assert_called_with(self.instance.root, payload) 

844 self.assertIsNone(result) 

845 

846 def test_create_exist(self): 

847 payload = {'key': 'value'} 

848 self.proxy.post.side_effect = jsonrpc.NefException(code='EEXIST') 

849 result = self.instance.create(payload) 

850 self.proxy.post.assert_called_with(self.instance.root, payload) 

851 self.assertIsNone(result) 

852 

853 def test_create_error(self): 

854 payload = {'key': 'value'} 

855 self.proxy.post.side_effect = jsonrpc.NefException(code='EBUSY') 

856 self.assertRaises(jsonrpc.NefException, self.instance.create, payload) 

857 self.proxy.post.assert_called_with(self.instance.root, payload) 

858 

859 def test_delete(self): 

860 name = 'parent/child' 

861 payload = {'key': 'value'} 

862 expected = None 

863 path = self.instance.path(name) 

864 self.proxy.delete.return_value = expected 

865 result = self.instance.delete(name, payload) 

866 self.proxy.delete.assert_called_with(path, payload) 

867 self.assertIsNone(result) 

868 

869 def test_delete_not_found(self): 

870 name = 'parent/child' 

871 payload = {'key': 'value'} 

872 path = self.instance.path(name) 

873 self.proxy.delete.side_effect = jsonrpc.NefException(code='ENOENT') 

874 result = self.instance.delete(name, payload) 

875 self.proxy.delete.assert_called_with(path, payload) 

876 self.assertIsNone(result) 

877 

878 def test_delete_error(self): 

879 name = 'parent/child' 

880 payload = {'key': 'value'} 

881 path = self.instance.path(name) 

882 self.proxy.delete.side_effect = jsonrpc.NefException(code='EINVAL') 

883 self.assertRaises(jsonrpc.NefException, self.instance.delete, name, 

884 payload) 

885 self.proxy.delete.assert_called_with(path, payload) 

886 

887 

888class TestNefSettings(test.TestCase): 

889 

890 def setUp(self): 

891 super(TestNefSettings, self).setUp() 

892 self.proxy = mock.Mock() 

893 self.instance = jsonrpc.NefSettings(self.proxy) 

894 

895 def test_create(self): 

896 payload = {'key': 'value'} 

897 result = self.instance.create(payload) 

898 expected = NotImplemented 

899 self.assertEqual(expected, result) 

900 

901 def test_delete(self): 

902 name = 'parent/child' 

903 payload = {'key': 'value'} 

904 result = self.instance.delete(name, payload) 

905 expected = NotImplemented 

906 self.assertEqual(expected, result) 

907 

908 

909class TestNefDatasets(test.TestCase): 

910 

911 def setUp(self): 

912 super(TestNefDatasets, self).setUp() 

913 self.proxy = mock.Mock() 

914 self.instance = jsonrpc.NefDatasets(self.proxy) 

915 

916 def test_rename(self): 

917 name = 'parent/child' 

918 payload = {'key': 'value'} 

919 expected = None 

920 path = self.instance.path(name) 

921 path = posixpath.join(path, 'rename') 

922 self.proxy.post.return_value = expected 

923 result = self.instance.rename(name, payload) 

924 self.proxy.post.assert_called_with(path, payload) 

925 self.assertIsNone(result) 

926 

927 

928class TestNefSnapshots(test.TestCase): 

929 

930 def setUp(self): 

931 super(TestNefSnapshots, self).setUp() 

932 self.proxy = mock.Mock() 

933 self.instance = jsonrpc.NefSnapshots(self.proxy) 

934 

935 def test_clone(self): 

936 name = 'parent/child' 

937 payload = {'key': 'value'} 

938 expected = None 

939 path = self.instance.path(name) 

940 path = posixpath.join(path, 'clone') 

941 self.proxy.post.return_value = expected 

942 result = self.instance.clone(name, payload) 

943 self.proxy.post.assert_called_with(path, payload) 

944 self.assertIsNone(result) 

945 

946 

947class TestNefFilesystems(test.TestCase): 

948 

949 def setUp(self): 

950 super(TestNefFilesystems, self).setUp() 

951 self.proxy = mock.Mock() 

952 self.instance = jsonrpc.NefFilesystems(self.proxy) 

953 

954 def test_mount(self): 

955 name = 'parent/child' 

956 payload = {'key': 'value'} 

957 expected = None 

958 path = self.instance.path(name) 

959 path = posixpath.join(path, 'mount') 

960 self.proxy.post.return_value = expected 

961 result = self.instance.mount(name, payload) 

962 self.proxy.post.assert_called_with(path, payload) 

963 self.assertIsNone(result) 

964 

965 def test_unmount(self): 

966 name = 'parent/child' 

967 payload = {'key': 'value'} 

968 expected = None 

969 path = self.instance.path(name) 

970 path = posixpath.join(path, 'unmount') 

971 self.proxy.post.return_value = expected 

972 result = self.instance.unmount(name, payload) 

973 self.proxy.post.assert_called_with(path, payload) 

974 self.assertIsNone(result) 

975 

976 def test_acl(self): 

977 name = 'parent/child' 

978 payload = {'key': 'value'} 

979 expected = None 

980 path = self.instance.path(name) 

981 path = posixpath.join(path, 'acl') 

982 self.proxy.post.return_value = expected 

983 result = self.instance.acl(name, payload) 

984 self.proxy.post.assert_called_with(path, payload) 

985 self.assertIsNone(result) 

986 

987 def test_promote(self): 

988 name = 'parent/child' 

989 payload = {'key': 'value'} 

990 expected = None 

991 path = self.instance.path(name) 

992 path = posixpath.join(path, 'promote') 

993 self.proxy.post.return_value = expected 

994 result = self.instance.promote(name, payload) 

995 self.proxy.post.assert_called_with(path, payload) 

996 self.assertIsNone(result) 

997 

998 def test_rollback(self): 

999 name = 'parent/child' 

1000 payload = {'key': 'value'} 

1001 expected = None 

1002 path = self.instance.path(name) 

1003 path = posixpath.join(path, 'rollback') 

1004 self.proxy.post.return_value = expected 

1005 result = self.instance.rollback(name, payload) 

1006 self.proxy.post.assert_called_with(path, payload) 

1007 self.assertIsNone(result) 

1008 

1009 

1010class TestNefHpr(test.TestCase): 

1011 

1012 def setUp(self): 

1013 super(TestNefHpr, self).setUp() 

1014 self.proxy = mock.Mock() 

1015 self.instance = jsonrpc.NefHpr(self.proxy) 

1016 

1017 def test_activate(self): 

1018 payload = {'key': 'value'} 

1019 expected = None 

1020 path = posixpath.join(self.instance.root, 'activate') 

1021 self.proxy.post.return_value = expected 

1022 result = self.instance.activate(payload) 

1023 self.proxy.post.assert_called_with(path, payload) 

1024 self.assertIsNone(result) 

1025 

1026 def test_start(self): 

1027 name = 'parent/child' 

1028 payload = {'key': 'value'} 

1029 expected = None 

1030 path = posixpath.join(self.instance.path(name), 'start') 

1031 self.proxy.post.return_value = expected 

1032 result = self.instance.start(name, payload) 

1033 self.proxy.post.assert_called_with(path, payload) 

1034 self.assertIsNone(result) 

1035 

1036 

1037class TestNefProxy(test.TestCase): 

1038 

1039 def setUp(self): 

1040 super(TestNefProxy, self).setUp() 

1041 self.cfg = mock.Mock(spec=conf.Configuration) 

1042 self.cfg.nexenta_use_https = True 

1043 self.cfg.nexenta_ssl_cert_verify = True 

1044 self.cfg.nexenta_user = 'user' 

1045 self.cfg.nexenta_password = 'pass' 

1046 self.cfg.nexenta_rest_addresses = ['1.1.1.1', '2.2.2.2'] 

1047 self.cfg.nexenta_rest_port = 8443 

1048 self.cfg.nexenta_rest_backoff_factor = 1 

1049 self.cfg.nexenta_rest_retry_count = 3 

1050 self.cfg.nexenta_rest_connect_timeout = 1 

1051 self.cfg.nexenta_rest_read_timeout = 1 

1052 self.cfg.nexenta_nas_host = '3.3.3.3' 

1053 self.cfg.nexenta_folder = 'pool/path/to/share' 

1054 self.nef_mock = mock.Mock() 

1055 self.mock_object(jsonrpc, 'NefRequest') 

1056 

1057 self.proto = 'nfs' 

1058 self.proxy = jsonrpc.NefProxy(self.proto, 

1059 self.cfg.nexenta_folder, 

1060 self.cfg) 

1061 

1062 def test___init___http(self): 

1063 proto = 'nfs' 

1064 cfg = copy.copy(self.cfg) 

1065 cfg.nexenta_use_https = False 

1066 result = jsonrpc.NefProxy(proto, cfg.nexenta_folder, cfg) 

1067 self.assertIsInstance(result, jsonrpc.NefProxy) 

1068 

1069 def test___init___no_rest_port_http(self): 

1070 proto = 'nfs' 

1071 cfg = copy.copy(self.cfg) 

1072 cfg.nexenta_rest_port = 0 

1073 cfg.nexenta_use_https = False 

1074 result = jsonrpc.NefProxy(proto, cfg.nexenta_folder, cfg) 

1075 self.assertIsInstance(result, jsonrpc.NefProxy) 

1076 

1077 def test___init___no_rest_port_https(self): 

1078 proto = 'nfs' 

1079 cfg = copy.copy(self.cfg) 

1080 cfg.nexenta_rest_port = 0 

1081 cfg.nexenta_use_https = True 

1082 result = jsonrpc.NefProxy(proto, cfg.nexenta_folder, cfg) 

1083 self.assertIsInstance(result, jsonrpc.NefProxy) 

1084 

1085 def test___init___iscsi(self): 

1086 proto = 'iscsi' 

1087 cfg = copy.copy(self.cfg) 

1088 result = jsonrpc.NefProxy(proto, cfg.nexenta_folder, cfg) 

1089 self.assertIsInstance(result, jsonrpc.NefProxy) 

1090 

1091 def test___init___nfs_no_rest_address(self): 

1092 proto = 'nfs' 

1093 cfg = copy.copy(self.cfg) 

1094 cfg.nexenta_rest_addresses = '' 

1095 result = jsonrpc.NefProxy(proto, cfg.nexenta_folder, cfg) 

1096 self.assertIsInstance(result, jsonrpc.NefProxy) 

1097 

1098 def test___init___iscsi_no_rest_address(self): 

1099 proto = 'iscsi' 

1100 cfg = copy.copy(self.cfg) 

1101 cfg.nexenta_rest_addresses = '' 

1102 cfg.nexenta_nas_host = '4.4.4.4' 

1103 result = jsonrpc.NefProxy(proto, cfg.nexenta_folder, cfg) 

1104 self.assertIsInstance(result, jsonrpc.NefProxy) 

1105 

1106 @mock.patch('requests.packages.urllib3.disable_warnings') 

1107 def test___init___no_ssl_cert_verify(self, disable_warnings): 

1108 proto = 'nfs' 

1109 cfg = copy.copy(self.cfg) 

1110 cfg.nexenta_ssl_cert_verify = False 

1111 disable_warnings.return_value = None 

1112 result = jsonrpc.NefProxy(proto, cfg.nexenta_folder, cfg) 

1113 disable_warnings.assert_called() 

1114 self.assertIsInstance(result, jsonrpc.NefProxy) 

1115 

1116 def test_delete_bearer(self): 

1117 self.assertIsNone(self.proxy.delete_bearer()) 

1118 self.assertNotIn('Authorization', self.proxy.session.headers) 

1119 self.proxy.session.headers['Authorization'] = 'Bearer token' 

1120 self.assertIsNone(self.proxy.delete_bearer()) 

1121 self.assertNotIn('Authorization', self.proxy.session.headers) 

1122 

1123 def test_update_bearer(self): 

1124 token = 'token' 

1125 bearer = 'Bearer %s' % token 

1126 self.assertNotIn('Authorization', self.proxy.session.headers) 

1127 self.assertIsNone(self.proxy.update_bearer(token)) 

1128 self.assertIn('Authorization', self.proxy.session.headers) 

1129 self.assertEqual(self.proxy.session.headers['Authorization'], bearer) 

1130 

1131 def test_update_token(self): 

1132 token = 'token' 

1133 bearer = 'Bearer %s' % token 

1134 self.assertIsNone(self.proxy.update_token(token)) 

1135 self.assertEqual(self.proxy.tokens[self.proxy.host], token) 

1136 self.assertEqual(self.proxy.session.headers['Authorization'], bearer) 

1137 

1138 def test_update_host(self): 

1139 token = 'token' 

1140 bearer = 'Bearer %s' % token 

1141 host = self.cfg.nexenta_rest_addresses[0] 

1142 self.proxy.tokens[host] = token 

1143 self.assertIsNone(self.proxy.update_host(host)) 

1144 self.assertEqual(self.proxy.session.headers['Authorization'], bearer) 

1145 

1146 def test_skip_update_host(self): 

1147 host = 'nonexistent' 

1148 self.assertIsNone(self.proxy.update_host(host)) 

1149 

1150 @mock.patch('manila.share.drivers.nexenta.ns5.' 

1151 'jsonrpc.NefSettings.get') 

1152 def test_update_lock(self, get_settings): 

1153 guid = uuid.uuid4().hex 

1154 settings = {'value': guid} 

1155 get_settings.return_value = settings 

1156 self.assertIsNone(self.proxy.update_lock()) 

1157 path = '%s:%s' % (guid, self.proxy.path) 

1158 if isinstance(path, str): 1158 ↛ 1160line 1158 didn't jump to line 1160 because the condition on line 1158 was always true

1159 path = path.encode('utf-8') 

1160 expected = hashlib.md5(path).hexdigest() 

1161 self.assertEqual(expected, self.proxy.lock) 

1162 

1163 def test_url(self): 

1164 path = '/path/to/api' 

1165 result = self.proxy.url(path) 

1166 expected = '%s://%s:%s%s' % (self.proxy.scheme, 

1167 self.proxy.host, 

1168 self.proxy.port, 

1169 path) 

1170 self.assertEqual(expected, result) 

1171 

1172 @mock.patch('time.sleep') 

1173 def test_delay(self, sleep): 

1174 sleep.return_value = None 

1175 for attempt in range(0, 10): 

1176 expected = int(self.proxy.backoff_factor * (2 ** (attempt - 1))) 

1177 self.assertIsNone(self.proxy.delay(attempt)) 

1178 sleep.assert_called_with(expected)