Coverage for manila/tests/api/v2/test_quota_sets.py: 98%

306 statements  

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

1# Copyright 2013 OpenStack Foundation 

2# Copyright (c) 2015 Mirantis inc. 

3# 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 

17""" 

18Tests for manila.api.v2.quota_sets.py 

19""" 

20 

21from unittest import mock 

22 

23import ddt 

24from oslo_config import cfg 

25import webob.exc 

26import webob.response 

27 

28from manila.api.openstack import api_version_request as api_version 

29from manila.api.v2 import quota_sets 

30from manila import context 

31from manila import exception 

32from manila import policy 

33from manila import test 

34from manila.tests.api import fakes 

35from manila import utils 

36 

37CONF = cfg.CONF 

38sg_quota_keys = ['share_groups', 'share_group_snapshots'] 

39replica_quota_keys = ['share_replicas'] 

40per_share_size_quota_keys = ['per_share_gigabytes'] 

41 

42 

43def _get_request(is_admin, user_in_url): 

44 req = mock.MagicMock( 

45 api_version_request=api_version.APIVersionRequest("2.40")) 

46 req.environ = {'manila.context': context.get_admin_context()} 

47 req.environ['manila.context'].is_admin = is_admin 

48 req.environ['manila.context'].auth_token = 'foo_auth_token' 

49 req.environ['manila.context'].project_id = 'foo_project_id' 

50 if user_in_url: 

51 req.environ['manila.context'].user_id = 'foo_user_id' 

52 req.environ['QUERY_STRING'] = 'user_id=foo_user_id' 

53 return req 

54 

55 

56@ddt.ddt 

57class QuotaSetsControllerTest(test.TestCase): 

58 

59 def setUp(self): 

60 super(QuotaSetsControllerTest, self).setUp() 

61 self.controller = quota_sets.QuotaSetsController() 

62 self.resource_name = self.controller.resource_name 

63 self.project_id = 'foo_project_id' 

64 self.mock_policy_check = self.mock_object( 

65 policy, 'check_policy', mock.Mock(return_value=True)) 

66 

67 @ddt.data( 

68 {"shares": 3, "snapshots": 4, "gigabytes": 5, 

69 "snapshot_gigabytes": 6, "share_networks": 7}, 

70 {"shares": -1, "snapshots": -1, "gigabytes": -1, 

71 "snapshot_gigabytes": -1, "share_networks": -1}, 

72 {"shares": 13}, 

73 {"snapshots": 24}, 

74 {"gigabytes": 7}, 

75 {"snapshot_gigabytes": 10001}, 

76 {"share_networks": 12345}, 

77 {"share_groups": 123456}, 

78 {"share_group_snapshots": 123456}, 

79 ) 

80 def test_defaults(self, quotas): 

81 req = _get_request(True, False) 

82 for k, v in quotas.items(): 

83 CONF.set_default(k, v, 'quota') 

84 expected = { 

85 'quota_set': { 

86 'id': self.project_id, 

87 'shares': quotas.get('shares', 50), 

88 'gigabytes': quotas.get('gigabytes', 1000), 

89 'snapshots': quotas.get('snapshots', 50), 

90 'snapshot_gigabytes': quotas.get('snapshot_gigabytes', 1000), 

91 'share_networks': quotas.get('share_networks', 10), 

92 'share_groups': quotas.get('share_groups', 50), 

93 'share_group_snapshots': quotas.get( 

94 'share_group_snapshots', 50), 

95 } 

96 } 

97 

98 result = self.controller.defaults(req, self.project_id) 

99 

100 self.assertEqual(expected, result) 

101 self.mock_policy_check.assert_called_once_with( 

102 req.environ['manila.context'], self.resource_name, 'show') 

103 

104 @ddt.data( 

105 ('os-', '1.0', quota_sets.QuotaSetsControllerLegacy, 'defaults'), 

106 ('os-', '2.6', quota_sets.QuotaSetsControllerLegacy, 'defaults'), 

107 ('', '2.7', quota_sets.QuotaSetsController, 'defaults'), 

108 ('os-', '1.0', quota_sets.QuotaSetsControllerLegacy, 'show'), 

109 ('os-', '2.6', quota_sets.QuotaSetsControllerLegacy, 'show'), 

110 ('', '2.7', quota_sets.QuotaSetsController, 'show'), 

111 ) 

