Coverage for manila/tests/test_quota.py: 99%

346 statements  

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

1# Copyright 2017 Mirantis 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 

16from unittest import mock 

17 

18import ddt 

19from oslo_config import cfg 

20 

21from manila import exception 

22from manila import quota 

23from manila import test 

24 

25CONF = cfg.CONF 

26 

27 

28@ddt.ddt 

29class DbQuotaDriverTestCase(test.TestCase): 

30 

31 def setUp(self): 

32 super(DbQuotaDriverTestCase, self).setUp() 

33 self.project_id = 'fake_project_id' 

34 self.user_id = 'fake_user_id' 

35 self.share_type_id = 'fake_share_type_id' 

36 self.ctxt = type( 

37 'FakeContext', (object, ), 

38 {'project_id': self.project_id, 'user_id': self.user_id, 

39 'quota_class': 'fake_quota_class', 'elevated': mock.Mock()}) 

40 self.driver = quota.DbQuotaDriver() 

41 self.reservations = ['foo', 'bar'] 

42 self.resources = {k: quota.BaseResource(k) for k in ('foo', 'bar')} 

43 

44 def test_get_by_class(self): 

45 self.mock_object(quota.db, 'quota_class_get') 

46 

47 result = self.driver.get_by_class( 

48 self.ctxt, 'fake_quota_class', 'fake_res') 

49 

50 self.assertEqual(quota.db.quota_class_get.return_value, result) 

51 quota.db.quota_class_get.assert_called_once_with( 

52 self.ctxt, 'fake_quota_class', 'fake_res') 

53 

54 def test_get_defaults(self): 

55 self.mock_object( 

56 quota.db, 'quota_class_get_default', 

57 mock.Mock(return_value={'foo': 13})) 

58 

59 result = self.driver.get_defaults(self.ctxt, self.resources) 

60 

61 self.assertEqual( 

62 {'foo': 13, 'bar': self.resources['bar'].default}, result) 

63 quota.db.quota_class_get_default.assert_called_once_with(self.ctxt) 

64 

65 @ddt.data(True, False) 

66 def test_get_class_quotas(self, defaults): 

67 self.mock_object( 

68 quota.db, 'quota_class_get_all_by_name', 

69 mock.Mock(return_value={'foo': 13})) 

70 

71 result = self.driver.get_class_quotas( 

72 self.ctxt, self.resources, 'fake_quota_class', defaults) 

73 

74 expected = {'foo': 13, 'bar': -1} if defaults else {'foo': 13} 

75 self.assertEqual(expected, result) 

76 quota.db.quota_class_get_all_by_name.assert_called_once_with( 

77 self.ctxt, 'fake_quota_class') 

78 

79 @ddt.data( 

80 ('fake_project_id', {'foo': 20}, None, True, None, True), 

81 ('fake_different_project_id', {'bar': 40}, 'fake_quota_class', True, 

82 {'foo': {'in_use': 3, 'reserved': 2}}, False), 

83 ('fake_project_id', {'bar': 30}, 'fake_quota_class', True, None, False) 

84 ) 

85 @ddt.unpack 

86 def test__process_quotas(self, project_id, quotas, quota_class, defaults, 

87 usages, remains): 

88 self.mock_object(quota.db, 'quota_get_all', mock.Mock(return_value=[])) 

89 self.mock_object(quota.db, 'quota_class_get_all_by_name') 

90 self.mock_object( 

91 self.driver, 'get_defaults', 

92 mock.Mock(return_value={'foo': 11, 'bar': 12})) 

93 self.mock_object( 

94 quota.db, 'quota_get_all', 

95 mock.Mock(return_value=[])) 

96 

97 result = self.driver._process_quotas( 

98 self.ctxt, self.resources, project_id, quotas, quota_class, 

99 defaults, usages, remains) 

100 

101 expected = {key: {'limit': mock.ANY} for key in ('foo', 'bar')} 

102 if usages: 

103 for res in self.resources.values(): 

104 usage = usages.get(res.name, {}) 