112 @ddt.unpack 

113 def test_get_quotas_with_different_api_versions(self, url, version, 

114 controller, method_name): 

115 expected = { 

116 'quota_set': { 

117 'id': self.project_id, 

118 'shares': 50, 

119 'gigabytes': 1000, 

120 'snapshots': 50, 

121 'snapshot_gigabytes': 1000, 

122 'share_networks': 10, 

123 } 

124 } 

125 req = fakes.HTTPRequest.blank( 

126 '/fooproject/%squota-sets' % url, 

127 version=version, use_admin_context=True) 

128 

129 result = getattr(controller(), method_name)(req, self.project_id) 

130 

131 self.assertEqual(expected, result) 

132 

133 @staticmethod 

134 def _get_share_type_request_object(microversion=None): 

135 req = _get_request(True, False) 

136 req.environ['QUERY_STRING'] = 'share_type=fake_share_type_name_or_id' 

137 req.api_version_request = api_version.APIVersionRequest( 

138 microversion or '2.39') 

139 return req 

140 

141 @ddt.data('2.39', '2.40') 

142 def test_share_type_quota_detail(self, microversion): 

143 self.mock_object( 

144 quota_sets.db, 'share_type_get_by_name_or_id', 

145 mock.Mock(return_value={'id': 'fake_st_id'})) 

146 req = self._get_share_type_request_object(microversion) 

147 quotas = { 

148 "shares": 23, 

149 "snapshots": 34, 

150 "gigabytes": 45, 

151 "snapshot_gigabytes": 56, 

152 } 

153 expected = {'quota_set': { 

154 'id': self.project_id, 

155 'shares': { 

156 'in_use': 0, 

157 'limit': quotas['shares'], 

158 'reserved': 0, 

159 }, 

160 'gigabytes': { 

161 'in_use': 0, 

162 'limit': quotas['gigabytes'], 

163 'reserved': 0, 

164 }, 

165 'snapshots': { 

166 'in_use': 0, 

167 'limit': quotas['snapshots'], 

168 'reserved': 0, 

169 }, 

170 'snapshot_gigabytes': { 

171 'in_use': 0, 

172 'limit': quotas['snapshot_gigabytes'], 

173 'reserved': 0, 

174 }, 

175 }} 

176 for k, v in quotas.items(): 

177 CONF.set_default(k, v, 'quota') 

178 

179 result = self.controller.detail(req, self.project_id) 

180 

181 self.assertEqual(expected, result) 

182 self.mock_policy_check.assert_called_once_with( 

183 req.environ['manila.context'], self.resource_name, 'show') 

184 quota_sets.db.share_type_get_by_name_or_id.assert_called_once_with( 

185 req.environ['manila.context'], 'fake_share_type_name_or_id') 

186 

187 @ddt.data('2.39', '2.40') 

188 def test_show_share_type_quota(self, microversion): 

189 self.mock_object( 

190 quota_sets.db, 'share_type_get_by_name_or_id', 

191 mock.Mock(return_value={'id': 'fake_st_id'})) 

192 req = self._get_share_type_request_object(microversion) 

193 quotas = { 

194 "shares": 23, 

195 "snapshots": 34, 

196 "gigabytes": 45, 

197 "snapshot_gigabytes": 56, 

198 } 

199 expected = { 

200 'quota_set': { 

201 'id': self.project_id, 

202 'shares': quotas.get('shares', 50), 

203 'gigabytes': quotas.get('gigabytes', 1000), 

204 'snapshots': quotas.get('snapshots', 50), 

205 'snapshot_gigabytes': quotas.get('snapshot_gigabytes', 1000), 

206 } 

207 } 

208 for k, v in quotas.items(): 

209 CONF.set_default(k, v, 'quota') 

210 

211 result = self.controller.show(req, self.project_id) 

212 

213 self.assertEqual(expected, result) 

214 self.mock_policy_check.assert_called_once_with( 

215 req.environ['manila.context'], self.resource_name, 'show') 