105 expected[res.name].update( 

106 in_use=usage.get('in_use', 0), 

107 reserved=usage.get('reserved', 0)) 

108 if remains: 

109 quota.db.quota_get_all.assert_called_once_with( 

110 self.ctxt, project_id) 

111 for res in self.resources.values(): 

112 expected[res.name]['remains'] = mock.ANY 

113 else: 

114 self.assertEqual(0, quota.db.quota_get_all.call_count) 

115 

116 self.assertEqual(expected, result) 

117 if quota_class or project_id == self.ctxt.project_id: 117 ↛ 121line 117 didn't jump to line 121 because the condition on line 117 was always true

118 quota.db.quota_class_get_all_by_name.assert_called_once_with( 

119 self.ctxt, quota_class or self.ctxt.quota_class) 

120 else: 

121 self.assertEqual( 

122 0, quota.db.quota_class_get_all_by_name.call_count) 

123 

124 @ddt.data( 

125 ('fake_quota_class', True, None, 'fake_remains'), 

126 (None, False, 'fake_usages', False), 

127 ) 

128 @ddt.unpack 

129 def test_get_project_quotas(self, quota_class, defaults, usages, remains): 

130 self.mock_object(quota.db, 'quota_get_all_by_project') 

131 self.mock_object(quota.db, 'quota_usage_get_all_by_project') 

132 self.mock_object(self.driver, '_process_quotas') 

133 

134 result = self.driver.get_project_quotas( 

135 self.ctxt, self.resources, self.project_id, 

136 quota_class, defaults, usages, remains) 

137 

138 self.assertEqual( 

139 result, self.driver._process_quotas.return_value) 

140 project_usages = None 

141 if usages: 

142 project_usages = ( 

143 quota.db.quota_usage_get_all_by_project.return_value) 

144 self.driver._process_quotas.assert_called_once_with( 

145 self.ctxt, self.resources, self.project_id, 

146 quota.db.quota_get_all_by_project.return_value, 

147 quota_class, defaults=defaults, usages=project_usages, 

148 remains=remains) 

149 quota.db.quota_get_all_by_project.assert_called_once_with( 

150 self.ctxt, self.project_id) 

151 if usages: 

152 quota.db.quota_usage_get_all_by_project.assert_called_once_with( 

153 self.ctxt, self.project_id) 

154 else: 

155 self.assertEqual( 

156 0, quota.db.quota_usage_get_all_by_project.call_count) 

157 

158 @ddt.data( 

159 (None, True, True), 

160 ('fake_quota_class', False, True), 

161 ('fake_quota_class', True, False), 

162 ) 

163 @ddt.unpack 

164 def test_get_user_quotas(self, quota_class, defaults, usages): 

165 project_quotas = {'fake_resource': 5} 

166 self.mock_object( 

167 quota.db, 'quota_get_all_by_project', 

168 mock.Mock(return_value=project_quotas)) 

169 self.mock_object( 

170 quota.db, 'quota_get_all_by_project_and_user', 

171 mock.Mock(return_value={'fake_user_defined_resource': 14})) 

172 mock_user_usages = self.mock_object( 

173 quota.db, 'quota_usage_get_all_by_project_and_user') 

174 self.mock_object(self.driver, '_process_quotas') 

175 

176 result = self.driver.get_user_quotas( 

177 self.ctxt, self.resources, self.project_id, self.user_id, 

178 quota_class, defaults, usages) 

179 

180 self.assertEqual( 

181 self.driver._process_quotas.return_value, result) 

182 quota.db.quota_get_all_by_project.assert_called_once_with( 

183 self.ctxt, self.project_id) 

184 quota.db.quota_get_all_by_project_and_user.assert_called_once_with( 

185 self.ctxt, self.project_id, self.user_id) 

186 if usages: 

187 user_usages = mock_user_usages.return_value 

188 mock_user_usages.assert_called_once_with( 

189 self.ctxt, self.project_id, self.user_id) 

190 else: 

191 user_usages = None 

192 self.assertEqual(0, mock_user_usages.call_count) 

193 expected_user_quotas = {'fake_user_defined_resource': 14} 

194 expected_user_quotas.update(project_quotas) 

195 self.driver._process_quotas.assert_called_once_with( 

196 self.ctxt, self.resources, self.project_id, expected_user_quotas, 

197 quota_class, defaults=defaults, usages=user_usages) 

198 

199 @ddt.data( 

200 (None, True, True), 

201 ('fake_quota_class', False, True), 

202 ('fake_quota_class', True, False), 

203 ) 

204 @ddt.unpack 

205 def test_get_share_type_quotas(self, quota_class, defaults, usages): 

206 project_quotas = {'fake_resource': 5} 

207 self.mock_object( 

208 quota.db, 'quota_get_all_by_project', 

209 mock.Mock(return_value=project_quotas)) 

210 mock_st_quotas = self.mock_object( 

211 quota.db, 'quota_get_all_by_project_and_share_type', 

212 mock.Mock(return_value={'fake_st_defined_resource': 14})) 

213 mock_st_usages = self.mock_object( 

214 quota.db, 'quota_usage_get_all_by_project_and_share_type') 

215 self.mock_object(self.driver, '_process_quotas') 

216 

217 result = self.driver.get_share_type_quotas( 

218 self.ctxt, self.resources, self.project_id, self.share_type_id, 

219 quota_class, defaults, usages) 

220 

221 self.assertEqual( 

222 self.driver._process_quotas.return_value, result) 

223 quota.db.quota_get_all_by_project.assert_called_once_with( 

224 self.ctxt, self.project_id) 

225 mock_st_quotas.assert_called_once_with( 

226 self.ctxt, self.project_id, self.share_type_id) 

227 if usages: 

228 st_usages = mock_st_usages.return_value 

229 mock_st_usages.assert_called_once_with( 

230 self.ctxt, self.project_id, self.share_type_id) 

231 else: 

232 st_usages = None 

233 self.assertEqual(0, mock_st_usages.call_count) 

234 expected_st_quotas = {'fake_st_defined_resource': 14} 

235 expected_st_quotas.update(project_quotas) 

236 self.driver._process_quotas.assert_called_once_with( 

237 self.ctxt, self.resources, self.project_id, expected_st_quotas, 

238 quota_class, defaults=defaults, usages=st_usages) 

239 

240 @ddt.data((None, None), (None, 'foo_st_id'), ('foo_user_id', None)) 

241 @ddt.unpack 

242 def test_get_settable_quotas(self, user_id, st_id): 

243 project_quotas = {'fake': { 

244 'limit': 13, 'in_use': 7, 'reserved': 5, 'remains': 1, 

245 }} 

246 user_or_st_quotas = {'fake': { 

247 'limit': 11, 'in_use': 5, 'reserved': 2, 

248 }} 

249 self.mock_object( 

250 self.driver, 'get_project_quotas', 

251 mock.Mock(return_value=project_quotas)) 

252 self.mock_object( 

253 self.driver, 'get_user_quotas', 

254 mock.Mock(return_value=user_or_st_quotas)) 

255 self.mock_object( 

256 self.driver, 'get_share_type_quotas', 

257 mock.Mock(return_value=user_or_st_quotas)) 

258 

259 result = self.driver.get_settable_quotas( 

260 self.ctxt, self.resources, self.project_id, user_id, st_id) 

261 

262 if user_id: 

263 self.driver.get_user_quotas.assert_called_once_with( 

264 self.ctxt, self.resources, self.project_id, user_id) 

265 else: 

266 self.assertEqual(0, self.driver.get_user_quotas.call_count) 

267 if st_id: 

268 self.driver.get_share_type_quotas.assert_called_once_with( 

269 self.ctxt, self.resources, self.project_id, st_id) 

270 else: 

271 self.assertEqual(0, self.driver.get_share_type_quotas.call_count) 

272 if user_id or st_id: 