216 quota_sets.db.share_type_get_by_name_or_id.assert_called_once_with( 

217 req.environ['manila.context'], 'fake_share_type_name_or_id') 

218 

219 @ddt.data('show', 'detail') 

220 def test_get_share_type_quota_with_old_microversion(self, method): 

221 req = self._get_share_type_request_object('2.38') 

222 self.assertRaises( 

223 webob.exc.HTTPBadRequest, 

224 getattr(self.controller, method), 

225 req, self.project_id) 

226 

227 @ddt.data((None, None), (None, 'foo'), ('bar', None)) 

228 @ddt.unpack 

229 def test__validate_user_id_and_share_type_args(self, user_id, st_id): 

230 result = self.controller._validate_user_id_and_share_type_args( 

231 user_id, st_id) 

232 

233 self.assertIsNone(result) 

234 

235 def test__validate_user_id_and_share_type_args_exception(self): 

236 self.assertRaises( 

237 webob.exc.HTTPBadRequest, 

238 self.controller._validate_user_id_and_share_type_args, 

239 'foo', 'bar') 

240 

241 def test__get_share_type_id_found(self): 

242 self.mock_object( 

243 quota_sets.db, 'share_type_get_by_name_or_id', 

244 mock.Mock(return_value={'id': 'fake_st_id'})) 

245 ctxt = 'fake_context' 

246 share_type = 'fake_share_type_name_or_id' 

247 

248 result = self.controller._get_share_type_id(ctxt, share_type) 

249 

250 self.assertEqual('fake_st_id', result) 

251 

252 def test__get_share_type_id_not_found(self): 

253 self.mock_object( 

254 quota_sets.db, 'share_type_get_by_name_or_id', 

255 mock.Mock(return_value=None)) 

256 ctxt = 'fake_context' 

257 share_type = 'fake_share_type_name_or_id' 

258 

259 self.assertRaises( 

260 webob.exc.HTTPNotFound, 

261 self.controller._get_share_type_id, 

262 ctxt, share_type) 

263 

264 def test__get_share_type_id_is_not_provided(self): 

265 self.mock_object( 

266 quota_sets.db, 'share_type_get_by_name_or_id', 

267 mock.Mock(return_value={'id': 'fake_st_id'})) 

268 ctxt = 'fake_context' 

269 

270 result = self.controller._get_share_type_id(ctxt, None) 

271 

272 self.assertIsNone(result) 

273 

274 @ddt.data( 

275 ({}, sg_quota_keys, '2.40'), 

276 ({"quota_set": {}}, sg_quota_keys, '2.40'), 

277 ({"quota_set": {"foo": "bar"}}, sg_quota_keys, '2.40'), 

278 ({"foo": "bar"}, replica_quota_keys, '2.53'), 

279 ({"quota_set": {"foo": "bar"}}, replica_quota_keys, '2.53'), 

280 ({"quota_set": {"foo": "bar"}}, per_share_size_quota_keys, '2.62'), 

281 ) 

282 @ddt.unpack 

283 def test__ensure_specific_microversion_args_are_absent_success( 

284 self, body, keys, microversion): 

285 result = self.controller._ensure_specific_microversion_args_are_absent( 

286 body, keys, microversion) 

287 

288 self.assertIsNone(result) 

289 

290 @ddt.data( 

291 ({"share_groups": 5}, sg_quota_keys, '2.40'), 

292 ({"share_group_snapshots": 6}, sg_quota_keys, '2.40'), 

293 ({"quota_set": {"share_groups": 7}}, sg_quota_keys, '2.40'), 

294 ({"quota_set": {"share_group_snapshots": 8}}, sg_quota_keys, '2.40'), 

295 ({"quota_set": {"share_replicas": 9}}, replica_quota_keys, '2.53'), 

296 ({"quota_set": {"share_replicas": 10}}, replica_quota_keys, '2.53'), 

297 ({"quota_set": {"per_share_gigabytes": 10}}, 

298 per_share_size_quota_keys, '2.62'), 

299 ) 

300 @ddt.unpack 

301 def test__ensure_specific_microversion_args_are_absent_error( 

302 self, body, keys, microversion): 

303 self.assertRaises( 

304 webob.exc.HTTPBadRequest, 

305 self.controller._ensure_specific_microversion_args_are_absent, 

306 body, 

307 keys, 

308 microversion 

309 ) 

310 

311 @ddt.data(_get_request(True, True), _get_request(True, False)) 

312 def test__ensure_share_type_arg_is_absent(self, req): 

313 result = self.controller._ensure_share_type_arg_is_absent(req) 

314 

315 self.assertIsNone(result) 

316 

317 def test__ensure_share_type_arg_is_absent_exception(self): 

318 req = self._get_share_type_request_object('2.39') 

319 

320 self.assertRaises( 

321 webob.exc.HTTPBadRequest, 

322 self.controller._ensure_share_type_arg_is_absent, 

323 req) 

324 

325 @ddt.data(_get_request(True, True), _get_request(True, False)) 

326 def test_quota_detail(self, request): 

327 request.api_version_request = api_version.APIVersionRequest('2.25') 

328 quotas = { 

329 "shares": 23, 

330 "snapshots": 34, 

331 "gigabytes": 45, 

332 "snapshot_gigabytes": 56, 

333 "share_networks": 67, 

334 } 

335 expected = { 

336 'quota_set': { 

337 'id': self.project_id, 

338 'shares': {'in_use': 0, 

339 'limit': quotas['shares'], 

340 'reserved': 0}, 

341 'gigabytes': {'in_use': 0, 

342 'limit': quotas['gigabytes'], 'reserved': 0}, 

343 'snapshots': {'in_use': 0, 

344 'limit': quotas['snapshots'], 'reserved': 0}, 

345 'snapshot_gigabytes': { 

346 'in_use': 0, 

347 'limit': quotas['snapshot_gigabytes'], 

348 'reserved': 0, 

349 }, 

350 'share_networks': { 

351 'in_use': 0, 

352 'limit': quotas['share_networks'], 

353 'reserved': 0 

354 }, 

355 } 

356 } 

357 for k, v in quotas.items(): 

358 CONF.set_default(k, v, 'quota') 

359 

360 result = self.controller.detail(request, self.project_id) 

361 

362 self.assertEqual(expected, result) 

363 self.mock_policy_check.assert_called_once_with( 

364 request.environ['manila.context'], self.resource_name, 'show') 

365 

366 @ddt.data(_get_request(True, True), _get_request(True, False)) 

367 def test_show_quota(self, request): 

368 quotas = { 

369 "shares": 23, 

370 "snapshots": 34, 

371 "gigabytes": 45, 

372 "snapshot_gigabytes": 56, 

373 "share_networks": 67, 

374 "share_groups": 53, 

375 "share_group_snapshots": 57, 

376 } 

377 expected = { 

378 'quota_set': { 

379 'id': self.project_id, 

380 'shares': quotas.get('shares', 50), 

381 'gigabytes': quotas.get('gigabytes', 1000), 

382 'snapshots': quotas.get('snapshots', 50), 

383 'snapshot_gigabytes': quotas.get('snapshot_gigabytes', 1000), 

384 'share_networks': quotas.get('share_networks', 10), 

385 'share_groups': quotas.get('share_groups', 50), 

386 'share_group_snapshots': quotas.get( 

387 'share_group_snapshots', 50), 

388 } 

389 } 

390 for k, v in quotas.items(): 

391 CONF.set_default(k, v, 'quota') 

392 

393 result = self.controller.show(request, self.project_id) 

394 

395 self.assertEqual(expected, result) 

396 self.mock_policy_check.assert_called_once_with( 

397 request.environ['manila.context'], self.resource_name, 'show') 

398 

399 def test_show_quota_not_authorized(self): 

400 req = _get_request(True, False) 

401 self.mock_object( 

402 quota_sets.db, 

403 'authorize_project_context', 

404 mock.Mock(side_effect=exception.NotAuthorized)) 

405 

406 self.assertRaises( 

407 webob.exc.HTTPForbidden, 

408 self.controller.show, 

409 req, self.project_id) 

410 self.mock_policy_check.assert_called_once_with( 

411 req.environ['manila.context'], self.resource_name, 'show') 

412 

413 @ddt.data(_get_request(True, True), _get_request(True, False)) 

414 def test_update_quota(self, request): 