273 expected_settable_quotas = {'fake': {'maximum': 13, 'minimum': 7}} 

274 else: 

275 expected_settable_quotas = {'fake': {'maximum': -1, 'minimum': 12}} 

276 self.driver.get_project_quotas.assert_called_once_with( 

277 self.ctxt, self.resources, self.project_id, remains=True) 

278 self.assertEqual(expected_settable_quotas, result) 

279 

280 @ddt.data((None, None), (None, 'fake_st_id'), ('fake_user_id', None)) 

281 @ddt.unpack 

282 def test__get_quotas(self, user_id, st_id): 

283 quotas = {'foo': {'limit': 5}, 'bar': {'limit': 13}} 

284 self.mock_object( 

285 self.driver, 'get_project_quotas', mock.Mock(return_value=quotas)) 

286 self.mock_object( 

287 self.driver, 'get_user_quotas', mock.Mock(return_value=quotas)) 

288 self.mock_object( 

289 self.driver, 'get_share_type_quotas', 

290 mock.Mock(return_value=quotas)) 

291 

292 result = self.driver._get_quotas( 

293 self.ctxt, self.resources, ('foo', 'bar'), False, 

294 self.project_id, user_id, st_id) 

295 

296 expected = {k: v['limit'] for k, v in quotas.items()} 

297 self.assertEqual(expected, result) 

298 sub_resources = {k: v for k, v in self.resources.items()} 

299 if user_id: 

300 self.driver.get_user_quotas.assert_called_once_with( 

301 self.ctxt, sub_resources, self.project_id, user_id, 

302 self.ctxt.quota_class, usages=False) 

303 self.assertEqual(0, self.driver.get_project_quotas.call_count) 

304 self.assertEqual(0, self.driver.get_share_type_quotas.call_count) 

305 elif st_id: 

306 self.driver.get_share_type_quotas.assert_called_once_with( 

307 self.ctxt, sub_resources, self.project_id, st_id, 

308 self.ctxt.quota_class, usages=False) 

309 self.assertEqual(0, self.driver.get_project_quotas.call_count) 

310 self.assertEqual(0, self.driver.get_user_quotas.call_count) 

311 else: 

312 self.driver.get_project_quotas.assert_called_once_with( 

313 self.ctxt, sub_resources, self.project_id, 

314 self.ctxt.quota_class, usages=False) 

315 self.assertEqual(0, self.driver.get_user_quotas.call_count) 

316 self.assertEqual(0, self.driver.get_share_type_quotas.call_count) 

317 

318 def test__get_quotas_unknown(self): 

319 quotas = {'foo': {'limit': 5}, 'bar': {'limit': 13}} 

320 self.mock_object( 

321 self.driver, 'get_project_quotas', mock.Mock(return_value=quotas)) 

322 self.mock_object( 

323 self.driver, 'get_user_quotas', mock.Mock(return_value=quotas)) 

324 self.mock_object( 

325 self.driver, 'get_share_type_quotas', 

326 mock.Mock(return_value=quotas)) 

327 

328 self.assertRaises( 

329 exception.QuotaResourceUnknown, 

330 self.driver._get_quotas, 

331 self.ctxt, self.resources, ['foo', 'bar'], True, 

332 self.project_id, self.user_id, self.share_type_id) 

333 

334 self.assertEqual(0, self.driver.get_project_quotas.call_count) 

335 self.assertEqual(0, self.driver.get_user_quotas.call_count) 

336 self.assertEqual(0, self.driver.get_share_type_quotas.call_count) 

337 

338 @ddt.data( 

339 {}, {'project_id': 'fake_project'}, {'user_id': 'fake_user'}, 

340 {'share_type_id': 'fake_share_type_id'}, 

341 ) 

342 def test_reserve(self, kwargs): 

343 self.mock_object(quota.db, 'quota_reserve') 

344 deltas = {'delta1': 1, 'delta2': 2} 

345 quotas, user_quotas, st_quotas = 'fake1', 'fake2', 'fake3' 