415 self.mock_object( 

416 quota_sets.db, 'share_type_get_by_name_or_id', 

417 mock.Mock( 

418 return_value={'id': 'fake_st_id', 'name': 'fake_st_name'})) 

419 CONF.set_default('shares', 789, 'quota') 

420 body = {'quota_set': {'tenant_id': self.project_id, 'shares': 788}} 

421 expected = { 

422 'quota_set': { 

423 'shares': body['quota_set']['shares'], 

424 'gigabytes': 1000, 

425 'snapshots': 50, 

426 'snapshot_gigabytes': 1000, 

427 'share_networks': 10, 

428 'share_groups': 50, 

429 'share_group_snapshots': 50, 

430 } 

431 } 

432 mock_policy_update_check_call = mock.call( 

433 request.environ['manila.context'], self.resource_name, 'update') 

434 mock_policy_show_check_call = mock.call( 

435 request.environ['manila.context'], self.resource_name, 'show') 

436 

437 update_result = self.controller.update( 

438 request, self.project_id, body=body) 

439 

440 self.assertEqual(expected, update_result) 

441 

442 show_result = self.controller.show(request, self.project_id) 

443 

444 expected['quota_set']['id'] = self.project_id 

445 self.assertEqual(expected, show_result) 

446 self.mock_policy_check.assert_has_calls([ 

447 mock_policy_update_check_call, mock_policy_show_check_call]) 

448 quota_sets.db.share_type_get_by_name_or_id.assert_not_called() 

449 

450 @ddt.data(_get_request(True, True), _get_request(True, False)) 

451 def test_update_quota_with_value_greater_than_2147483647(self, req): 

452 value = 2147483648 

453 body = {'quota_set': {'tenant_id': self.project_id, 'shares': value}} 

454 

455 if req == _get_request(True, True): 455 ↛ 456line 455 didn't jump to line 456 because the condition on line 455 was never true

456 self.mock_policy_update_check_call = mock.call( 

457 req.environ['manila.context'], self.resource_name, 'update') 

458 self.assertRaises( 

459 webob.exc.HTTPBadRequest, 

460 self.controller.update, 

461 req, self.project_id, body 

462 ) 

463 self.mock_policy_check.assert_called_once_with( 

464 req.environ['manila.context'], self.resource_name, 'update') 

465 

466 if req == _get_request(True, False): 466 ↛ 467line 466 didn't jump to line 467 because the condition on line 466 was never true

467 self.assertRaises( 

468 webob.exc.HTTPBadRequest, 

469 self.controller.update, 

470 req, self.project_id, body 

471 ) 

472 self.mock_policy_check.assert_not_called() 

473 

474 @ddt.data('2.39', '2.40') 

475 def test_update_share_type_quota(self, microversion): 

476 self.mock_object( 

477 quota_sets.db, 'share_type_get_by_name_or_id', 

478 mock.Mock( 

479 return_value={'id': 'fake_st_id', 'name': 'fake_st_name'})) 

480 req = self._get_share_type_request_object(microversion) 

481 

482 CONF.set_default('shares', 789, 'quota') 

483 body = {'quota_set': {'tenant_id': self.project_id, 'shares': 788}} 

484 expected = { 

485 'quota_set': { 

486 'shares': body['quota_set']['shares'], 

487 'gigabytes': 1000, 

488 'snapshots': 50, 

489 'snapshot_gigabytes': 1000, 

490 } 

491 } 

492 

493 update_result = self.controller.update(req, self.project_id, body=body) 

494 

495 self.assertEqual(expected, update_result) 

496 quota_sets.db.share_type_get_by_name_or_id.assert_called_once_with( 

497 req.environ['manila.context'], 

498 req.environ['QUERY_STRING'].split('=')[-1]) 

499 quota_sets.db.share_type_get_by_name_or_id.reset_mock() 

500 

501 show_result = self.controller.show(req, self.project_id) 

502 

503 expected['quota_set']['id'] = self.project_id 

504 self.assertEqual(expected, show_result) 

505 self.mock_policy_check.assert_has_calls([ 

506 mock.call(req.environ['manila.context'], self.resource_name, key) 

507 for key in ('update', 'show') 

508 ]) 

509 quota_sets.db.share_type_get_by_name_or_id.assert_called_once_with( 

510 req.environ['manila.context'], 

511 req.environ['QUERY_STRING'].split('=')[-1]) 

512 

513 def test_update_share_type_quota_using_too_old_microversion(self): 

514 self.mock_object( 

515 quota_sets.db, 'share_type_get_by_name_or_id', 

516 mock.Mock( 

517 return_value={'id': 'fake_st_id', 'name': 'fake_st_name'})) 

518 req = self._get_share_type_request_object('2.38') 

519 body = {'quota_set': {'tenant_id': self.project_id, 'shares': 788}} 

520 

521 self.assertRaises( 

522 webob.exc.HTTPBadRequest, 

523 self.controller.update, 

524 req, self.project_id, body=body) 

525 

526 quota_sets.db.share_type_get_by_name_or_id.assert_not_called() 

527 

528 def test_update_share_type_quota_for_share_networks(self): 

529 self.mock_object( 

530 quota_sets.db, 'share_type_get_by_name_or_id', 

531 mock.Mock( 

532 return_value={'id': 'fake_st_id', 'name': 'fake_st_name'})) 

533 req = self._get_share_type_request_object('2.39') 

534 body = {'quota_set': { 

535 'tenant_id': self.project_id, 'share_networks': 788, 

536 }} 

537 

538 self.assertRaises( 

539 webob.exc.HTTPBadRequest, 

540 self.controller.update, 

541 req, self.project_id, body=body) 

542 

543 quota_sets.db.share_type_get_by_name_or_id.assert_called_once_with( 

544 req.environ['manila.context'], 

545 req.environ['QUERY_STRING'].split('=')[-1]) 

546 

547 @ddt.data(-2, 'foo', {1: 2}, [1]) 

548 def test_update_quota_with_invalid_value(self, value): 

549 req = _get_request(True, False) 

550 body = {'quota_set': {'tenant_id': self.project_id, 'shares': value}} 

551 

552 self.assertRaises( 

553 webob.exc.HTTPBadRequest, 

554 self.controller.update, 

555 req, self.project_id, body=body) 

556 self.mock_policy_check.assert_called_once_with( 

557 req.environ['manila.context'], self.resource_name, 'update') 

558 

559 def test_user_quota_can_not_be_bigger_than_tenant_quota(self): 

560 value = 777 

561 CONF.set_default('shares', value, 'quota') 

562 body = { 

563 'quota_set': { 

564 'tenant_id': self.project_id, 

565 'shares': value + 1, 

566 } 

567 } 

568 req = _get_request(True, True) 

569 

570 self.assertRaises( 

571 webob.exc.HTTPBadRequest, 

572 self.controller.update, 

573 req, self.project_id, body=body) 

574 self.mock_policy_check.assert_called_once_with( 

575 req.environ['manila.context'], self.resource_name, 'update') 

576 

577 def test_update_inexistent_quota(self): 

578 body = { 

579 'quota_set': { 

580 'tenant_id': self.project_id, 

581 'fake_quota': 13, 

582 } 

583 } 

584 req = _get_request(True, False) 

585 

586 self.assertRaises( 

587 webob.exc.HTTPBadRequest, 

588 self.controller.update, 

589 req, self.project_id, body=body) 

590 self.mock_policy_check.assert_called_once_with( 

591 req.environ['manila.context'], self.resource_name, 'update') 

592 

593 def test_update_quota_not_authorized(self): 

594 body = {'quota_set': {'tenant_id': self.project_id, 'shares': 13}} 

595 req = _get_request(False, False) 

596 

597 self.assertRaises( 

598 webob.exc.HTTPForbidden, 

599 self.controller.update, 

600 req, self.project_id, body=body) 

601 self.mock_policy_check.assert_called_once_with( 

602 req.environ['manila.context'], self.resource_name, 'update') 

603 

604 @ddt.data( 

605 ('os-quota-sets', '1.0', quota_sets.QuotaSetsControllerLegacy), 

606 ('os-quota-sets', '2.6', quota_sets.QuotaSetsControllerLegacy), 

607 ('quota-sets', '2.7', quota_sets.QuotaSetsController), 

608 ) 