346 self.mock_object( 

347 self.driver, '_get_quotas', mock.Mock( 

348 side_effect=[quotas, user_quotas, st_quotas])) 

349 

350 result = self.driver.reserve( 

351 self.ctxt, self.resources, deltas, None, **kwargs) 

352 

353 expected_kwargs = { 

354 'project_id': self.ctxt.project_id, 

355 'user_id': self.ctxt.user_id, 

356 'share_type_id': None, 

357 'overquota_allowed': False 

358 } 

359 expected_kwargs.update(kwargs) 

360 st_quotas = st_quotas if kwargs.get('share_type_id') else {} 

361 self.assertEqual(quota.db.quota_reserve.return_value, result) 

362 quota.db.quota_reserve.assert_called_once_with( 

363 self.ctxt, self.resources, quotas, user_quotas, st_quotas, 

364 deltas, mock.ANY, CONF.quota.until_refresh, CONF.quota.max_age, 

365 **expected_kwargs) 

366 self.assertEqual( 

367 3 if kwargs.get('share_type_id') else 2, 

368 self.driver._get_quotas.call_count) 

369 

370 def test_reserve_wrong_expire(self): 

371 self.assertRaises( 

372 exception.InvalidReservationExpiration, 

373 self.driver.reserve, 

374 self.ctxt, self.resources, 'fake_deltas', 'fake_expire') 

375 

376 def test_commit(self): 

377 self.mock_object(quota.db, 'reservation_commit') 

378 

379 result = self.driver.commit( 

380 self.ctxt, self.reservations, self.project_id, self.user_id, 

381 self.share_type_id) 

382 

383 self.assertIsNone(result) 

384 quota.db.reservation_commit.assert_called_once_with( 

385 self.ctxt, self.reservations, project_id=self.project_id, 

386 user_id=self.user_id, share_type_id=self.share_type_id) 

387 

388 @ddt.data( 

389 (None, None), 

390 ('fake_project_id', 'fake_user_id'), 

391 ) 

392 @ddt.unpack 

393 def test_rollback(self, project_id, user_id): 

394 self.mock_object(quota.db, 'reservation_rollback') 

395 

396 result = self.driver.rollback( 

397 self.ctxt, self.reservations, project_id, user_id, 

398 self.share_type_id) 

399 

400 expected_project_id = project_id or self.ctxt.project_id 

401 expected_user_id = user_id or self.ctxt.user_id 

402 self.assertIsNone(result) 

403 quota.db.reservation_rollback.assert_called_once_with( 

404 self.ctxt, self.reservations, project_id=expected_project_id, 

405 user_id=expected_user_id, share_type_id=self.share_type_id) 

406 

407 def test_usage_reset(self): 

408 self.mock_object( 

409 quota.db, 'quota_usage_update', 

410 mock.Mock(side_effect=[ 

411 'foo', 

412 exception.QuotaUsageNotFound(project_id=self.project_id)])) 

413 

414 result = self.driver.usage_reset(self.ctxt, ['foo', 'bar']) 

415 

416 self.assertIsNone(result) 

417 quota.db.quota_usage_update.assert_has_calls([ 

418 mock.call( 

419 self.ctxt.elevated.return_value, self.ctxt.project_id, 

420 self.ctxt.user_id, res, in_use=-1) 

421 for res in ('foo', 'bar') 

422 ]) 

423 

424 def test_destroy_all_by_project(self): 

425 self.mock_object(quota.db, 'quota_destroy_all_by_project') 

426 

427 result = self.driver.destroy_all_by_project(self.ctxt, self.project_id) 

428 

429 self.assertIsNone(result) 

430 quota.db.quota_destroy_all_by_project.assert_called_once_with( 

431 self.ctxt, self.project_id) 

432 

433 def test_destroy_all_by_project_and_user(self): 

434 self.mock_object(quota.db, 'quota_destroy_all_by_project_and_user') 

435 

436 result = self.driver.destroy_all_by_project_and_user( 

437 self.ctxt, self.project_id, self.user_id) 

438 