609 @ddt.unpack 

610 def test_update_all_quotas_with_force(self, url, version, controller): 

611 req = fakes.HTTPRequest.blank( 

612 '/fooproject/%s' % url, version=version, use_admin_context=True) 

613 quotas = ( 

614 ('quota_shares', 13), 

615 ('quota_gigabytes', 14), 

616 ('quota_snapshots', 15), 

617 ('quota_snapshot_gigabytes', 16), 

618 ('quota_share_networks', 17), 

619 ) 

620 for quota, value in quotas: 

621 CONF.set_default(quota, value) 

622 expected = { 

623 'quota_set': { 

624 'tenant_id': self.project_id, 

625 'shares': quotas[0][1], 

626 'gigabytes': quotas[1][1], 

627 'snapshots': quotas[2][1], 

628 'snapshot_gigabytes': quotas[3][1], 

629 'share_networks': quotas[4][1], 

630 'force': True, 

631 } 

632 } 

633 

634 update_result = controller().update( 

635 req, self.project_id, body=expected) 

636 

637 expected['quota_set'].pop('force') 

638 expected['quota_set'].pop('tenant_id') 

639 self.assertEqual(expected, update_result) 

640 

641 show_result = controller().show(req, self.project_id) 

642 

643 expected['quota_set']['id'] = self.project_id 

644 self.assertEqual(expected, show_result) 

645 self.mock_policy_check.assert_has_calls([ 

646 mock.call(req.environ['manila.context'], 

647 self.resource_name, action) 

648 for action in ('update', 'show') 

649 ]) 

650 

651 @ddt.data( 

652 ('os-quota-sets', '1.0', quota_sets.QuotaSetsControllerLegacy), 

653 ('os-quota-sets', '2.6', quota_sets.QuotaSetsControllerLegacy), 

654 ('quota-sets', '2.7', quota_sets.QuotaSetsController), 

655 ) 

656 @ddt.unpack 

657 def test_delete_tenant_quota(self, url, version, controller): 

658 self.mock_object(quota_sets.QUOTAS, 'destroy_all_by_project_and_user') 

659 self.mock_object(quota_sets.QUOTAS, 'destroy_all_by_project') 

660 req = fakes.HTTPRequest.blank( 

661 '/fooproject/%s' % url, version=version, use_admin_context=True) 

662 

663 result = controller().delete(req, self.project_id) 

664 

665 self.assertTrue( 

666 utils.IsAMatcher(webob.response.Response) == result 

667 ) 

668 self.assertTrue(hasattr(result, 'status_code')) 

669 self.assertEqual(202, result.status_code) 

670 self.assertFalse( 

671 quota_sets.QUOTAS.destroy_all_by_project_and_user.called) 

672 quota_sets.QUOTAS.destroy_all_by_project.assert_called_once_with( 

673 req.environ['manila.context'], self.project_id) 

674 self.mock_policy_check.assert_called_once_with( 

675 req.environ['manila.context'], self.resource_name, 'delete') 

676 

677 def test_delete_user_quota(self): 

678 project_id = 'foo_project_id' 

679 self.mock_object(quota_sets.QUOTAS, 'destroy_all_by_project_and_user') 

680 self.mock_object(quota_sets.QUOTAS, 'destroy_all_by_project') 

681 req = _get_request(True, True) 

682 

683 result = self.controller.delete(req, project_id) 

684 

685 self.assertTrue( 

686 utils.IsAMatcher(webob.response.Response) == result 

687 ) 

688 self.assertTrue(hasattr(result, 'status_code')) 

689 self.assertEqual(202, result.status_code) 

690 (quota_sets.QUOTAS.destroy_all_by_project_and_user. 

691 assert_called_once_with( 

692 req.environ['manila.context'], 

693 project_id, 

694 req.environ['manila.context'].user_id)) 

695 self.assertFalse(quota_sets.QUOTAS.destroy_all_by_project.called) 

696 self.mock_policy_check.assert_called_once_with( 

697 req.environ['manila.context'], self.resource_name, 'delete') 

698 

699 def test_delete_share_type_quota(self): 

700 req = self._get_share_type_request_object('2.39') 

701 self.mock_object(quota_sets.QUOTAS, 'destroy_all_by_project') 

702 self.mock_object(quota_sets.QUOTAS, 'destroy_all_by_project_and_user') 

703 mock_delete_st_quotas = self.mock_object( 

704 quota_sets.QUOTAS, 'destroy_all_by_project_and_share_type') 

705 self.mock_object( 

706 quota_sets.db, 'share_type_get_by_name_or_id', 

707 mock.Mock( 

708 return_value={'id': 'fake_st_id', 'name': 'fake_st_name'})) 

709 

710 result = self.controller.delete(req, self.project_id) 

711 

712 self.assertEqual(utils.IsAMatcher(webob.response.Response), result) 

713 self.assertTrue(hasattr(result, 'status_code')) 

714 self.assertEqual(202, result.status_code) 

715 mock_delete_st_quotas.assert_called_once_with( 

716 req.environ['manila.context'], self.project_id, 'fake_st_id') 

717 quota_sets.QUOTAS.destroy_all_by_project.assert_not_called() 

718 quota_sets.QUOTAS.destroy_all_by_project_and_user.assert_not_called() 

719 self.mock_policy_check.assert_called_once_with( 

720 req.environ['manila.context'], self.resource_name, 'delete') 

721 quota_sets.db.share_type_get_by_name_or_id.assert_called_once_with( 

722 req.environ['manila.context'], 

723 req.environ['QUERY_STRING'].split('=')[-1]) 

724 

725 def test_delete_share_type_quota_using_too_old_microversion(self): 

726 self.mock_object( 

727 quota_sets.db, 'share_type_get_by_name_or_id', 

728 mock.Mock( 

729 return_value={'id': 'fake_st_id', 'name': 'fake_st_name'})) 

730 req = self._get_share_type_request_object('2.38') 

731 

732 self.assertRaises( 

733 webob.exc.HTTPBadRequest, 

734 self.controller.delete, 

735 req, self.project_id) 

736 

737 quota_sets.db.share_type_get_by_name_or_id.assert_not_called() 

738 

739 def test_delete_not_authorized(self): 

740 req = _get_request(False, False) 

741 self.assertRaises( 

742 webob.exc.HTTPForbidden, 

743 self.controller.delete, 

744 req, self.project_id) 

745 self.mock_policy_check.assert_called_once_with( 

746 req.environ['manila.context'], self.resource_name, 'delete') 

747 

748 @ddt.data( 

749 ('os-quota-sets', '2.7', quota_sets.QuotaSetsControllerLegacy), 

750 ('quota-sets', '2.6', quota_sets.QuotaSetsController), 

751 ('quota-sets', '2.0', quota_sets.QuotaSetsController), 

752 ) 

753 @ddt.unpack 

754 def test_api_not_found(self, url, version, controller): 

755 req = fakes.HTTPRequest.blank('/fooproject/%s' % url, version=version) 

756 for method_name in ('show', 'defaults', 'delete'): 

757 self.assertRaises( 

758 exception.VersionNotFoundForAPIMethod, 

759 getattr(controller(), method_name), 

760 req, self.project_id) 

761 

762 @ddt.data( 

763 ('os-quota-sets', '2.7', quota_sets.QuotaSetsControllerLegacy), 

764 ('quota-sets', '2.6', quota_sets.QuotaSetsController), 

765 ('quota-sets', '2.0', quota_sets.QuotaSetsController), 

766 ) 

767 @ddt.unpack 

768 def test_update_api_not_found(self, url, version, controller): 

769 req = fakes.HTTPRequest.blank('/fooproject/%s' % url, version=version) 

770 self.assertRaises( 

771 exception.VersionNotFoundForAPIMethod, 

772 controller().update, 

773 req, self.project_id) 

774 

775 def test_update_without_quota(self): 

776 body = { 

777 'quota_set': { 

778 'tenant_id': self.project_id, 

779 } 

780 } 

781 req = _get_request(True, False) 

782 

783 self.assertRaises( 

784 webob.exc.HTTPBadRequest, 

785 self.controller.update, 

786 req, self.project_id, body=body) 

787 self.mock_policy_check.assert_called_once_with( 

788 req.environ['manila.context'], self.resource_name, 'update')