439 self.assertIsNone(result) 

440 quota.db.quota_destroy_all_by_project_and_user.assert_called_once_with( 

441 self.ctxt, self.project_id, self.user_id) 

442 

443 def test_destroy_all_by_project_and_share_type(self): 

444 mock_destroy_all = self.mock_object( 

445 quota.db, 'quota_destroy_all_by_share_type') 

446 

447 result = self.driver.destroy_all_by_project_and_share_type( 

448 self.ctxt, self.project_id, self.share_type_id) 

449 

450 self.assertIsNone(result) 

451 mock_destroy_all.assert_called_once_with( 

452 self.ctxt, self.share_type_id, project_id=self.project_id) 

453 

454 def test_expire(self): 

455 self.mock_object(quota.db, 'reservation_expire') 

456 

457 result = self.driver.expire(self.ctxt) 

458 

459 self.assertIsNone(result) 

460 quota.db.reservation_expire.assert_called_once_with(self.ctxt) 

461 

462 

463@ddt.ddt 

464class QuotaEngineTestCase(test.TestCase): 

465 

466 def setUp(self): 

467 super(QuotaEngineTestCase, self).setUp() 

468 self.ctxt = 'fake_context' 

469 self.mock_class('manila.quota.DbQuotaDriver') 

470 self.engine = quota.QuotaEngine() 

471 self.driver = self.engine._driver 

472 self.resources = [quota.BaseResource('foo'), quota.BaseResource('bar')] 

473 self.project_id = 'fake_project_id' 

474 self.user_id = 'fake_user_id' 

475 self.share_type_id = 'fake_share_type_id' 

476 self.quota_class = 'fake_quota_class' 

477 

478 def test_register_resource(self): 

479 self.assertNotIn(self.resources[0].name, self.engine) 

480 self.engine.register_resource(self.resources[0]) 

481 self.assertIn(self.resources[0].name, self.engine) 

482 

483 def test_register_resources(self): 

484 for res in self.resources: 

485 self.assertNotIn(res.name, self.engine) 

486 self.engine.register_resources(self.resources) 

487 for res in self.resources: 

488 self.assertIn(res.name, self.engine) 

489 

490 def test_get_by_class(self): 

491 result = self.engine.get_by_class( 

492 self.ctxt, self.quota_class, 'fake_res') 

493 

494 self.assertEqual(result, self.driver.get_by_class.return_value) 

495 self.driver.get_by_class.assert_called_once_with( 

496 self.ctxt, self.quota_class, 'fake_res') 

497 

498 def test_get_defaults(self): 

499 result = self.engine.get_defaults(self.ctxt) 

500 

501 self.assertEqual(result, self.driver.get_defaults.return_value) 

502 self.driver.get_defaults.assert_called_once_with( 

503 self.ctxt, self.engine._resources) 

504 

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

506 def test_get_class_quotas(self, defaults): 

507 kwargs = {} 

508 if defaults is not None: 

509 kwargs['defaults'] = defaults 

510 

511 result = self.engine.get_class_quotas( 

512 self.ctxt, self.quota_class, **kwargs) 

513 

514 self.assertEqual(result, self.driver.get_class_quotas.return_value) 

515 kwargs['defaults'] = defaults if defaults is not None else True 

516 self.driver.get_class_quotas.assert_called_once_with( 

517 self.ctxt, self.engine._resources, self.quota_class, **kwargs) 

518 

519 @ddt.data( 

520 {}, 

521 {'quota_class': 'foo'}, 

522 {'defaults': False}, 

523 {'usages': False}, 

524 ) 

525 def test_get_user_quotas(self, kwargs): 

526 expected_kwargs = { 

527 'quota_class': None, 

528 'defaults': True, 

529 'usages': True, 

530 } 

531 expected_kwargs.update(kwargs) 

532 

533 result = self.engine.get_user_quotas( 

534 self.ctxt, self.project_id, self.user_id, **kwargs) 

535 

536 self.assertEqual(result, self.driver.get_user_quotas.return_value) 

537 self.driver.get_user_quotas.assert_called_once_with( 

538 self.ctxt, self.engine._resources, 

539 self.project_id, self.user_id, **expected_kwargs) 

540 

541 @ddt.data( 

542 {}, 

543 {'quota_class': 'foo'}, 

544 {'defaults': False}, 

545 {'usages': False}, 

546 ) 

547 def test_get_share_type_quotas(self, kwargs): 

548 expected_kwargs = { 

549 'quota_class': None, 

550 'defaults': True, 

551 'usages': True, 

552 } 

553 expected_kwargs.update(kwargs) 

554 

555 result = self.engine.get_share_type_quotas( 

556 self.ctxt, self.project_id, self.share_type_id, **kwargs) 

557 

558 self.assertEqual( 

559 result, self.driver.get_share_type_quotas.return_value) 

560 self.driver.get_share_type_quotas.assert_called_once_with( 

561 self.ctxt, self.engine._resources, 

562 self.project_id, self.share_type_id, **expected_kwargs) 

563 

564 @ddt.data( 

565 {}, 

566 {'quota_class': 'foo'}, 

567 {'defaults': False}, 

568 {'usages': False}, 

569 {'remains': True}, 

570 ) 

571 def test_get_project_quotas(self, kwargs): 

572 expected_kwargs = { 

573 'quota_class': None, 

574 'defaults': True, 

575 'usages': True, 

576 'remains': False, 

577 } 

578 expected_kwargs.update(kwargs) 

579 

580 result = self.engine.get_project_quotas( 

581 self.ctxt, self.project_id, **kwargs) 

582 

583 self.assertEqual(result, self.driver.get_project_quotas.return_value) 

584 self.driver.get_project_quotas.assert_called_once_with( 

585 self.ctxt, self.engine._resources, 

586 self.project_id, **expected_kwargs) 

587 

588 @ddt.data( 

589 {}, 

590 {'user_id': 'fake_user_id'}, 

591 {'share_type_id': 'fake_share_type_id'}, 

592 ) 

593 def test_get_settable_quotas(self, kwargs): 

594 expected_kwargs = {'user_id': None, 'share_type_id': None} 

595 expected_kwargs.update(kwargs) 

596 

597 result = self.engine.get_settable_quotas( 

598 self.ctxt, self.project_id, **kwargs) 

599 

600 self.assertEqual(result, self.driver.get_settable_quotas.return_value) 

601 self.driver.get_settable_quotas.assert_called_once_with( 

602 self.ctxt, self.engine._resources, 

603 self.project_id, **expected_kwargs) 

604 

605 def test_count(self): 

606 mock_count = mock.Mock() 

607 resource = quota.CountableResource('FakeCountableResource', mock_count) 

608 self.engine.register_resource(resource) 

609 

610 result = self.engine.count(self.ctxt, resource.name) 

611 

612 self.assertEqual(mock_count.return_value, result) 

613 

614 def test_count_unknown_resource(self): 

615 self.assertRaises( 

616 exception.QuotaResourceUnknown, 

617 self.engine.count, 

618 self.ctxt, 'nonexistent_resource', 'foo_arg', foo='kwarg') 

619 

620 def test_reserve(self): 

621 result = self.engine.reserve( 

622 self.ctxt, 'fake_expire', self.project_id, self.user_id, 

623 self.share_type_id, delta1=1, delta2=2) 

624 

625 self.assertEqual(self.driver.reserve.return_value, result) 

626 self.driver.reserve.assert_called_once_with( 

627 self.ctxt, self.engine._resources, {'delta1': 1, 'delta2': 2}, 

628 expire='fake_expire', project_id=self.project_id, 

629 user_id=self.user_id, share_type_id=self.share_type_id, 

630 overquota_allowed=False) 

631 

632 @ddt.data(Exception('FakeException'), [None]) 

633 def test_commit(self, side_effect): 

634 fake_reservations = ['foo', 'bar'] 

635 self.driver.commit.side_effect = side_effect 

636 self.mock_object(quota.LOG, 'exception') 

637 

638 result = self.engine.commit( 

639 self.ctxt, fake_reservations, 'fake_project_id', 

640 'fake_user_id', 'fake_share_type_id') 

641 

642 self.assertIsNone(result) 

643 self.driver.commit.assert_called_once_with( 

644 self.ctxt, fake_reservations, project_id='fake_project_id', 

645 user_id='fake_user_id', share_type_id='fake_share_type_id') 

646 if side_effect == [None]: 

647 self.assertEqual(0, quota.LOG.exception.call_count) 

648 else: 

649 quota.LOG.exception.assert_called_once_with( 

650 mock.ANY, fake_reservations) 

651 

652 @ddt.data(Exception('FakeException'), [None]) 

653 def test_rollback(self, side_effect): 

654 fake_reservations = ['foo', 'bar'] 

655 self.driver.rollback.side_effect = side_effect 

656 self.mock_object(quota.LOG, 'exception') 

657 

658 result = self.engine.rollback( 

659 self.ctxt, fake_reservations, 'fake_project_id', 

660 'fake_user_id', 'fake_share_type_id') 

661 

662 self.assertIsNone(result) 

663 self.driver.rollback.assert_called_once_with( 

664 self.ctxt, fake_reservations, project_id='fake_project_id', 

665 user_id='fake_user_id', share_type_id='fake_share_type_id') 

666 if side_effect == [None]: 

667 self.assertEqual(0, quota.LOG.exception.call_count) 

668 else: 

669 quota.LOG.exception.assert_called_once_with( 

670 mock.ANY, fake_reservations) 

671 

672 def test_usage_reset(self): 

673 result = self.engine.usage_reset(self.ctxt, 'fake_resources') 

674 

675 self.assertIsNone(result) 

676 self.driver.usage_reset.assert_called_once_with( 

677 self.ctxt, 'fake_resources') 

678 

679 def test_destroy_all_by_project_and_user(self): 

680 result = self.engine.destroy_all_by_project_and_user( 

681 self.ctxt, 'fake_project_id', 'fake_user_id') 

682 

683 self.assertIsNone(result) 

684 self.driver.destroy_all_by_project_and_user.assert_called_once_with( 

685 self.ctxt, 'fake_project_id', 'fake_user_id') 

686 

687 def test_destroy_all_by_project_and_share_type(self): 

688 result = self.engine.destroy_all_by_project_and_share_type( 

689 self.ctxt, 'fake_project_id', 'fake_st_id') 

690 

691 self.assertIsNone(result) 

692 mock_destroy_all_by_project_and_share_type = ( 

693 self.driver.destroy_all_by_project_and_share_type) 

694 mock_destroy_all_by_project_and_share_type.assert_called_once_with( 

695 self.ctxt, 'fake_project_id', 'fake_st_id') 

696 

697 def test_destroy_all_by_project(self): 

698 result = self.engine.destroy_all_by_project( 

699 self.ctxt, 'fake_project_id') 

700 

701 self.assertIsNone(result) 

702 self.driver.destroy_all_by_project.assert_called_once_with( 

703 self.ctxt, 'fake_project_id') 

704 

705 def test_expire(self): 

706 result = self.engine.expire(self.ctxt) 

707 

708 self.assertIsNone(result) 

709 self.driver.expire.assert_called_once_with(self.ctxt) 

710 

711 def test_resources(self): 

712 self.engine.register_resources(self.resources) 

713 self.assertEqual(['bar', 'foo'], self.engine.resources) 

714 

715 def test_current_common_resources(self): 

716 self.assertEqual( 

717 sorted(['gigabytes', 'per_share_gigabytes', 'replica_gigabytes', 

718 'share_group_snapshots', 'share_groups', 'share_networks', 

719 'share_replicas', 'shares', 'snapshot_gigabytes', 

720 'snapshots', 'backups', 'backup_gigabytes', 

721 'encryption_keys']), 

722 quota.QUOTAS.resources)