Coverage for manila/tests/db/sqlalchemy/test_api.py: 99%

2831 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) 2014 NetApp, Inc. 

3# Copyright (c) 2015 Rushil Chugh 

4# All Rights Reserved. 

5# 

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

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

8# a copy of the License at 

9# 

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

11# 

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

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

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

15# License for the specific language governing permissions and limitations 

16# under the License. 

17 

18"""Testing of SQLAlchemy backend.""" 

19 

20import copy 

21import datetime 

22import random 

23from unittest import mock 

24 

25import ddt 

26from oslo_db import exception as db_exception 

27from oslo_utils import timeutils 

28from oslo_utils import uuidutils 

29 

30from manila.common import constants 

31from manila import context 

32from manila.db.sqlalchemy import api as db_api 

33from manila.db.sqlalchemy import models 

34from manila import exception 

35from manila import quota 

36from manila import test 

37from manila.tests import db_utils 

38 

39QUOTAS = quota.QUOTAS 

40 

41security_service_dict = { 

42 'id': 'fake id', 

43 'project_id': 'fake project', 

44 'type': 'ldap', 

45 'dns_ip': 'fake dns', 

46 'server': 'fake ldap server', 

47 'domain': 'fake ldap domain', 

48 'default_ad_site': 'fake ldap default_ad_site', 

49 'ou': 'fake ldap ou', 

50 'user': 'fake user', 

51 'password': 'fake password', 

52 'name': 'whatever', 

53 'description': 'nevermind', 

54} 

55 

56 

57class BaseDatabaseAPITestCase(test.TestCase): 

58 def _check_fields(self, expected, actual): 

59 for key in expected: 

60 self.assertEqual(expected[key], actual[key]) 

61 

62 

63@ddt.ddt 

64class GenericDatabaseAPITestCase(test.TestCase): 

65 

66 def setUp(self): 

67 """Run before each test.""" 

68 super(GenericDatabaseAPITestCase, self).setUp() 

69 self.ctxt = context.get_admin_context() 

70 

71 @ddt.unpack 

72 @ddt.data( 

73 {'values': {'test': 'fake'}, 'call_count': 1}, 

74 {'values': {'test': 'fake', 'id': 'fake'}, 'call_count': 0}, 

75 {'values': {'test': 'fake', 'fooid': 'fake'}, 'call_count': 1}, 

76 {'values': {'test': 'fake', 'idfoo': 'fake'}, 'call_count': 1}, 

77 ) 

78 def test_ensure_model_values_has_id(self, values, call_count): 

79 self.mock_object(uuidutils, 'generate_uuid') 

80 

81 db_api.ensure_model_dict_has_id(values) 

82 

83 self.assertEqual(call_count, uuidutils.generate_uuid.call_count) 

84 self.assertIn('id', values) 

85 

86 def test_custom_query(self): 

87 share = db_utils.create_share() 

88 share_access = db_utils.create_access(share_id=share['id']) 

89 

90 db_api.share_instance_access_delete( 

91 self.ctxt, share_access.instance_mappings[0].id) 

92 self.assertRaises(exception.NotFound, db_api.share_access_get, 

93 self.ctxt, share_access.id) 

94 

95 

96@ddt.ddt 

97class ShareAccessDatabaseAPITestCase(test.TestCase): 

98 

99 def setUp(self): 

100 """Run before each test.""" 

101 super(ShareAccessDatabaseAPITestCase, self).setUp() 

102 self.ctxt = context.get_admin_context() 

103 

104 @ddt.data(0, 3) 

105 def test_share_access_get_all_for_share(self, len_rules): 

106 share = db_utils.create_share() 

107 rules = [db_utils.create_access(share_id=share['id']) 

108 for i in range(0, len_rules)] 

109 rule_ids = [r['id'] for r in rules] 

110 

111 result = db_api.share_access_get_all_for_share(self.ctxt, share['id']) 

112 

113 self.assertEqual(len_rules, len(result)) 

114 result_ids = [r['id'] for r in result] 

115 self.assertEqual(rule_ids, result_ids) 

116 

117 def test_share_access_get_all_for_share_no_instance_mappings(self): 

118 share = db_utils.create_share() 

119 share_instance = share['instance'] 

120 rule = db_utils.create_access(share_id=share['id']) 

121 # Mark instance mapping soft deleted 

122 db_api.share_instance_access_update( 

123 self.ctxt, rule['id'], share_instance['id'], {'deleted': "True"}) 

124 

125 result = db_api.share_access_get_all_for_share(self.ctxt, share['id']) 

126 

127 self.assertEqual([], result) 

128 

129 def test_share_instance_access_update(self): 

130 share = db_utils.create_share() 

131 access = db_utils.create_access(share_id=share['id']) 

132 

133 instance_access_mapping = db_api.share_instance_access_get( 

134 self.ctxt, access['id'], share.instance['id']) 

135 self.assertEqual(constants.ACCESS_STATE_QUEUED_TO_APPLY, 

136 access['state']) 

137 self.assertIsNone(access['access_key']) 

138 

139 db_api.share_instance_access_update( 

140 self.ctxt, access['id'], share.instance['id'], 

141 {'state': constants.STATUS_ERROR, 'access_key': 'watson4heisman'}) 

142 

143 instance_access_mapping = db_api.share_instance_access_get( 

144 self.ctxt, access['id'], share.instance['id']) 

145 access = db_api.share_access_get(self.ctxt, access['id']) 

146 self.assertEqual(constants.STATUS_ERROR, 

147 instance_access_mapping['state']) 

148 self.assertEqual('watson4heisman', access['access_key']) 

149 self.assertIsNotNone(access['updated_at']) 

150 time_now = timeutils.utcnow() 

151 self.assertTrue(access['updated_at'] < time_now) 

152 self.assertTrue(instance_access_mapping['updated_at'] < time_now) 

153 

154 @ddt.data(True, False) 

155 def test_share_access_get_all_for_instance_with_share_access_data( 

156 self, with_share_access_data): 

157 share = db_utils.create_share() 

158 access_1 = db_utils.create_access(share_id=share['id']) 

159 access_2 = db_utils.create_access(share_id=share['id']) 

160 share_access_keys = ('access_to', 'access_type', 'access_level', 

161 'share_id') 

162 

163 rules = db_api.share_access_get_all_for_instance( 

164 self.ctxt, share.instance['id'], 

165 with_share_access_data=with_share_access_data) 

166 

167 share_access_keys_present = True if with_share_access_data else False 

168 actual_access_ids = [r['access_id'] for r in rules] 

169 self.assertIsInstance(actual_access_ids, list) 

170 expected = [access_1['id'], access_2['id']] 

171 self.assertEqual(len(expected), len(actual_access_ids)) 

172 for pool in expected: 

173 self.assertIn(pool, actual_access_ids) 

174 for rule in rules: 

175 for key in share_access_keys: 

176 self.assertEqual(share_access_keys_present, key in rule) 

177 self.assertIn('state', rule) 

178 

179 def test_share_access_get_all_for_instance_with_filters(self): 

180 share = db_utils.create_share() 

181 new_share_instance = db_utils.create_share_instance( 

182 share_id=share['id']) 

183 access_1 = db_utils.create_access(share_id=share['id']) 

184 access_2 = db_utils.create_access(share_id=share['id']) 

185 share_access_keys = ('access_to', 'access_type', 'access_level', 

186 'share_id') 

187 db_api.share_instance_access_update( 

188 self.ctxt, access_1['id'], new_share_instance['id'], 

189 {'state': constants.STATUS_ACTIVE}) 

190 

191 rules = db_api.share_access_get_all_for_instance( 

192 self.ctxt, new_share_instance['id'], 

193 filters={'state': constants.ACCESS_STATE_QUEUED_TO_APPLY}) 

194 

195 self.assertEqual(1, len(rules)) 

196 self.assertEqual(access_2['id'], rules[0]['access_id']) 

197 

198 for rule in rules: 

199 for key in share_access_keys: 

200 self.assertIn(key, rule) 

201 

202 def test_share_instance_access_delete(self): 

203 share = db_utils.create_share() 

204 access = db_utils.create_access(share_id=share['id'], 

205 metadata={'key1': 'v1'}) 

206 instance_access_mapping = db_api.share_instance_access_get( 

207 self.ctxt, access['id'], share.instance['id']) 

208 

209 db_api.share_instance_access_delete( 

210 self.ctxt, instance_access_mapping['id']) 

211 

212 rules = db_api.share_access_get_all_for_instance( 

213 self.ctxt, share.instance['id']) 

214 self.assertEqual([], rules) 

215 

216 self.assertRaises(exception.NotFound, db_api.share_instance_access_get, 

217 self.ctxt, access['id'], share['instance']['id']) 

218 

219 def test_share_instance_access_delete_with_locks(self): 

220 share = db_utils.create_share() 

221 access = db_utils.create_access(share_id=share['id'], 

222 metadata={'key1': 'v1'}) 

223 

224 # create a share and an access lock to ensure they'll be deleted 

225 access_lock = db_utils.create_lock(resource_id=access['id']) 

226 share_lock_reason = ( 

227 constants.SHARE_LOCKED_BY_ACCESS_LOCK_REASON % 

228 {'lock_id': access_lock['id']} 

229 ) 

230 share_lock = db_utils.create_lock( 

231 resource_id=share['id'], lock_reason=share_lock_reason 

232 ) 

233 

234 # create another share lock, to ensure it won't be deleted 

235 unrelated_share_lock = db_utils.create_lock(resource_id=share['id']) 

236 

237 instance_access_mapping = db_api.share_instance_access_get( 

238 self.ctxt, access['id'], share.instance['id']) 

239 

240 db_api.share_instance_access_delete( 

241 self.ctxt, instance_access_mapping['id']) 

242 

243 rules = db_api.share_access_get_all_for_instance( 

244 self.ctxt, share.instance['id']) 

245 unrelated_share_lock_get = ( 

246 db_api.resource_lock_get(self.ctxt, unrelated_share_lock['id']) 

247 ) 

248 self.assertEqual([], rules) 

249 self.assertEqual(unrelated_share_lock['id'], 

250 unrelated_share_lock_get['id']) 

251 

252 # ensure the access rules and the locks have been dropped 

253 self.assertRaises(exception.NotFound, db_api.share_instance_access_get, 

254 self.ctxt, access['id'], share['instance']['id']) 

255 self.assertRaises(exception.NotFound, db_api.resource_lock_get, 

256 self.ctxt, access_lock['id']) 

257 self.assertRaises(exception.NotFound, db_api.resource_lock_get, 

258 self.ctxt, share_lock['id']) 

259 

260 def test_one_share_with_two_share_instance_access_delete(self): 

261 metadata = {'key2': 'v2', 'key3': 'v3'} 

262 share = db_utils.create_share() 

263 instance = db_utils.create_share_instance(share_id=share['id']) 

264 access = db_utils.create_access(share_id=share['id'], 

265 metadata=metadata) 

266 instance_access_mapping1 = db_api.share_instance_access_get( 

267 self.ctxt, access['id'], share.instance['id']) 

268 instance_access_mapping2 = db_api.share_instance_access_get( 

269 self.ctxt, access['id'], instance['id']) 

270 self.assertEqual(instance_access_mapping1['access_id'], 

271 instance_access_mapping2['access_id']) 

272 db_api.share_instance_delete(self.ctxt, instance['id']) 

273 

274 get_accesses = db_api.share_access_get_all_for_share(self.ctxt, 

275 share['id']) 

276 self.assertEqual(1, len(get_accesses)) 

277 get_metadata = ( 

278 get_accesses[0].get('share_access_rules_metadata') or {}) 

279 get_metadata = {item['key']: item['value'] for item in get_metadata} 

280 self.assertEqual(metadata, get_metadata) 

281 self.assertEqual(access['id'], get_accesses[0]['id']) 

282 

283 db_api.share_instance_delete(self.ctxt, share['instance']['id']) 

284 self.assertRaises(exception.NotFound, 

285 db_api.share_instance_access_get, 

286 self.ctxt, access['id'], share['instance']['id']) 

287 

288 get_accesses = db_api.share_access_get_all_for_share(self.ctxt, 

289 share['id']) 

290 self.assertEqual(0, len(get_accesses)) 

291 

292 @ddt.data(True, False) 

293 def test_share_instance_access_get_with_share_access_data( 

294 self, with_share_access_data): 

295 share = db_utils.create_share() 

296 access = db_utils.create_access(share_id=share['id']) 

297 

298 instance_access = db_api.share_instance_access_get( 

299 self.ctxt, access['id'], share['instance']['id'], 

300 with_share_access_data=with_share_access_data) 

301 

302 for key in ('share_id', 'access_type', 'access_to', 'access_level', 

303 'access_key'): 

304 self.assertEqual(with_share_access_data, key in instance_access) 

305 

306 @ddt.data({'existing': {'access_type': 'cephx', 'access_to': 'alice'}, 

307 'new': {'access_type': 'user', 'access_to': 'alice'}, 

308 'result': False}, 

309 {'existing': {'access_type': 'user', 'access_to': 'bob'}, 

310 'new': {'access_type': 'user', 'access_to': 'bob'}, 

311 'result': True}, 

312 {'existing': {'access_type': 'ip', 'access_to': '10.0.0.10/32'}, 

313 'new': {'access_type': 'ip', 'access_to': '10.0.0.10'}, 

314 'result': True}, 

315 {'existing': {'access_type': 'ip', 'access_to': '10.10.0.11'}, 

316 'new': {'access_type': 'ip', 'access_to': '10.10.0.11'}, 

317 'result': True}, 

318 {'existing': {'access_type': 'ip', 'access_to': 'fd21::11'}, 

319 'new': {'access_type': 'ip', 'access_to': 'fd21::11'}, 

320 'result': True}, 

321 {'existing': {'access_type': 'ip', 'access_to': 'fd21::10'}, 

322 'new': {'access_type': 'ip', 'access_to': 'fd21::10/128'}, 

323 'result': True}, 

324 {'existing': {'access_type': 'ip', 'access_to': '10.10.0.0/22'}, 

325 'new': {'access_type': 'ip', 'access_to': '10.10.0.0/24'}, 

326 'result': False}, 

327 {'existing': {'access_type': 'ip', 'access_to': '2620:52::/48'}, 

328 'new': {'access_type': 'ip', 

329 'access_to': '2620:52:0:13b8::/64'}, 

330 'result': False}) 

331 @ddt.unpack 

332 def test_share_access_check_for_existing_access(self, existing, new, 

333 result): 

334 share = db_utils.create_share() 

335 db_utils.create_access(share_id=share['id'], 

336 access_type=existing['access_type'], 

337 access_to=existing['access_to']) 

338 

339 rule_exists = db_api.share_access_check_for_existing_access( 

340 self.ctxt, share['id'], new['access_type'], new['access_to']) 

341 

342 self.assertEqual(result, rule_exists) 

343 

344 def test_share_access_get_all_for_share_with_metadata(self): 

345 share = db_utils.create_share() 

346 rules = [db_utils.create_access( 

347 share_id=share['id'], metadata={'key1': i}) 

348 for i in range(0, 3)] 

349 rule_ids = [r['id'] for r in rules] 

350 

351 result = db_api.share_access_get_all_for_share(self.ctxt, share['id']) 

352 

353 self.assertEqual(3, len(result)) 

354 result_ids = [r['id'] for r in result] 

355 self.assertEqual(rule_ids, result_ids) 

356 

357 result = db_api.share_access_get_all_for_share( 

358 self.ctxt, share['id'], {'metadata': {'key1': '2'}}) 

359 self.assertEqual(1, len(result)) 

360 self.assertEqual(rules[2]['id'], result[0]['id']) 

361 

362 def test_share_access_metadata_update(self): 

363 share = db_utils.create_share() 

364 new_metadata = {'key1': 'test_update', 'key2': 'v2'} 

365 rule = db_utils.create_access(share_id=share['id'], 

366 metadata={'key1': 'v1'}) 

367 result_metadata = db_api.share_access_metadata_update( 

368 self.ctxt, rule['id'], metadata=new_metadata) 

369 result = db_api.share_access_get(self.ctxt, rule['id']) 

370 self.assertEqual(new_metadata, result_metadata) 

371 metadata = result.get('share_access_rules_metadata') 

372 if metadata: 372 ↛ 375line 372 didn't jump to line 375 because the condition on line 372 was always true

373 metadata = {item['key']: item['value'] for item in metadata} 

374 else: 

375 metadata = {} 

376 self.assertEqual(new_metadata, metadata) 

377 

378 def test_share_access_get_with_context(self): 

379 ctxt = context.RequestContext('demo', 'fake', False) 

380 share = db_utils.create_share(project_id=ctxt.project_id) 

381 rules = [db_utils.create_access(share_id=share['id'])] 

382 

383 result = db_api.share_access_get_with_context(ctxt, rules[0]['id']) 

384 

385 self.assertEqual(result['project_id'], ctxt.project_id) 

386 

387 def test_share_access_get_with_context_not_found(self): 

388 

389 self.assertRaises( 

390 exception.NotFound, 

391 db_api.share_access_get_with_context, 

392 self.ctxt, 

393 'fake_rule_id') 

394 

395 

396@ddt.ddt 

397class ShareDatabaseAPITestCase(test.TestCase): 

398 

399 def setUp(self): 

400 """Run before each test.""" 

401 super(ShareDatabaseAPITestCase, self).setUp() 

402 self.ctxt = context.get_admin_context() 

403 

404 def test_share_create(self): 

405 share = db_api.share_create( 

406 self.ctxt, 

407 {'user_id': 'user', 'project_id': 'project', 'host': 'foo'}, 

408 ) 

409 self.assertEqual('user', share.user_id) 

410 self.assertEqual('project', share.project_id) 

411 self.assertEqual('foo', share.host) 

412 self.assertEqual(1, len(share.instances)) 

413 self.assertIsInstance(share.instances[0], models.ShareInstance) 

414 self.assertEqual(share.instances[0], share.instance) 

415 

416 def test_share_create__no_instance(self): 

417 share = db_api.share_create( 

418 self.ctxt, 

419 {'user_id': 'user', 'project_id': 'project', 'host': 'foo'}, 

420 create_share_instance=False, 

421 ) 

422 self.assertEqual('user', share.user_id) 

423 self.assertEqual('project', share.project_id) 

424 self.assertIsNone(share.host) 

425 self.assertEqual(0, len(share.instances)) 

426 

427 @ddt.data('yes', 'no', 'only') 

428 def test_share_read_deleted(self, read_deleted): 

429 share = db_utils.create_share() 

430 test_ctxt = context.get_admin_context(read_deleted=read_deleted) 

431 admin_ctxt = context.get_admin_context(read_deleted='yes') 

432 

433 if read_deleted in ('yes', 'no'): 

434 self.assertIsNotNone(db_api.share_get(test_ctxt, share['id'])) 

435 elif read_deleted == 'only': 435 ↛ 441line 435 didn't jump to line 441 because the condition on line 435 was always true

436 self.assertRaises(exception.NotFound, db_api.share_get, 

437 test_ctxt, share['id']) 

438 

439 # we don't use the to be tested context here and 

440 # we need to delete the share instance before we can delete the share 

441 db_api.share_instance_delete(admin_ctxt, share['instance']['id']) 

442 db_api.share_delete(admin_ctxt, share['id']) 

443 

444 if read_deleted in ('yes', 'only'): 

445 self.assertIsNotNone(db_api.share_get(test_ctxt, share['id'])) 

446 elif read_deleted == 'no': 446 ↛ exitline 446 didn't return from function 'test_share_read_deleted' because the condition on line 446 was always true

447 self.assertRaises(exception.NotFound, db_api.share_get, 

448 test_ctxt, share['id']) 

449 

450 def test_share_filter_by_host_with_pools(self): 

451 share_instances = [[ 

452 db_api.share_create(self.ctxt, {'host': value}).instance 

453 for value in ('foo', 'foo#pool0')]] 

454 

455 db_utils.create_share() 

456 self._assertEqualListsOfObjects(share_instances[0], 

457 db_api.share_instance_get_all_by_host( 

458 self.ctxt, 'foo'), 

459 ignored_keys=['share_type', 

460 'share_type_id', 

461 'export_locations']) 

462 

463 def test_share_filter_all_by_host_with_pools_multiple_hosts(self): 

464 share_instances = [[ 

465 db_api.share_create(self.ctxt, {'host': value}).instance 

466 for value in ('foo', 'foo#pool0', 'foo', 'foo#pool1')]] 

467 

468 db_utils.create_share() 

469 self._assertEqualListsOfObjects(share_instances[0], 

470 db_api.share_instance_get_all_by_host( 

471 self.ctxt, 'foo'), 

472 ignored_keys=['share_type', 

473 'share_type_id', 

474 'export_locations']) 

475 

476 def test_share_filter_all_by_share_server(self): 

477 share_network = db_utils.create_share_network() 

478 share_server = db_utils.create_share_server() 

479 share = db_utils.create_share(share_server_id=share_server['id'], 

480 share_network_id=share_network['id']) 

481 

482 actual_result = db_api.share_get_all_by_share_server( 

483 self.ctxt, share_server['id']) 

484 

485 self.assertEqual(1, len(actual_result)) 

486 self.assertEqual(share['id'], actual_result[0].id) 

487 

488 def test_share_in_recycle_bin_filter_all_by_share_server(self): 

489 share_network = db_utils.create_share_network() 

490 share_server = db_utils.create_share_server() 

491 share = db_utils.create_share(share_server_id=share_server['id'], 

492 share_network_id=share_network['id'], 

493 is_soft_deleted=True) 

494 

495 actual_result = db_api.share_get_all_soft_deleted( 

496 self.ctxt, share_server['id']) 

497 

498 self.assertEqual(1, len(actual_result)) 

499 self.assertEqual(share['id'], actual_result[0].id) 

500 

501 def test_share_in_recycle_bin_filter_all_by_share_network(self): 

502 share_network = db_utils.create_share_network() 

503 share_server = db_utils.create_share_server() 

504 share = db_utils.create_share(share_server_id=share_server['id'], 

505 share_network_id=share_network['id'], 

506 is_soft_deleted=True) 

507 

508 actual_result = db_api.share_get_all_soft_deleted_by_network( 

509 self.ctxt, share_network['id']) 

510 

511 self.assertEqual(1, len(actual_result)) 

512 self.assertEqual(share['id'], actual_result[0].id) 

513 

514 def test_share_filter_all_by_share_group(self): 

515 group = db_utils.create_share_group() 

516 share = db_utils.create_share(share_group_id=group['id']) 

517 

518 actual_result = db_api.share_get_all_by_share_group_id( 

519 self.ctxt, group['id']) 

520 

521 self.assertEqual(1, len(actual_result)) 

522 self.assertEqual(share['id'], actual_result[0].id) 

523 

524 def test_share_instance_delete_with_share(self): 

525 share = db_utils.create_share() 

526 

527 self.assertIsNotNone(db_api.share_get(self.ctxt, share['id'])) 

528 self.assertIsNotNone(db_api.share_metadata_get(self.ctxt, share['id'])) 

529 

530 db_api.share_instance_delete(self.ctxt, share.instance['id']) 

531 

532 self.assertRaises(exception.NotFound, db_api.share_get, 

533 self.ctxt, share['id']) 

534 self.assertRaises(exception.NotFound, db_api.share_metadata_get, 

535 self.ctxt, share['id']) 

536 

537 def test_share_instance_delete_with_share_need_to_update_usages(self): 

538 share = db_utils.create_share() 

539 

540 self.assertIsNotNone(db_api.share_get(self.ctxt, share['id'])) 

541 self.assertIsNotNone(db_api.share_metadata_get(self.ctxt, share['id'])) 

542 

543 self.mock_object(quota.QUOTAS, 'reserve', 

544 mock.Mock(return_value='reservation')) 

545 self.mock_object(quota.QUOTAS, 'commit') 

546 

547 db_api.share_instance_delete( 

548 self.ctxt, share.instance['id'], need_to_update_usages=True) 

549 

550 self.assertRaises(exception.NotFound, db_api.share_get, 

551 self.ctxt, share['id']) 

552 self.assertRaises(exception.NotFound, db_api.share_metadata_get, 

553 self.ctxt, share['id']) 

554 quota.QUOTAS.reserve.assert_called_once_with( 

555 self.ctxt, 

556 project_id=share['project_id'], 

557 shares=-1, 

558 gigabytes=-share['size'], 

559 share_type_id=None, 

560 user_id=share['user_id'] 

561 ) 

562 quota.QUOTAS.commit.assert_called_once_with( 

563 self.ctxt, 

564 mock.ANY, 

565 project_id=share['project_id'], 

566 share_type_id=None, 

567 user_id=share['user_id'] 

568 ) 

569 

570 def test_share_instance_get(self): 

571 share = db_utils.create_share() 

572 

573 instance = db_api.share_instance_get(self.ctxt, share.instance['id']) 

574 

575 self.assertEqual('share-%s' % instance['id'], instance['name']) 

576 

577 @ddt.data({'with_share_data': True, 'status': constants.STATUS_AVAILABLE}, 

578 {'with_share_data': False, 'status': None}) 

579 @ddt.unpack 

580 def test_share_instance_get_all_by_host(self, with_share_data, status): 

581 kwargs = {'status': status} if status else {} 

582 db_utils.create_share(**kwargs) 

583 instances = db_api.share_instance_get_all_by_host( 

584 self.ctxt, 'fake_host', with_share_data=with_share_data, 

585 status=status) 

586 

587 self.assertEqual(1, len(instances)) 

588 instance = instances[0] 

589 

590 self.assertEqual('share-%s' % instance['id'], instance['name']) 

591 

592 if with_share_data: 

593 self.assertEqual('NFS', instance['share_proto']) 

594 self.assertEqual(0, instance['size']) 

595 else: 

596 self.assertNotIn('share_proto', instance) 

597 

598 def test_share_instance_get_all_by_host_not_found_exception(self): 

599 db_utils.create_share() 

600 instances = db_api.share_instance_get_all_by_host( 

601 self.ctxt, 'not_found_host', True) 

602 

603 self.assertEqual(0, len(instances)) 

604 

605 @ddt.data( 

606 {'status': constants.STATUS_AVAILABLE}, 

607 {'status': None}) 

608 @ddt.unpack 

609 def test_share_instance_get_all_by_host_no_instance(self, status): 

610 db_utils.create_share_without_instance() 

611 instances = db_api.share_instance_get_all_by_host( 

612 self.ctxt, "fake_host", with_share_data=True, status=status 

613 ) 

614 

615 self.assertEqual(0, len(instances)) 

616 

617 def test_share_instance_get_all_by_share_group(self): 

618 group = db_utils.create_share_group() 

619 db_utils.create_share(share_group_id=group['id']) 

620 db_utils.create_share() 

621 

622 instances = db_api.share_instance_get_all_by_share_group_id( 

623 self.ctxt, group['id']) 

624 

625 self.assertEqual(1, len(instances)) 

626 instance = instances[0] 

627 

628 self.assertEqual('share-%s' % instance['id'], instance['name']) 

629 

630 @ddt.data('id', 'path') 

631 def test_share_instance_get_all_by_export_location(self, type): 

632 share = db_utils.create_share() 

633 initial_location = ['fake_export_location'] 

634 db_api.export_locations_update( 

635 self.ctxt, share.instance['id'], initial_location, False) 

636 

637 if type == 'id': 

638 export_location = db_api.export_location_get_all_by_share_id( 

639 self.ctxt, share['id']) 

640 value = export_location[0]['uuid'] 

641 else: 

642 value = 'fake_export_location' 

643 

644 instances = db_api.share_instance_get_all( 

645 self.ctxt, filters={'export_location_' + type: value}) 

646 

647 self.assertEqual(1, len(instances)) 

648 instance = instances[0] 

649 

650 self.assertEqual('share-%s' % instance['id'], instance['name']) 

651 

652 def test_share_instance_get_all_by_is_soft_deleted(self): 

653 db_utils.create_share() 

654 db_utils.create_share(is_soft_deleted=True) 

655 

656 instances = db_api.share_instance_get_all( 

657 self.ctxt, filters={'is_soft_deleted': True}) 

658 

659 self.assertEqual(1, len(instances)) 

660 instance = instances[0] 

661 

662 self.assertEqual('share-%s' % instance['id'], instance['name']) 

663 

664 def test_share_instance_get_all_by_status(self): 

665 share = db_utils.create_share() 

666 db_utils.create_share_instance( 

667 share_id=share['id'], status='creating') 

668 share2 = db_utils.create_share() 

669 db_utils.create_share_instance( 

670 share_id=share2['id'], status='error_deferred_deleting') 

671 

672 instances = db_api.share_instance_get_all( 

673 self.ctxt, filters={'status': 'error_deferred_deleting'}) 

674 self.assertEqual(1, len(instances)) 

675 

676 def test_share_instance_get_all_by_ids(self): 

677 fake_share = db_utils.create_share() 

678 expected_share_instance = db_utils.create_share_instance( 

679 share_id=fake_share['id']) 

680 

681 # Populate the db with a dummy share 

682 db_utils.create_share_instance(share_id=fake_share['id']) 

683 

684 instances = db_api.share_instance_get_all( 

685 self.ctxt, 

686 filters={'instance_ids': [expected_share_instance['id']]}) 

687 

688 self.assertEqual(1, len(instances)) 

689 instance = instances[0] 

690 

691 self.assertEqual('share-%s' % instance['id'], instance['name']) 

692 

693 @ddt.data('host', 'share_group_id') 

694 def test_share_get_all_sort_by_share_instance_fields(self, sort_key): 

695 shares = [db_utils.create_share(**{sort_key: n, 'size': 1}) 

696 for n in ('test1', 'test2')] 

697 

698 actual_result = db_api.share_get_all( 

699 self.ctxt, sort_key=sort_key, sort_dir='desc') 

700 

701 self.assertEqual(2, len(actual_result)) 

702 self.assertEqual(shares[0]['id'], actual_result[1]['id']) 

703 

704 @ddt.data('id') 

705 def test_share_get_all_sort_by_share_fields(self, sort_key): 

706 shares = [db_utils.create_share(**{sort_key: n, 'size': 1}) 

707 for n in ('FAKE_UUID1', 'FAKE_UUID2')] 

708 

709 actual_result = db_api.share_get_all( 

710 self.ctxt, sort_key=sort_key, sort_dir='desc') 

711 

712 self.assertEqual(2, len(actual_result)) 

713 self.assertEqual(shares[0]['id'], actual_result[1]['id']) 

714 

715 @ddt.data('id', 'path') 

716 def test_share_get_all_by_export_location(self, type): 

717 share = db_utils.create_share() 

718 initial_location = ['fake_export_location'] 

719 db_api.export_locations_update( 

720 self.ctxt, share.instance['id'], initial_location, False) 

721 if type == 'id': 

722 export_location = db_api.export_location_get_all_by_share_id( 

723 self.ctxt, share['id']) 

724 value = export_location[0]['uuid'] 

725 else: 

726 value = 'fake_export_location' 

727 

728 actual_result = db_api.share_get_all( 

729 self.ctxt, filters={'export_location_' + type: value}) 

730 

731 self.assertEqual(1, len(actual_result)) 

732 self.assertEqual(share['id'], actual_result[0]['id']) 

733 

734 @ddt.data('id', 'path') 

735 def test_share_get_all_by_export_location_not_exist(self, type): 

736 share = db_utils.create_share() 

737 initial_location = ['fake_export_location'] 

738 db_api.export_locations_update( 

739 self.ctxt, share.instance['id'], initial_location, False) 

740 filter = {'export_location_' + type: 'export_location_not_exist'} 

741 actual_result = db_api.share_get_all(self.ctxt, filters=filter) 

742 

743 self.assertEqual(0, len(actual_result)) 

744 

745 @ddt.data((10, 5), (20, 5)) 

746 @ddt.unpack 

747 def test_share_get_all_with_limit(self, limit, offset): 

748 for i in range(limit + 5): 

749 db_utils.create_share() 

750 

751 filters = {'limit': offset, 'offset': 0} 

752 shares_not_requested = db_api.share_get_all( 

753 self.ctxt, filters=filters) 

754 

755 filters = {'limit': limit, 'offset': offset} 

756 shares_requested = db_api.share_get_all(self.ctxt, filters=filters) 

757 

758 shares_not_requested_ids = [s['id'] for s in shares_not_requested] 

759 shares_requested_ids = [s['id'] for s in shares_requested] 

760 

761 self.assertEqual(offset, len(shares_not_requested_ids)) 

762 self.assertEqual(limit, len(shares_requested_ids)) 

763 self.assertEqual(0, len( 

764 set(shares_requested_ids) & set(shares_not_requested_ids))) 

765 

766 @ddt.data( 

767 ({'display_name~': 'fake_name'}, 3, 3), 

768 ({'display_name~': 'fake_name', 'limit': 2}, 3, 2) 

769 ) 

770 @ddt.unpack 

771 def test_share_get_all_with_count(self, filters, amount_of_shares, 

772 expected_shares_len): 

773 c_shares = [ 

774 db_utils.create_share(display_name='fake_name_%s' % str(i)) 

775 for i in range(amount_of_shares)] 

776 

777 # create one more share instance 

778 db_utils.create_share_instance(share_id=c_shares[0]['id']) 

779 db_utils.create_share_instance(share_id=c_shares[1]['id']) 

780 

781 count, shares = db_api.share_get_all_with_count( 

782 self.ctxt, filters=filters) 

783 

784 self.assertEqual(count, amount_of_shares) 

785 for share in shares: 

786 self.assertIn('fake_name', share['display_name']) 

787 self.assertEqual(expected_shares_len, len(shares)) 

788 

789 def test_share_get_all_by_share_group_id_with_count(self): 

790 share_groups = [db_utils.create_share_group() for i in range(2)] 

791 shares = [ 

792 db_utils.create_share(share_group_id=share_group['id']) 

793 for share_group in share_groups] 

794 

795 count, result = db_api.share_get_all_by_share_group_id_with_count( 

796 self.ctxt, share_groups[0]['id']) 

797 

798 self.assertEqual(count, 1) 

799 self.assertEqual(shares[0]['id'], result[0]['id']) 

800 self.assertEqual(1, len(result)) 

801 

802 def test_share_get_all_by_share_server_with_count(self): 

803 share_servers = [db_utils.create_share_server() for i in range(2)] 

804 shares = [ 

805 db_utils.create_share(share_server_id=share_server['id']) 

806 for share_server in share_servers] 

807 

808 count, result = db_api.share_get_all_by_share_server_with_count( 

809 self.ctxt, share_servers[0]['id']) 

810 

811 self.assertEqual(count, 1) 

812 self.assertEqual(shares[0]['id'], result[0]['id']) 

813 self.assertEqual(1, len(result)) 

814 

815 def test_share_get_all_by_project_with_count(self): 

816 project_ids = ['fake_id_1', 'fake_id_2'] 

817 shares = [ 

818 db_utils.create_share(project_id=project_id) 

819 for project_id in project_ids] 

820 

821 count, result = db_api.share_get_all_by_project_with_count( 

822 self.ctxt, project_ids[0]) 

823 

824 self.assertEqual(count, 1) 

825 self.assertEqual(shares[0]['id'], result[0]['id']) 

826 self.assertEqual(1, len(result)) 

827 

828 def test_share_get_all_expired(self): 

829 now_time = timeutils.utcnow() 

830 time_delta = datetime.timedelta(seconds=3600) 

831 time1 = now_time + time_delta 

832 time2 = now_time - time_delta 

833 share1 = db_utils.create_share(status=constants.STATUS_AVAILABLE, 

834 is_soft_deleted=False, 

835 scheduled_to_be_deleted_at=None) 

836 share2 = db_utils.create_share(status=constants.STATUS_AVAILABLE, 

837 is_soft_deleted=True, 

838 scheduled_to_be_deleted_at=time1) 

839 share3 = db_utils.create_share(status=constants.STATUS_AVAILABLE, 

840 is_soft_deleted=True, 

841 scheduled_to_be_deleted_at=time2) 

842 shares = [share1, share2, share3] 

843 result = db_api.share_get_all_expired(self.ctxt) 

844 self.assertEqual(1, len(result)) 

845 self.assertEqual(shares[2]['id'], result[0]['id']) 

846 

847 @ddt.data( 

848 ({'status': constants.STATUS_AVAILABLE}, 'status', 

849 [constants.STATUS_AVAILABLE, constants.STATUS_ERROR]), 

850 ({'share_group_id': 'fake_group_id'}, 'share_group_id', 

851 ['fake_group_id', 'group_id']), 

852 ({'snapshot_id': 'fake_snapshot_id'}, 'snapshot_id', 

853 ['fake_snapshot_id', 'snapshot_id']), 

854 ({'share_type_id': 'fake_type_id'}, 'share_type_id', 

855 ['fake_type_id', 'type_id']), 

856 ({'host': 'fakehost@fakebackend#fakepool'}, 'host', 

857 ['fakehost@fakebackend#fakepool', 'foo@bar#test']), 

858 ({'share_network_id': 'fake_net_id'}, 'share_network_id', 

859 ['fake_net_id', 'net_id']), 

860 ({'display_name': 'fake_share_name'}, 'display_name', 

861 ['fake_share_name', 'share_name']), 

862 ({'display_description': 'fake description'}, 'display_description', 

863 ['fake description', 'description']), 

864 ({'is_soft_deleted': True}, 'is_soft_deleted', 

865 [True, False]) 

866 ) 

867 @ddt.unpack 

868 def test_share_get_all_with_filters(self, filters, key, share_values): 

869 for value in share_values: 

870 kwargs = {key: value} 

871 db_utils.create_share(**kwargs) 

872 

873 results = db_api.share_get_all(self.ctxt, filters=filters) 

874 

875 for share in results: 

876 self.assertEqual(share[key], filters[key]) 

877 

878 @ddt.data( 

879 ('display_name~', 'display_name', 

880 ['fake_name_1', 'fake_name_2', 'fake_name_3'], 'fake_name'), 

881 ('display_description~', 'display_description', 

882 ['fake desc 1', 'fake desc 2', 'fake desc 3'], 'fake desc') 

883 ) 

884 @ddt.unpack 

885 def test_share_get_all_like_filters( 

886 self, filter_name, key, share_values, like_value): 

887 for value in share_values: 

888 kwargs = {key: value} 

889 db_utils.create_share(**kwargs) 

890 db_utils.create_share( 

891 display_name='irrelevant_name', 

892 display_description='should not be queried') 

893 

894 filters = {filter_name: like_value} 

895 

896 results = db_api.share_get_all(self.ctxt, filters=filters) 

897 

898 self.assertEqual(len(share_values), len(results)) 

899 

900 @ddt.data( 

901 ('display_name~', 'display_name', 

902 ['fake_name_1', 'fake_name_2', 'fake_name_%'], '%'), 

903 ('display_description~', 'display_description', 

904 ['fake desc 1', 'fake desc 2', 'fake desc %'], '%') 

905 ) 

906 @ddt.unpack 

907 def test_share_get_all_like_filters_with_percent_sign( 

908 self, filter_name, key, share_values, like_value): 

909 for value in share_values: 

910 kwargs = {key: value} 

911 db_utils.create_share(**kwargs) 

912 db_utils.create_share( 

913 display_name='irrelevant_name', 

914 display_description='should not be queried') 

915 

916 filters = {filter_name: like_value} 

917 

918 results = db_api.share_get_all(self.ctxt, filters=filters) 

919 

920 self.assertEqual(1, len(results)) 

921 

922 @ddt.data(None, 'writable') 

923 def test_share_get_has_replicas_field(self, replication_type): 

924 share = db_utils.create_share(replication_type=replication_type) 

925 

926 db_share = db_api.share_get(self.ctxt, share['id']) 

927 

928 self.assertIn('has_replicas', db_share) 

929 

930 @ddt.data({'with_share_data': False, 'with_share_server': False}, 

931 {'with_share_data': False, 'with_share_server': True}, 

932 {'with_share_data': True, 'with_share_server': False}, 

933 {'with_share_data': True, 'with_share_server': True}) 

934 @ddt.unpack 

935 def test_share_replicas_get_all(self, with_share_data, 

936 with_share_server): 

937 share_server = db_utils.create_share_server() 

938 share_1 = db_utils.create_share() 

939 share_2 = db_utils.create_share() 

940 db_utils.create_share_replica( 

941 replica_state=constants.REPLICA_STATE_ACTIVE, 

942 share_id=share_1['id'], 

943 share_server_id=share_server['id']) 

944 db_utils.create_share_replica( 

945 replica_state=constants.REPLICA_STATE_IN_SYNC, 

946 share_id=share_1['id'], 

947 share_server_id=share_server['id']) 

948 db_utils.create_share_replica( 

949 replica_state=constants.REPLICA_STATE_OUT_OF_SYNC, 

950 share_id=share_2['id'], 

951 share_server_id=share_server['id']) 

952 db_utils.create_share_replica(share_id=share_2['id']) 

953 expected_ss_keys = { 

954 'backend_details', 'host', 'id', 

955 'share_network_subnet_ids', 'status', 

956 } 

957 expected_share_keys = { 

958 'project_id', 'share_type_id', 'display_name', 

959 'name', 'share_proto', 'is_public', 

960 'source_share_group_snapshot_member_id', 

961 } 

962 

963 share_replicas = db_api.share_replicas_get_all( 

964 self.ctxt, with_share_server=with_share_server, 

965 with_share_data=with_share_data, 

966 ) 

967 

968 self.assertEqual(3, len(share_replicas)) 

969 for replica in share_replicas: 

970 if with_share_server: 

971 self.assertTrue(expected_ss_keys.issubset( 

972 replica['share_server'].keys())) 

973 else: 

974 self.assertNotIn('share_server', replica.keys()) 

975 self.assertEqual( 

976 with_share_data, 

977 expected_share_keys.issubset(replica.keys())) 

978 

979 @ddt.data({'with_share_data': False, 'with_share_server': False}, 

980 {'with_share_data': False, 'with_share_server': True}, 

981 {'with_share_data': True, 'with_share_server': False}, 

982 {'with_share_data': True, 'with_share_server': True}) 

983 @ddt.unpack 

984 def test_share_replicas_get_all_by_share(self, with_share_data, 

985 with_share_server): 

986 share_server = db_utils.create_share_server() 

987 share = db_utils.create_share() 

988 db_utils.create_share_replica( 

989 replica_state=constants.REPLICA_STATE_ACTIVE, 

990 share_id=share['id'], 

991 share_server_id=share_server['id']) 

992 db_utils.create_share_replica( 

993 replica_state=constants.REPLICA_STATE_IN_SYNC, 

994 share_id=share['id'], 

995 share_server_id=share_server['id']) 

996 db_utils.create_share_replica( 

997 replica_state=constants.REPLICA_STATE_OUT_OF_SYNC, 

998 share_id=share['id'], 

999 share_server_id=share_server['id']) 

1000 expected_ss_keys = { 

1001 'backend_details', 'host', 'id', 

1002 'share_network_subnet_ids', 'status', 

1003 } 

1004 expected_share_keys = { 

1005 'project_id', 'share_type_id', 'display_name', 

1006 'name', 'share_proto', 'is_public', 

1007 'source_share_group_snapshot_member_id', 

1008 } 

1009 

1010 share_replicas = db_api.share_replicas_get_all_by_share( 

1011 self.ctxt, share['id'], 

1012 with_share_server=with_share_server, 

1013 with_share_data=with_share_data) 

1014 

1015 self.assertEqual(3, len(share_replicas)) 

1016 for replica in share_replicas: 

1017 if with_share_server: 

1018 self.assertTrue(expected_ss_keys.issubset( 

1019 replica['share_server'].keys())) 

1020 else: 

1021 self.assertNotIn('share_server', replica.keys()) 

1022 self.assertEqual(with_share_data, 

1023 expected_share_keys.issubset(replica.keys())) 

1024 

1025 def test_share_replicas_get_available_active_replica(self): 

1026 share_server = db_utils.create_share_server() 

1027 share_1 = db_utils.create_share() 

1028 share_2 = db_utils.create_share() 

1029 share_3 = db_utils.create_share() 

1030 db_utils.create_share_replica( 

1031 id='Replica1', 

1032 share_id=share_1['id'], 

1033 status=constants.STATUS_AVAILABLE, 

1034 replica_state=constants.REPLICA_STATE_ACTIVE, 

1035 share_server_id=share_server['id']) 

1036 db_utils.create_share_replica( 

1037 id='Replica2', 

1038 status=constants.STATUS_AVAILABLE, 

1039 share_id=share_1['id'], 

1040 replica_state=constants.REPLICA_STATE_ACTIVE, 

1041 share_server_id=share_server['id']) 

1042 db_utils.create_share_replica( 

1043 id='Replica3', 

1044 status=constants.STATUS_AVAILABLE, 

1045 share_id=share_2['id'], 

1046 replica_state=constants.REPLICA_STATE_ACTIVE) 

1047 db_utils.create_share_replica( 

1048 id='Replica4', 

1049 status=constants.STATUS_ERROR, 

1050 share_id=share_2['id'], 

1051 replica_state=constants.REPLICA_STATE_ACTIVE) 

1052 db_utils.create_share_replica( 

1053 id='Replica5', 

1054 status=constants.STATUS_AVAILABLE, 

1055 share_id=share_2['id'], 

1056 replica_state=constants.REPLICA_STATE_IN_SYNC) 

1057 db_utils.create_share_replica( 

1058 id='Replica6', 

1059 share_id=share_3['id'], 

1060 status=constants.STATUS_AVAILABLE, 

1061 replica_state=constants.REPLICA_STATE_IN_SYNC) 

1062 expected_ss_keys = { 

1063 'backend_details', 'host', 'id', 

1064 'share_network_subnet_ids', 'status', 

1065 } 

1066 expected_share_keys = { 

1067 'project_id', 'share_type_id', 'display_name', 

1068 'name', 'share_proto', 'is_public', 

1069 'source_share_group_snapshot_member_id', 

1070 } 

1071 

1072 replica_share_1 = ( 

1073 db_api.share_replicas_get_available_active_replica( 

1074 self.ctxt, share_1['id'], with_share_server=True, 

1075 ) 

1076 ) 

1077 replica_share_2 = ( 

1078 db_api.share_replicas_get_available_active_replica( 

1079 self.ctxt, share_2['id'], with_share_server=True, 

1080 with_share_data=True) 

1081 ) 

1082 replica_share_3 = ( 

1083 db_api.share_replicas_get_available_active_replica( 

1084 self.ctxt, share_3['id'], 

1085 ) 

1086 ) 

1087 

1088 self.assertIn(replica_share_1.get('id'), ['Replica1', 'Replica2']) 

1089 self.assertTrue(expected_ss_keys.issubset( 

1090 replica_share_1['share_server'].keys())) 

1091 self.assertFalse( 

1092 expected_share_keys.issubset(replica_share_1.keys())) 

1093 self.assertEqual(replica_share_2.get('id'), 'Replica3') 

1094 self.assertFalse(replica_share_2['share_server']) 

1095 self.assertTrue( 

1096 expected_share_keys.issubset(replica_share_2.keys())) 

1097 self.assertIsNone(replica_share_3) 

1098 

1099 def test_share_replica_get_exception(self): 

1100 replica = db_utils.create_share_replica(share_id='FAKE_SHARE_ID') 

1101 

1102 self.assertRaises(exception.ShareReplicaNotFound, 

1103 db_api.share_replica_get, 

1104 self.ctxt, replica['id']) 

1105 

1106 def test_share_replica_get_without_share_data(self): 

1107 share = db_utils.create_share() 

1108 replica = db_utils.create_share_replica( 

1109 share_id=share['id'], 

1110 replica_state=constants.REPLICA_STATE_ACTIVE) 

1111 expected_extra_keys = { 

1112 'project_id', 'share_type_id', 'display_name', 

1113 'name', 'share_proto', 'is_public', 

1114 'source_share_group_snapshot_member_id', 

1115 } 

1116 

1117 share_replica = db_api.share_replica_get(self.ctxt, replica['id']) 

1118 

1119 self.assertIsNotNone(share_replica['replica_state']) 

1120 self.assertEqual(share['id'], share_replica['share_id']) 

1121 self.assertFalse(expected_extra_keys.issubset(share_replica.keys())) 

1122 

1123 def test_share_replica_get_with_share_data(self): 

1124 share = db_utils.create_share() 

1125 replica = db_utils.create_share_replica( 

1126 share_id=share['id'], 

1127 replica_state=constants.REPLICA_STATE_ACTIVE) 

1128 expected_extra_keys = { 

1129 'project_id', 'share_type_id', 'display_name', 

1130 'name', 'share_proto', 'is_public', 

1131 'source_share_group_snapshot_member_id', 

1132 } 

1133 

1134 share_replica = db_api.share_replica_get( 

1135 self.ctxt, replica['id'], with_share_data=True) 

1136 

1137 self.assertIsNotNone(share_replica['replica_state']) 

1138 self.assertEqual(share['id'], share_replica['share_id']) 

1139 self.assertTrue(expected_extra_keys.issubset(share_replica.keys())) 

1140 

1141 def test_share_replica_get_with_share_server(self): 

1142 share_server = db_utils.create_share_server() 

1143 share = db_utils.create_share() 

1144 replica = db_utils.create_share_replica( 

1145 share_id=share['id'], 

1146 replica_state=constants.REPLICA_STATE_ACTIVE, 

1147 share_server_id=share_server['id'] 

1148 ) 

1149 expected_extra_keys = { 

1150 'backend_details', 'host', 'id', 

1151 'share_network_subnet_ids', 'status', 

1152 } 

1153 

1154 share_replica = db_api.share_replica_get( 

1155 self.ctxt, replica['id'], with_share_server=True, 

1156 ) 

1157 

1158 self.assertIsNotNone(share_replica['replica_state']) 

1159 self.assertEqual( 

1160 share_server['id'], share_replica['share_server_id']) 

1161 self.assertTrue(expected_extra_keys.issubset( 

1162 share_replica['share_server'].keys())) 

1163 

1164 def test_share_replica_update(self): 

1165 share = db_utils.create_share() 

1166 replica = db_utils.create_share_replica( 

1167 share_id=share['id'], replica_state=constants.REPLICA_STATE_ACTIVE) 

1168 

1169 updated_replica = db_api.share_replica_update( 

1170 self.ctxt, replica['id'], 

1171 {'replica_state': constants.REPLICA_STATE_OUT_OF_SYNC}) 

1172 

1173 self.assertEqual(constants.REPLICA_STATE_OUT_OF_SYNC, 

1174 updated_replica['replica_state']) 

1175 

1176 def test_share_replica_delete(self): 

1177 share = db_utils.create_share() 

1178 share = db_api.share_get(self.ctxt, share['id']) 

1179 self.mock_object(quota.QUOTAS, 'reserve', 

1180 mock.Mock(return_value='reservation')) 

1181 self.mock_object(quota.QUOTAS, 'commit') 

1182 replica = db_utils.create_share_replica( 

1183 share_id=share['id'], replica_state=constants.REPLICA_STATE_ACTIVE) 

1184 

1185 self.assertEqual(1, len( 

1186 db_api.share_replicas_get_all_by_share(self.ctxt, share['id']))) 

1187 

1188 db_api.share_replica_delete(self.ctxt, replica['id']) 

1189 

1190 self.assertEqual( 

1191 [], db_api.share_replicas_get_all_by_share(self.ctxt, share['id'])) 

1192 share_type_id = share['instances'][0].get('share_type_id', None) 

1193 quota.QUOTAS.reserve.assert_called_once_with( 

1194 self.ctxt, project_id=share['project_id'], 

1195 user_id=share['user_id'], share_type_id=share_type_id, 

1196 share_replicas=-1, replica_gigabytes=share['size']) 

1197 quota.QUOTAS.commit.assert_called_once_with( 

1198 self.ctxt, 'reservation', project_id=share['project_id'], 

1199 user_id=share['user_id'], share_type_id=share_type_id) 

1200 

1201 @ddt.data( 

1202 (True, {"share_replicas": -1, "replica_gigabytes": 0}, 'active'), 

1203 (False, {"shares": -1, "gigabytes": 0}, None), 

1204 (False, {"shares": -1, "gigabytes": 0, 

1205 "share_replicas": -1, "replica_gigabytes": 0}, 'active') 

1206 ) 

1207 @ddt.unpack 

1208 def test_share_instance_delete_quota_error(self, is_replica, deltas, 

1209 replica_state): 

1210 share = db_utils.create_share(replica_state=replica_state) 

1211 share = db_api.share_get(self.ctxt, share['id']) 

1212 instance_id = share['instances'][0]['id'] 

1213 

1214 if is_replica: 

1215 replica = db_utils.create_share_replica( 

1216 share_id=share['id'], 

1217 replica_state=constants.REPLICA_STATE_ACTIVE) 

1218 instance_id = replica['id'] 

1219 reservation = 'fake' 

1220 share_type_id = share['instances'][0]['share_type_id'] 

1221 

1222 self.mock_object(quota.QUOTAS, 'reserve', 

1223 mock.Mock(return_value=reservation)) 

1224 self.mock_object(quota.QUOTAS, 'commit', mock.Mock( 

1225 side_effect=exception.QuotaError('fake'))) 

1226 self.mock_object(quota.QUOTAS, 'rollback') 

1227 

1228 # NOTE(silvacarlose): not calling with assertRaises since the 

1229 # _update_share_instance_usages method is not raising an exception 

1230 db_api.share_instance_delete( 

1231 self.ctxt, instance_id, need_to_update_usages=True) 

1232 

1233 quota.QUOTAS.reserve.assert_called_once_with( 

1234 self.ctxt, project_id=share['project_id'], 

1235 user_id=share['user_id'], share_type_id=share_type_id, **deltas) 

1236 quota.QUOTAS.commit.assert_called_once_with( 

1237 self.ctxt, reservation, project_id=share['project_id'], 

1238 user_id=share['user_id'], share_type_id=share_type_id) 

1239 quota.QUOTAS.rollback.assert_called_once_with( 

1240 self.ctxt, reservation, share_type_id=share_type_id) 

1241 

1242 def test_share_instance_access_copy(self): 

1243 share = db_utils.create_share() 

1244 rules = [] 

1245 for i in range(0, 5): 

1246 rules.append(db_utils.create_access(share_id=share['id'])) 

1247 

1248 instance = db_utils.create_share_instance(share_id=share['id']) 

1249 

1250 share_access_rules = db_api.share_instance_access_copy( 

1251 self.ctxt, share['id'], instance['id']) 

1252 share_access_rule_ids = [a['id'] for a in share_access_rules] 

1253 

1254 self.assertEqual(5, len(share_access_rules)) 

1255 for rule_id in share_access_rule_ids: 

1256 self.assertIsNotNone( 

1257 db_api.share_instance_access_get( 

1258 self.ctxt, rule_id, instance['id'])) 

1259 

1260 def test_share_soft_delete(self): 

1261 share = db_utils.create_share() 

1262 db_api.share_soft_delete(self.ctxt, share['id']) 

1263 share = db_api.share_get(self.ctxt, share['id']) 

1264 

1265 self.assertEqual(share['is_soft_deleted'], True) 

1266 

1267 def test_share_restore(self): 

1268 share = db_utils.create_share(is_soft_deleted=True) 

1269 db_api.share_restore(self.ctxt, share['id']) 

1270 share = db_api.share_get(self.ctxt, share['id']) 

1271 

1272 self.assertEqual(share['is_soft_deleted'], False) 

1273 

1274 def test_share_metadata_get(self): 

1275 metadata = {'a': 'b', 'c': 'd'} 

1276 

1277 share_1 = db_utils.create_share(size=1) 

1278 db_api.share_metadata_update( 

1279 self.ctxt, share_id=share_1['id'], 

1280 metadata=metadata, delete=False) 

1281 self.assertEqual( 

1282 metadata, db_api.share_metadata_get( 

1283 self.ctxt, share_id=share_1['id'])) 

1284 

1285 def test_share_metadata_get_item(self): 

1286 metadata = {'a': 'b', 'c': 'd'} 

1287 key = 'a' 

1288 shouldbe = {'a': 'b'} 

1289 share_1 = db_utils.create_share(size=1) 

1290 db_api.share_metadata_update( 

1291 self.ctxt, share_id=share_1['id'], 

1292 metadata=metadata, delete=False) 

1293 self.assertEqual( 

1294 shouldbe, db_api.share_metadata_get_item( 

1295 self.ctxt, share_id=share_1['id'], 

1296 key=key)) 

1297 

1298 def test_share_metadata_update(self): 

1299 metadata1 = {'a': '1', 'c': '2'} 

1300 metadata2 = {'a': '3', 'd': '5'} 

1301 should_be = {'a': '3', 'c': '2', 'd': '5'} 

1302 share_1 = db_utils.create_share(size=1) 

1303 db_api.share_metadata_update( 

1304 self.ctxt, share_id=share_1['id'], 

1305 metadata=metadata1, delete=False) 

1306 db_api.share_metadata_update( 

1307 self.ctxt, share_id=share_1['id'], 

1308 metadata=metadata2, delete=False) 

1309 self.assertEqual( 

1310 should_be, db_api.share_metadata_get( 

1311 self.ctxt, share_id=share_1['id'])) 

1312 

1313 def test_share_metadata_update_item(self): 

1314 metadata1 = {'a': '1', 'c': '2'} 

1315 metadata2 = {'a': '3'} 

1316 should_be = {'a': '3', 'c': '2'} 

1317 share_1 = db_utils.create_share(size=1) 

1318 db_api.share_metadata_update( 

1319 self.ctxt, share_id=share_1['id'], 

1320 metadata=metadata1, delete=False) 

1321 db_api.share_metadata_update_item( 

1322 self.ctxt, share_id=share_1['id'], 

1323 item=metadata2) 

1324 self.assertEqual( 

1325 should_be, db_api.share_metadata_get( 

1326 self.ctxt, share_id=share_1['id'])) 

1327 

1328 def test_share_metadata_delete(self): 

1329 key = 'a' 

1330 metadata = {'a': '1', 'c': '2'} 

1331 should_be = {'c': '2'} 

1332 share_1 = db_utils.create_share(size=1) 

1333 db_api.share_metadata_update( 

1334 self.ctxt, share_id=share_1['id'], 

1335 metadata=metadata, delete=False) 

1336 db_api.share_metadata_delete( 

1337 self.ctxt, share_id=share_1['id'], 

1338 key=key) 

1339 self.assertEqual( 

1340 should_be, db_api.share_metadata_get( 

1341 self.ctxt, share_id=share_1['id'])) 

1342 

1343 

1344@ddt.ddt 

1345class ShareGroupDatabaseAPITestCase(test.TestCase): 

1346 def setUp(self): 

1347 """Run before each test.""" 

1348 super(ShareGroupDatabaseAPITestCase, self).setUp() 

1349 self.ctxt = context.get_admin_context() 

1350 

1351 def test_share_group_create_with_share_type(self): 

1352 fake_share_types = ["fake_share_type"] 

1353 share_group = db_utils.create_share_group(share_types=fake_share_types) 

1354 share_group = db_api.share_group_get(self.ctxt, share_group['id']) 

1355 

1356 self.assertEqual(1, len(share_group['share_types'])) 

1357 

1358 def test_share_group_get(self): 

1359 share_group = db_utils.create_share_group() 

1360 

1361 self.assertDictEqual( 

1362 dict(share_group), 

1363 dict(db_api.share_group_get(self.ctxt, share_group['id']))) 

1364 

1365 def test_count_share_groups_in_share_network(self): 

1366 share_network = db_utils.create_share_network() 

1367 db_utils.create_share_group() 

1368 db_utils.create_share_group(share_network_id=share_network['id']) 

1369 

1370 count = db_api.count_share_groups_in_share_network( 

1371 self.ctxt, share_network_id=share_network['id']) 

1372 

1373 self.assertEqual(1, count) 

1374 

1375 def test_share_group_get_all(self): 

1376 expected_share_group = db_utils.create_share_group() 

1377 

1378 share_groups = db_api.share_group_get_all(self.ctxt, detailed=False) 

1379 

1380 self.assertEqual(1, len(share_groups)) 

1381 share_group = share_groups[0] 

1382 self.assertEqual(2, len(dict(share_group).keys())) 

1383 self.assertEqual(expected_share_group['id'], share_group['id']) 

1384 self.assertEqual(expected_share_group['name'], share_group['name']) 

1385 

1386 def test_share_group_get_all_with_detail(self): 

1387 expected_share_group = db_utils.create_share_group() 

1388 

1389 share_groups = db_api.share_group_get_all(self.ctxt, detailed=True) 

1390 

1391 self.assertEqual(1, len(share_groups)) 

1392 self.assertDictEqual(dict(expected_share_group), dict(share_groups[0])) 

1393 

1394 def test_share_group_get_all_by_host(self): 

1395 fake_host = 'my_fake_host' 

1396 expected_share_group = db_utils.create_share_group(host=fake_host) 

1397 db_utils.create_share_group() 

1398 

1399 share_groups = db_api.share_group_get_all_by_host( 

1400 self.ctxt, fake_host, detailed=False) 

1401 

1402 self.assertEqual(1, len(share_groups)) 

1403 share_group = share_groups[0] 

1404 self.assertEqual(2, len(dict(share_group).keys())) 

1405 self.assertEqual(expected_share_group['id'], share_group['id']) 

1406 self.assertEqual(expected_share_group['name'], share_group['name']) 

1407 

1408 def test_share_group_get_all_by_host_with_details(self): 

1409 fake_host = 'my_fake_host' 

1410 expected_share_group = db_utils.create_share_group(host=fake_host) 

1411 db_utils.create_share_group() 

1412 

1413 share_groups = db_api.share_group_get_all_by_host( 

1414 self.ctxt, fake_host, detailed=True) 

1415 

1416 self.assertEqual(1, len(share_groups)) 

1417 share_group = share_groups[0] 

1418 self.assertDictEqual(dict(expected_share_group), dict(share_group)) 

1419 self.assertEqual(fake_host, share_group['host']) 

1420 

1421 def test_share_group_get_all_by_project(self): 

1422 fake_project = 'fake_project' 

1423 expected_group = db_utils.create_share_group( 

1424 project_id=fake_project) 

1425 db_utils.create_share_group() 

1426 

1427 groups = db_api.share_group_get_all_by_project(self.ctxt, 

1428 fake_project, 

1429 detailed=False) 

1430 

1431 self.assertEqual(1, len(groups)) 

1432 group = groups[0] 

1433 self.assertEqual(2, len(dict(group).keys())) 

1434 self.assertEqual(expected_group['id'], group['id']) 

1435 self.assertEqual(expected_group['name'], group['name']) 

1436 

1437 def test_share_group_get_all_by_share_server(self): 

1438 fake_server = 123 

1439 expected_group = db_utils.create_share_group( 

1440 share_server_id=fake_server) 

1441 db_utils.create_share_group() 

1442 

1443 groups = db_api.share_group_get_all_by_share_server(self.ctxt, 

1444 fake_server) 

1445 

1446 self.assertEqual(1, len(groups)) 

1447 group = groups[0] 

1448 self.assertEqual(expected_group['id'], group['id']) 

1449 self.assertEqual(expected_group['name'], group['name']) 

1450 

1451 def test_share_group_get_all_by_project_with_details(self): 

1452 fake_project = 'fake_project' 

1453 expected_group = db_utils.create_share_group( 

1454 project_id=fake_project) 

1455 db_utils.create_share_group() 

1456 

1457 groups = db_api.share_group_get_all_by_project(self.ctxt, 

1458 fake_project, 

1459 detailed=True) 

1460 

1461 self.assertEqual(1, len(groups)) 

1462 group = groups[0] 

1463 self.assertDictEqual(dict(expected_group), dict(group)) 

1464 self.assertEqual(fake_project, group['project_id']) 

1465 

1466 @ddt.data(({'name': 'fo'}, 0), ({'description': 'd'}, 0), 

1467 ({'name': 'foo', 'description': 'd'}, 0), 

1468 ({'name': 'foo'}, 1), ({'description': 'ds'}, 1), 

1469 ({'name~': 'foo', 'description~': 'ds'}, 2), 

1470 ({'name': 'foo', 'description~': 'ds'}, 1), 

1471 ({'name~': 'foo', 'description': 'ds'}, 1)) 

1472 @ddt.unpack 

1473 def test_share_group_get_all_by_name_and_description( 

1474 self, search_opts, group_number): 

1475 db_utils.create_share_group(name='fo1', description='d1') 

1476 expected_group1 = db_utils.create_share_group(name='foo', 

1477 description='ds') 

1478 expected_group2 = db_utils.create_share_group(name='foo1', 

1479 description='ds2') 

1480 

1481 groups = db_api.share_group_get_all( 

1482 self.ctxt, detailed=True, 

1483 filters=search_opts) 

1484 

1485 self.assertEqual(group_number, len(groups)) 

1486 if group_number == 1: 

1487 self.assertDictEqual(dict(expected_group1), dict(groups[0])) 

1488 elif group_number == 2: 

1489 self.assertDictEqual(dict(expected_group1), dict(groups[1])) 

1490 self.assertDictEqual(dict(expected_group2), dict(groups[0])) 

1491 

1492 def test_share_group_update(self): 

1493 fake_name = "my_fake_name" 

1494 expected_group = db_utils.create_share_group() 

1495 expected_group['name'] = fake_name 

1496 

1497 db_api.share_group_update(self.ctxt, 

1498 expected_group['id'], 

1499 {'name': fake_name}) 

1500 

1501 group = db_api.share_group_get(self.ctxt, expected_group['id']) 

1502 self.assertEqual(fake_name, group['name']) 

1503 

1504 def test_share_group_destroy(self): 

1505 group = db_utils.create_share_group() 

1506 db_api.share_group_get(self.ctxt, group['id']) 

1507 

1508 db_api.share_group_destroy(self.ctxt, group['id']) 

1509 

1510 self.assertRaises(exception.NotFound, db_api.share_group_get, 

1511 self.ctxt, group['id']) 

1512 

1513 def test_count_shares_in_share_group(self): 

1514 sg = db_utils.create_share_group() 

1515 db_utils.create_share(share_group_id=sg['id']) 

1516 db_utils.create_share() 

1517 

1518 count = db_api.count_shares_in_share_group(self.ctxt, sg['id']) 

1519 

1520 self.assertEqual(1, count) 

1521 

1522 def test_count_sg_snapshots_in_share_group(self): 

1523 sg = db_utils.create_share_group() 

1524 db_utils.create_share_group_snapshot(sg['id']) 

1525 db_utils.create_share_group_snapshot(sg['id']) 

1526 

1527 count = db_api.count_share_group_snapshots_in_share_group( 

1528 self.ctxt, sg['id']) 

1529 

1530 self.assertEqual(2, count) 

1531 

1532 def test_share_group_snapshot_get(self): 

1533 sg = db_utils.create_share_group() 

1534 sg_snap = dict(db_utils.create_share_group_snapshot(sg['id'])) 

1535 sg_snap_source_group = sg_snap.pop('share_group', {}) 

1536 get_sg_snap = dict( 

1537 db_api.share_group_snapshot_get(self.ctxt, sg_snap['id'])) 

1538 get_sg_snap_source_group = get_sg_snap.pop('share_group', {}) 

1539 

1540 self.assertDictEqual( 

1541 dict(sg_snap_source_group), dict(get_sg_snap_source_group)) 

1542 self.assertDictEqual(sg_snap, get_sg_snap) 

1543 

1544 def test_share_group_snapshot_get_all(self): 

1545 sg = db_utils.create_share_group() 

1546 expected_sg_snap = db_utils.create_share_group_snapshot(sg['id']) 

1547 

1548 snaps = db_api.share_group_snapshot_get_all(self.ctxt, detailed=False) 

1549 

1550 self.assertEqual(1, len(snaps)) 

1551 snap = snaps[0] 

1552 self.assertEqual(2, len(dict(snap).keys())) 

1553 self.assertEqual(expected_sg_snap['id'], snap['id']) 

1554 self.assertEqual(expected_sg_snap['name'], snap['name']) 

1555 

1556 def test_share_group_snapshot_get_all_with_detail(self): 

1557 sg = db_utils.create_share_group() 

1558 expected_sg_snap = dict(db_utils.create_share_group_snapshot(sg['id'])) 

1559 sg_snap_source_group = expected_sg_snap.pop('share_group', {}) 

1560 

1561 snaps = db_api.share_group_snapshot_get_all(self.ctxt, detailed=True) 

1562 

1563 self.assertEqual(1, len(snaps)) 

1564 actual_sg_snap = dict(snaps[0]) 

1565 get_sg_snap_source = actual_sg_snap.pop('share_group', {}) 

1566 self.assertDictEqual( 

1567 dict(sg_snap_source_group), dict(get_sg_snap_source)) 

1568 self.assertDictEqual(expected_sg_snap, actual_sg_snap) 

1569 

1570 def test_share_group_snapshot_get_all_by_project(self): 

1571 fake_project = uuidutils.generate_uuid() 

1572 sg = db_utils.create_share_group() 

1573 expected_sg_snap = db_utils.create_share_group_snapshot( 

1574 sg['id'], project_id=fake_project) 

1575 

1576 snaps = db_api.share_group_snapshot_get_all_by_project( 

1577 self.ctxt, fake_project, detailed=False) 

1578 

1579 self.assertEqual(1, len(snaps)) 

1580 snap = snaps[0] 

1581 self.assertEqual(2, len(dict(snap).keys())) 

1582 self.assertEqual(expected_sg_snap['id'], snap['id']) 

1583 self.assertEqual(expected_sg_snap['name'], snap['name']) 

1584 

1585 def test_share_group_snapshot_get_all_by_project_with_details(self): 

1586 fake_project = uuidutils.generate_uuid() 

1587 sg = db_utils.create_share_group() 

1588 expected_sg_snap = dict(db_utils.create_share_group_snapshot( 

1589 sg['id'], project_id=fake_project)) 

1590 sg_snap_source_group = expected_sg_snap.pop( 

1591 'share_group', {}) 

1592 

1593 snaps = db_api.share_group_snapshot_get_all_by_project( 

1594 self.ctxt, fake_project, detailed=True) 

1595 

1596 self.assertEqual(1, len(snaps)) 

1597 actual_snap = dict(snaps[0]) 

1598 get_sg_snap_source = actual_snap.pop('share_group', {}) 

1599 self.assertDictEqual( 

1600 dict(sg_snap_source_group), dict(get_sg_snap_source)) 

1601 self.assertEqual(expected_sg_snap, actual_snap) 

1602 self.assertEqual(fake_project, actual_snap['project_id']) 

1603 

1604 def test_share_group_snapshot_update(self): 

1605 fake_name = "my_fake_name" 

1606 sg = db_utils.create_share_group() 

1607 expected_sg_snap = db_utils.create_share_group_snapshot(sg['id']) 

1608 expected_sg_snap['name'] = fake_name 

1609 

1610 db_api.share_group_snapshot_update( 

1611 self.ctxt, expected_sg_snap['id'], {'name': fake_name}) 

1612 

1613 sg_snap = db_api.share_group_snapshot_get( 

1614 self.ctxt, expected_sg_snap['id']) 

1615 self.assertEqual(fake_name, sg_snap['name']) 

1616 

1617 def test_share_group_snapshot_destroy(self): 

1618 sg = db_utils.create_share_group() 

1619 sg_snap = db_utils.create_share_group_snapshot(sg['id']) 

1620 db_api.share_group_snapshot_get(self.ctxt, sg_snap['id']) 

1621 

1622 db_api.share_group_snapshot_destroy(self.ctxt, sg_snap['id']) 

1623 

1624 self.assertRaises( 

1625 exception.NotFound, 

1626 db_api.share_group_snapshot_get, self.ctxt, sg_snap['id']) 

1627 

1628 def test_share_group_snapshot_members_get_all(self): 

1629 sg = db_utils.create_share_group() 

1630 share = db_utils.create_share(share_group_id=sg['id']) 

1631 si = db_utils.create_share_instance(share_id=share['id']) 

1632 sg_snap = db_utils.create_share_group_snapshot(sg['id']) 

1633 expected_member = dict(db_utils.create_share_group_snapshot_member( 

1634 sg_snap['id'], share_instance_id=si['id'])) 

1635 sg_snap_source_member = expected_member.pop( 

1636 'share_group_snapshot', {}) 

1637 sg_snap_source_member = expected_member.pop('share_instance', {}) 

1638 

1639 members = db_api.share_group_snapshot_members_get_all( 

1640 self.ctxt, sg_snap['id']) 

1641 

1642 self.assertEqual(1, len(members)) 

1643 member = dict(members[0]) 

1644 get_sg_snap_source_member = member.pop( 

1645 'share_group_snapshot', {}) 

1646 get_sg_snap_source_member = member.pop('share_instance', {}) 

1647 self.assertDictEqual(dict( 

1648 sg_snap_source_member), dict(get_sg_snap_source_member)) 

1649 self.assertDictEqual(expected_member, member) 

1650 

1651 def test_count_share_group_snapshot_members_in_share(self): 

1652 sg = db_utils.create_share_group() 

1653 share = db_utils.create_share(share_group_id=sg['id']) 

1654 si = db_utils.create_share_instance(share_id=share['id']) 

1655 share2 = db_utils.create_share(share_group_id=sg['id']) 

1656 si2 = db_utils.create_share_instance(share_id=share2['id']) 

1657 sg_snap = db_utils.create_share_group_snapshot(sg['id']) 

1658 db_utils.create_share_group_snapshot_member( 

1659 sg_snap['id'], share_instance_id=si['id']) 

1660 db_utils.create_share_group_snapshot_member( 

1661 sg_snap['id'], share_instance_id=si2['id']) 

1662 

1663 count = db_api.count_share_group_snapshot_members_in_share( 

1664 self.ctxt, share['id']) 

1665 

1666 self.assertEqual(1, count) 

1667 

1668 def test_share_group_snapshot_members_get(self): 

1669 sg = db_utils.create_share_group() 

1670 share = db_utils.create_share(share_group_id=sg['id']) 

1671 si = db_utils.create_share_instance(share_id=share['id']) 

1672 sg_snap = db_utils.create_share_group_snapshot(sg['id']) 

1673 expected_member = dict(db_utils.create_share_group_snapshot_member( 

1674 sg_snap['id'], share_instance_id=si['id'])) 

1675 sg_snap_source_member = expected_member.pop('share_group_snapshot', {}) 

1676 sg_snap_source_member = expected_member.pop('share_instance', {}) 

1677 

1678 member = dict(db_api.share_group_snapshot_member_get( 

1679 self.ctxt, expected_member['id'])) 

1680 get_sg_snap_source_member = member.pop('share_group_snapshot', {}) 

1681 get_sg_snap_source_member = member.pop('share_instance', {}) 

1682 

1683 self.assertDictEqual(dict( 

1684 sg_snap_source_member), dict(get_sg_snap_source_member)) 

1685 self.assertDictEqual(expected_member, member) 

1686 

1687 def test_share_group_snapshot_members_get_not_found(self): 

1688 self.assertRaises( 

1689 exception.ShareGroupSnapshotMemberNotFound, 

1690 db_api.share_group_snapshot_member_get, self.ctxt, 'fake_id') 

1691 

1692 def test_share_group_snapshot_member_update(self): 

1693 sg = db_utils.create_share_group() 

1694 share = db_utils.create_share(share_group_id=sg['id']) 

1695 si = db_utils.create_share_instance(share_id=share['id']) 

1696 sg_snap = db_utils.create_share_group_snapshot(sg['id']) 

1697 expected_member = db_utils.create_share_group_snapshot_member( 

1698 sg_snap['id'], share_instance_id=si['id']) 

1699 

1700 db_api.share_group_snapshot_member_update( 

1701 self.ctxt, expected_member['id'], 

1702 {'status': constants.STATUS_AVAILABLE}) 

1703 

1704 member = db_api.share_group_snapshot_member_get( 

1705 self.ctxt, expected_member['id']) 

1706 self.assertEqual(constants.STATUS_AVAILABLE, member['status']) 

1707 

1708 

1709@ddt.ddt 

1710class ShareGroupTypeAPITestCase(test.TestCase): 

1711 

1712 def setUp(self): 

1713 super(ShareGroupTypeAPITestCase, self).setUp() 

1714 self.ctxt = context.RequestContext( 

1715 user_id='user_id', project_id='project_id', is_admin=True) 

1716 

1717 @ddt.data(True, False) 

1718 def test_share_type_destroy_in_use(self, used_by_groups): 

1719 share_type_1 = db_utils.create_share_type(name='fike') 

1720 share_type_2 = db_utils.create_share_type(name='bowman') 

1721 share_group_type_1 = db_utils.create_share_group_type( 

1722 name='orange', is_public=False, share_types=[share_type_1['id']], 

1723 group_specs={'dabo': 'allin', 'cadence': 'count'}, 

1724 override_defaults=True) 

1725 db_api.share_group_type_access_add(self.ctxt, 

1726 share_group_type_1['id'], 

1727 "2018ndaetfigovnsaslcahfavmrpions") 

1728 db_api.share_group_type_access_add(self.ctxt, 

1729 share_group_type_1['id'], 

1730 "2016ndaetfigovnsaslcahfavmrpions") 

1731 share_group_type_2 = db_utils.create_share_group_type( 

1732 name='regalia', share_types=[share_type_2['id']]) 

1733 if used_by_groups: 

1734 share_group_1 = db_utils.create_share_group( 

1735 share_group_type_id=share_group_type_1['id'], 

1736 share_types=[share_type_1['id']]) 

1737 share_group_2 = db_utils.create_share_group( 

1738 share_group_type_id=share_group_type_2['id'], 

1739 share_types=[share_type_2['id']]) 

1740 self.assertRaises(exception.ShareGroupTypeInUse, 

1741 db_api.share_group_type_destroy, 

1742 self.ctxt, share_group_type_1['id']) 

1743 self.assertRaises(exception.ShareGroupTypeInUse, 

1744 db_api.share_group_type_destroy, 

1745 self.ctxt, share_group_type_2['id']) 

1746 # Cleanup share groups 

1747 db_api.share_group_destroy(self.ctxt, share_group_1['id']) 

1748 db_api.share_group_destroy(self.ctxt, share_group_2['id']) 

1749 

1750 # Let's cleanup share_group_type_1 and verify it is gone 

1751 self.assertIsNone(db_api.share_group_type_destroy( 

1752 self.ctxt, share_group_type_1['id'])) 

1753 self.assertDictEqual( 

1754 {}, db_api.share_group_type_specs_get( 

1755 self.ctxt, share_group_type_1['id'])) 

1756 self.assertRaises(exception.ShareGroupTypeNotFound, 

1757 db_api.share_group_type_access_get_all, 

1758 self.ctxt, share_group_type_1['id']) 

1759 self.assertRaises(exception.ShareGroupTypeNotFound, 

1760 db_api.share_group_type_get, 

1761 self.ctxt, share_group_type_1['id']) 

1762 

1763 # share_group_type_2 must still be around 

1764 self.assertEqual(share_group_type_2['id'], 

1765 db_api.share_group_type_get( 

1766 self.ctxt, share_group_type_2['id'])['id']) 

1767 

1768 

1769@ddt.ddt 

1770class ShareSnapshotDatabaseAPITestCase(test.TestCase): 

1771 

1772 def setUp(self): 

1773 """Run before each test.""" 

1774 super(ShareSnapshotDatabaseAPITestCase, self).setUp() 

1775 self.ctxt = context.get_admin_context() 

1776 

1777 self.share_instances = [ 

1778 db_utils.create_share_instance( 

1779 status=constants.STATUS_REPLICATION_CHANGE, 

1780 share_id='fake_share_id_1'), 

1781 db_utils.create_share_instance( 

1782 status=constants.STATUS_AVAILABLE, 

1783 share_id='fake_share_id_1'), 

1784 db_utils.create_share_instance( 

1785 status=constants.STATUS_ERROR_DELETING, 

1786 share_id='fake_share_id_2'), 

1787 db_utils.create_share_instance( 

1788 status=constants.STATUS_MANAGING, 

1789 share_id='fake_share_id_2'), 

1790 ] 

1791 self.share_1 = db_utils.create_share( 

1792 id='fake_share_id_1', instances=self.share_instances[0:2]) 

1793 self.share_2 = db_utils.create_share( 

1794 id='fake_share_id_2', instances=self.share_instances[2:-1]) 

1795 self.snapshot_instances = [ 

1796 db_utils.create_snapshot_instance( 

1797 'fake_snapshot_id_1', 

1798 status=constants.STATUS_CREATING, 

1799 share_instance_id=self.share_instances[0]['id']), 

1800 db_utils.create_snapshot_instance( 

1801 'fake_snapshot_id_1', 

1802 status=constants.STATUS_ERROR, 

1803 share_instance_id=self.share_instances[1]['id']), 

1804 db_utils.create_snapshot_instance( 

1805 'fake_snapshot_id_1', 

1806 status=constants.STATUS_DELETING, 

1807 share_instance_id=self.share_instances[2]['id']), 

1808 db_utils.create_snapshot_instance( 

1809 'fake_snapshot_id_2', 

1810 status=constants.STATUS_AVAILABLE, 

1811 id='fake_snapshot_instance_id', 

1812 provider_location='hogsmeade:snapshot1', 

1813 progress='87%', 

1814 share_instance_id=self.share_instances[3]['id']), 

1815 ] 

1816 self.snapshot_1 = db_utils.create_snapshot( 

1817 id='fake_snapshot_id_1', share_id=self.share_1['id'], 

1818 instances=self.snapshot_instances[0:3]) 

1819 self.snapshot_2 = db_utils.create_snapshot( 

1820 id='fake_snapshot_id_2', share_id=self.share_2['id'], 

1821 instances=self.snapshot_instances[3:4], metadata={'foo': 'bar'}) 

1822 

1823 self.snapshot_instance_export_locations = [ 

1824 db_utils.create_snapshot_instance_export_locations( 

1825 self.snapshot_instances[0].id, 

1826 path='1.1.1.1:/fake_path', 

1827 is_admin_only=True), 

1828 db_utils.create_snapshot_instance_export_locations( 

1829 self.snapshot_instances[1].id, 

1830 path='2.2.2.2:/fake_path', 

1831 is_admin_only=True), 

1832 db_utils.create_snapshot_instance_export_locations( 

1833 self.snapshot_instances[2].id, 

1834 path='3.3.3.3:/fake_path', 

1835 is_admin_only=True), 

1836 db_utils.create_snapshot_instance_export_locations( 

1837 self.snapshot_instances[3].id, 

1838 path='4.4.4.4:/fake_path', 

1839 is_admin_only=True) 

1840 ] 

1841 

1842 def test_create(self): 

1843 share = db_utils.create_share(size=1) 

1844 values = { 

1845 'share_id': share['id'], 

1846 'size': share['size'], 

1847 'user_id': share['user_id'], 

1848 'project_id': share['project_id'], 

1849 'status': constants.STATUS_CREATING, 

1850 'progress': '0%', 

1851 'share_size': share['size'], 

1852 'display_name': 'fake', 

1853 'display_description': 'fake', 

1854 'share_proto': share['share_proto'] 

1855 } 

1856 

1857 actual_result = db_api.share_snapshot_create( 

1858 self.ctxt, values, create_snapshot_instance=True) 

1859 

1860 self.assertEqual(1, len(actual_result.instances)) 

1861 self.assertSubDictMatch(values, actual_result.to_dict()) 

1862 

1863 @ddt.data( 

1864 ({'with_count': True}, 3, 3), 

1865 ({'with_count': True, 'limit': 2}, 3, 2) 

1866 ) 

1867 @ddt.unpack 

1868 def test_share_snapshot_get_all_with_count(self, filters, 

1869 amount_of_share_snapshots, 

1870 expected_share_snapshots_len): 

1871 share = db_utils.create_share(size=1) 

1872 values = { 

1873 'share_id': share['id'], 

1874 'size': share['size'], 

1875 'user_id': share['user_id'], 

1876 'project_id': share['project_id'], 

1877 'status': constants.STATUS_CREATING, 

1878 'progress': '0%', 

1879 'share_size': share['size'], 

1880 'display_description': 'fake_count_test', 

1881 'share_proto': share['share_proto'], 

1882 } 

1883 

1884 # consider only shares created in this function 

1885 filters.update({'share_id': share['id']}) 

1886 

1887 for i in range(amount_of_share_snapshots): 

1888 tmp_values = copy.deepcopy(values) 

1889 tmp_values['display_name'] = 'fake_name_%s' % str(i) 

1890 db_api.share_snapshot_create(self.ctxt, tmp_values) 

1891 

1892 limit = filters.get('limit') 

1893 count, share_snapshots = db_api.share_snapshot_get_all_with_count( 

1894 self.ctxt, filters=filters, limit=limit) 

1895 

1896 self.assertEqual(count, amount_of_share_snapshots) 

1897 self.assertEqual(expected_share_snapshots_len, len(share_snapshots)) 

1898 

1899 def test_share_snapshot_get_all_with_filters_some(self): 

1900 expected_status = constants.STATUS_AVAILABLE 

1901 filters = { 

1902 'status': expected_status, 

1903 'metadata': {'foo': 'bar'} 

1904 } 

1905 snapshots = db_api.share_snapshot_get_all(self.ctxt, filters=filters) 

1906 

1907 self.assertEqual(1, len(snapshots)) 

1908 

1909 for snapshot in snapshots: 

1910 s = snapshot.get('share_snapshot_metadata') 

1911 for k, v in filters['metadata'].items(): 

1912 filter_meta_key = k 

1913 filter_meta_val = v 

1914 self.assertEqual('fake_snapshot_id_2', snapshot['id']) 

1915 self.assertEqual(snapshot['status'], filters['status']) 

1916 self.assertEqual(s[0]['key'], filter_meta_key) 

1917 self.assertEqual(s[0]['value'], filter_meta_val) 

1918 

1919 def test_share_snapshot_get_latest_for_share(self): 

1920 

1921 share = db_utils.create_share(size=1) 

1922 values = { 

1923 'share_id': share['id'], 

1924 'size': share['size'], 

1925 'user_id': share['user_id'], 

1926 'project_id': share['project_id'], 

1927 'status': constants.STATUS_CREATING, 

1928 'progress': '0%', 

1929 'share_size': share['size'], 

1930 'display_description': 'fake', 

1931 'share_proto': share['share_proto'], 

1932 } 

1933 values1 = copy.deepcopy(values) 

1934 values1['display_name'] = 'snap1' 

1935 db_api.share_snapshot_create(self.ctxt, values1) 

1936 values2 = copy.deepcopy(values) 

1937 values2['display_name'] = 'snap2' 

1938 db_api.share_snapshot_create(self.ctxt, values2) 

1939 values3 = copy.deepcopy(values) 

1940 values3['display_name'] = 'snap3' 

1941 db_api.share_snapshot_create(self.ctxt, values3) 

1942 

1943 result = db_api.share_snapshot_get_latest_for_share(self.ctxt, 

1944 share['id']) 

1945 

1946 self.assertSubDictMatch(values3, result.to_dict()) 

1947 

1948 def test_get_instance(self): 

1949 snapshot = db_utils.create_snapshot(with_share=True) 

1950 

1951 instance = db_api.share_snapshot_instance_get( 

1952 self.ctxt, snapshot.instance['id'], with_share_data=True) 

1953 instance_dict = instance.to_dict() 

1954 

1955 self.assertTrue(hasattr(instance, 'name')) 

1956 self.assertTrue(hasattr(instance, 'share_name')) 

1957 self.assertTrue(hasattr(instance, 'share_id')) 

1958 self.assertIn('name', instance_dict) 

1959 self.assertIn('share_name', instance_dict) 

1960 

1961 @ddt.data(None, constants.STATUS_ERROR) 

1962 def test_share_snapshot_instance_get_all_with_filters_some(self, status): 

1963 expected_status = status or (constants.STATUS_CREATING, 

1964 constants.STATUS_DELETING) 

1965 expected_number = 1 if status else 2 

1966 filters = { 

1967 'snapshot_ids': 'fake_snapshot_id_1', 

1968 'statuses': expected_status 

1969 } 

1970 instances = db_api.share_snapshot_instance_get_all_with_filters( 

1971 self.ctxt, filters) 

1972 

1973 for instance in instances: 

1974 self.assertEqual('fake_snapshot_id_1', instance['snapshot_id']) 

1975 self.assertIn(instance['status'], filters['statuses']) 

1976 

1977 self.assertEqual(expected_number, len(instances)) 

1978 

1979 def test_share_snapshot_instance_get_all_with_filters_all_filters(self): 

1980 filters = { 

1981 'snapshot_ids': 'fake_snapshot_id_2', 

1982 'instance_ids': 'fake_snapshot_instance_id', 

1983 'statuses': constants.STATUS_AVAILABLE, 

1984 'share_instance_ids': self.share_instances[3]['id'], 

1985 } 

1986 instances = db_api.share_snapshot_instance_get_all_with_filters( 

1987 self.ctxt, filters, with_share_data=True) 

1988 self.assertEqual(1, len(instances)) 

1989 self.assertEqual('fake_snapshot_instance_id', instances[0]['id']) 

1990 self.assertEqual( 

1991 self.share_2['id'], instances[0]['share_instance']['share_id']) 

1992 

1993 def test_share_snapshot_instance_get_all_with_filters_wrong_filters(self): 

1994 filters = { 

1995 'some_key': 'some_value', 

1996 'some_other_key': 'some_other_value', 

1997 } 

1998 instances = db_api.share_snapshot_instance_get_all_with_filters( 

1999 self.ctxt, filters) 

2000 self.assertEqual(4, len(instances)) 

2001 

2002 def test_share_snapshot_instance_create(self): 

2003 snapshot = db_utils.create_snapshot(with_share=True) 

2004 share = snapshot['share'] 

2005 share_instance = db_utils.create_share_instance(share_id=share['id']) 

2006 values = { 

2007 'snapshot_id': snapshot['id'], 

2008 'share_instance_id': share_instance['id'], 

2009 'status': constants.STATUS_MANAGING, 

2010 'progress': '88%', 

2011 'provider_location': 'whomping_willow', 

2012 } 

2013 

2014 actual_result = db_api.share_snapshot_instance_create( 

2015 self.ctxt, snapshot['id'], values) 

2016 

2017 snapshot = db_api.share_snapshot_get(self.ctxt, snapshot['id']) 

2018 

2019 self.assertSubDictMatch(values, actual_result.to_dict()) 

2020 self.assertEqual(2, len(snapshot['instances'])) 

2021 

2022 def test_share_snapshot_instance_update(self): 

2023 snapshot = db_utils.create_snapshot(with_share=True) 

2024 

2025 values = { 

2026 'snapshot_id': snapshot['id'], 

2027 'status': constants.STATUS_ERROR, 

2028 'progress': '18%', 

2029 'provider_location': 'godrics_hollow', 

2030 } 

2031 

2032 actual_result = db_api.share_snapshot_instance_update( 

2033 self.ctxt, snapshot['instance']['id'], values) 

2034 

2035 self.assertSubDictMatch(values, actual_result.to_dict()) 

2036 

2037 @ddt.data(2, 1) 

2038 def test_share_snapshot_instance_delete(self, instances): 

2039 snapshot = db_utils.create_snapshot(with_share=True) 

2040 first_instance_id = snapshot['instance']['id'] 

2041 if instances > 1: 

2042 instance = db_utils.create_snapshot_instance( 

2043 snapshot['id'], 

2044 share_instance_id=snapshot['share']['instance']['id']) 

2045 else: 

2046 instance = snapshot['instance'] 

2047 

2048 retval = db_api.share_snapshot_instance_delete( 

2049 self.ctxt, instance['id']) 

2050 

2051 self.assertIsNone(retval) 

2052 if instances == 1: 

2053 self.assertRaises(exception.ShareSnapshotNotFound, 

2054 db_api.share_snapshot_get, 

2055 self.ctxt, snapshot['id']) 

2056 else: 

2057 snapshot = db_api.share_snapshot_get(self.ctxt, snapshot['id']) 

2058 self.assertEqual(1, len(snapshot['instances'])) 

2059 self.assertEqual(first_instance_id, snapshot['instance']['id']) 

2060 

2061 def test_share_snapshot_access_create(self): 

2062 values = { 

2063 'share_snapshot_id': self.snapshot_1['id'], 

2064 } 

2065 actual_result = db_api.share_snapshot_access_create(self.ctxt, 

2066 values) 

2067 

2068 self.assertSubDictMatch(values, actual_result.to_dict()) 

2069 

2070 def test_share_snapshot_instance_access_get_all(self): 

2071 access = db_utils.create_snapshot_access( 

2072 share_snapshot_id=self.snapshot_1['id']) 

2073 

2074 # NOTE(zzzeek) the create_snapshot_access routine iterates through the 

2075 # ShareSnapshot.instances collection and creates a new 

2076 # ShareSnapshotInstanceAccessMapping for each ShareSnapshotInstance. 

2077 # however, this collection is unordered and does not have any guarantee 

2078 # that its ordering would match that of our self.snapshot_instances 

2079 # collection. Therefore key the fixture values and the resulting 

2080 # ShareSnapshotInstanceAccessMapping objects by share_snapshot_id 

2081 # and compare individually. 

2082 

2083 values_by_sid = { 

2084 snapshot_instance.id: { 

2085 'share_snapshot_instance_id': snapshot_instance.id, 

2086 'access_id': access['id'] 

2087 } 

2088 for snapshot_instance in self.snapshot_instances 

2089 if "fake" not in snapshot_instance.id 

2090 } 

2091 

2092 rules_by_sid = { 

2093 rule.share_snapshot_instance_id: rule 

2094 for rule in db_api.share_snapshot_instance_access_get_all( 

2095 self.ctxt, access['id'] 

2096 ) 

2097 } 

2098 

2099 for sid in values_by_sid: 

2100 self.assertSubDictMatch( 

2101 values_by_sid[sid], 

2102 rules_by_sid[sid].to_dict() 

2103 ) 

2104 

2105 def test_share_snapshot_access_get(self): 

2106 access = db_utils.create_snapshot_access( 

2107 share_snapshot_id=self.snapshot_1['id']) 

2108 values = {'share_snapshot_id': self.snapshot_1['id']} 

2109 

2110 actual_value = db_api.share_snapshot_access_get( 

2111 self.ctxt, access['id']) 

2112 

2113 self.assertSubDictMatch(values, actual_value.to_dict()) 

2114 

2115 def test_share_snapshot_access_get_all_for_share_snapshot(self): 

2116 access = db_utils.create_snapshot_access( 

2117 share_snapshot_id=self.snapshot_1['id']) 

2118 values = {'access_type': access['access_type'], 

2119 'access_to': access['access_to'], 

2120 'share_snapshot_id': self.snapshot_1['id']} 

2121 

2122 actual_value = db_api.share_snapshot_access_get_all_for_share_snapshot( 

2123 self.ctxt, self.snapshot_1['id'], {}) 

2124 

2125 self.assertSubDictMatch(values, actual_value[0].to_dict()) 

2126 

2127 @ddt.data({'existing': {'access_type': 'cephx', 'access_to': 'alice'}, 

2128 'new': {'access_type': 'user', 'access_to': 'alice'}, 

2129 'result': False}, 

2130 {'existing': {'access_type': 'user', 'access_to': 'bob'}, 

2131 'new': {'access_type': 'user', 'access_to': 'bob'}, 

2132 'result': True}, 

2133 {'existing': {'access_type': 'ip', 'access_to': '10.0.0.10/32'}, 

2134 'new': {'access_type': 'ip', 'access_to': '10.0.0.10'}, 

2135 'result': True}, 

2136 {'existing': {'access_type': 'ip', 'access_to': '10.10.0.11'}, 

2137 'new': {'access_type': 'ip', 'access_to': '10.10.0.11'}, 

2138 'result': True}, 

2139 {'existing': {'access_type': 'ip', 'access_to': 'fd21::11'}, 

2140 'new': {'access_type': 'ip', 'access_to': 'fd21::11'}, 

2141 'result': True}, 

2142 {'existing': {'access_type': 'ip', 'access_to': 'fd21::10'}, 

2143 'new': {'access_type': 'ip', 'access_to': 'fd21::10/128'}, 

2144 'result': True}, 

2145 {'existing': {'access_type': 'ip', 'access_to': '10.10.0.0/22'}, 

2146 'new': {'access_type': 'ip', 'access_to': '10.10.0.0/24'}, 

2147 'result': False}, 

2148 {'existing': {'access_type': 'ip', 'access_to': '2620:52::/48'}, 

2149 'new': {'access_type': 'ip', 

2150 'access_to': '2620:52:0:13b8::/64'}, 

2151 'result': False}) 

2152 @ddt.unpack 

2153 def test_share_snapshot_check_for_existing_access(self, existing, new, 

2154 result): 

2155 db_utils.create_snapshot_access( 

2156 share_snapshot_id=self.snapshot_1['id'], 

2157 access_type=existing['access_type'], 

2158 access_to=existing['access_to']) 

2159 

2160 rule_exists = db_api.share_snapshot_check_for_existing_access( 

2161 self.ctxt, self.snapshot_1['id'], new['access_type'], 

2162 new['access_to']) 

2163 

2164 self.assertEqual(result, rule_exists) 

2165 

2166 def test_share_snapshot_access_get_all_for_snapshot_instance(self): 

2167 access = db_utils.create_snapshot_access( 

2168 share_snapshot_id=self.snapshot_1['id']) 

2169 values = {'access_type': access['access_type'], 

2170 'access_to': access['access_to'], 

2171 'share_snapshot_id': self.snapshot_1['id']} 

2172 

2173 out = db_api.share_snapshot_access_get_all_for_snapshot_instance( 

2174 self.ctxt, self.snapshot_instances[0].id) 

2175 

2176 self.assertSubDictMatch(values, out[0].to_dict()) 

2177 

2178 def test_share_snapshot_instance_access_update_state(self): 

2179 access = db_utils.create_snapshot_access( 

2180 share_snapshot_id=self.snapshot_1['id']) 

2181 values = {'state': constants.STATUS_ACTIVE, 

2182 'access_id': access['id'], 

2183 'share_snapshot_instance_id': self.snapshot_instances[0].id} 

2184 

2185 actual_result = db_api.share_snapshot_instance_access_update( 

2186 self.ctxt, access['id'], self.snapshot_1.instance['id'], 

2187 {'state': constants.STATUS_ACTIVE}) 

2188 

2189 self.assertSubDictMatch(values, actual_result.to_dict()) 

2190 self.assertIsNotNone(actual_result['updated_at']) 

2191 time_now = timeutils.utcnow() 

2192 self.assertTrue(actual_result['updated_at'] < time_now) 

2193 

2194 def test_share_snapshot_instance_access_get(self): 

2195 access = db_utils.create_snapshot_access( 

2196 share_snapshot_id=self.snapshot_1['id']) 

2197 values = {'access_id': access['id'], 

2198 'share_snapshot_instance_id': self.snapshot_instances[0].id} 

2199 

2200 actual_result = db_api.share_snapshot_instance_access_get( 

2201 self.ctxt, access['id'], self.snapshot_instances[0].id) 

2202 

2203 self.assertSubDictMatch(values, actual_result.to_dict()) 

2204 

2205 def test_share_snapshot_instance_access_delete(self): 

2206 access = db_utils.create_snapshot_access( 

2207 share_snapshot_id=self.snapshot_1['id']) 

2208 

2209 db_api.share_snapshot_instance_access_delete( 

2210 self.ctxt, access['id'], self.snapshot_1.instance['id']) 

2211 

2212 def test_share_snapshot_instance_export_location_create(self): 

2213 values = { 

2214 'share_snapshot_instance_id': self.snapshot_instances[0].id, 

2215 } 

2216 

2217 actual_result = db_api.share_snapshot_instance_export_location_create( 

2218 self.ctxt, values) 

2219 

2220 self.assertSubDictMatch(values, actual_result.to_dict()) 

2221 

2222 def test_share_snapshot_export_locations_get(self): 

2223 out = db_api.share_snapshot_export_locations_get( 

2224 self.ctxt, self.snapshot_1['id']) 

2225 

2226 keys = ['share_snapshot_instance_id', 'path', 'is_admin_only'] 

2227 for expected, actual in zip(self.snapshot_instance_export_locations, 

2228 out): 

2229 [self.assertEqual(expected[k], actual[k]) for k in keys] 

2230 

2231 def test_share_snapshot_instance_export_locations_get(self): 

2232 out = db_api.share_snapshot_instance_export_locations_get_all( 

2233 self.ctxt, self.snapshot_instances[0].id) 

2234 

2235 keys = ['share_snapshot_instance_id', 'path', 'is_admin_only'] 

2236 for key in keys: 

2237 self.assertEqual(self.snapshot_instance_export_locations[0][key], 

2238 out[0][key]) 

2239 

2240 def test_share_snapshot_instance_export_locations_update(self): 

2241 snapshot = db_utils.create_snapshot(with_share=True) 

2242 initial_locations = ['fake1/1/', 'fake2/2', 'fake3/3'] 

2243 update_locations = ['fake4/4', 'fake2/2', 'fake3/3'] 

2244 

2245 # add initial locations 

2246 db_api.share_snapshot_instance_export_locations_update( 

2247 self.ctxt, snapshot.instance['id'], initial_locations, False) 

2248 # update locations 

2249 db_api.share_snapshot_instance_export_locations_update( 

2250 self.ctxt, snapshot.instance['id'], update_locations, True) 

2251 

2252 get_result = db_api.share_snapshot_instance_export_locations_get_all( 

2253 self.ctxt, snapshot.instance['id']) 

2254 result_locations = [el['path'] for el in get_result] 

2255 

2256 self.assertEqual(sorted(result_locations), sorted(update_locations)) 

2257 

2258 def test_share_snapshot_instance_export_locations_update_wrong_type(self): 

2259 snapshot = db_utils.create_snapshot(with_share=True) 

2260 new_export_locations = [1] 

2261 

2262 self.assertRaises( 

2263 exception.ManilaException, 

2264 db_api.share_snapshot_instance_export_locations_update, 

2265 self.ctxt, snapshot.instance['id'], new_export_locations, False) 

2266 

2267 def test_share_snapshot_metadata_get(self): 

2268 metadata = {'a': 'b', 'c': 'd'} 

2269 

2270 self.share_1 = db_utils.create_share(size=1) 

2271 self.snapshot_1 = db_utils.create_snapshot( 

2272 share_id=self.share_1['id']) 

2273 db_api.share_snapshot_metadata_update( 

2274 self.ctxt, share_snapshot_id=self.snapshot_1['id'], 

2275 metadata=metadata, delete=False) 

2276 self.assertEqual( 

2277 metadata, db_api.share_snapshot_metadata_get( 

2278 self.ctxt, share_snapshot_id=self.snapshot_1['id'])) 

2279 

2280 def test_share_snapshot_metadata_get_item(self): 

2281 metadata = {'a': 'b', 'c': 'd'} 

2282 key = 'a' 

2283 shouldbe = {'a': 'b'} 

2284 self.share_1 = db_utils.create_share(size=1) 

2285 self.snapshot_1 = db_utils.create_snapshot( 

2286 share_id=self.share_1['id']) 

2287 db_api.share_snapshot_metadata_update( 

2288 self.ctxt, share_snapshot_id=self.snapshot_1['id'], 

2289 metadata=metadata, delete=False) 

2290 self.assertEqual( 

2291 shouldbe, db_api.share_snapshot_metadata_get_item( 

2292 self.ctxt, share_snapshot_id=self.snapshot_1['id'], 

2293 key=key)) 

2294 

2295 def test_share_snapshot_metadata_update(self): 

2296 metadata1 = {'a': '1', 'c': '2'} 

2297 metadata2 = {'a': '3', 'd': '5'} 

2298 should_be = {'a': '3', 'c': '2', 'd': '5'} 

2299 self.share_1 = db_utils.create_share(size=1) 

2300 self.snapshot_1 = db_utils.create_snapshot( 

2301 share_id=self.share_1['id']) 

2302 db_api.share_snapshot_metadata_update( 

2303 self.ctxt, share_snapshot_id=self.snapshot_1['id'], 

2304 metadata=metadata1, delete=False) 

2305 db_api.share_snapshot_metadata_update( 

2306 self.ctxt, share_snapshot_id=self.snapshot_1['id'], 

2307 metadata=metadata2, delete=False) 

2308 self.assertEqual( 

2309 should_be, db_api.share_snapshot_metadata_get( 

2310 self.ctxt, share_snapshot_id=self.snapshot_1['id'])) 

2311 

2312 def test_share_snapshot_metadata_delete(self): 

2313 key = 'a' 

2314 metadata = {'a': '1', 'c': '2'} 

2315 should_be = {'c': '2'} 

2316 self.share_1 = db_utils.create_share(size=1) 

2317 self.snapshot_1 = db_utils.create_snapshot( 

2318 share_id=self.share_1['id']) 

2319 db_api.share_snapshot_metadata_update( 

2320 self.ctxt, share_snapshot_id=self.snapshot_1['id'], 

2321 metadata=metadata, delete=False) 

2322 db_api.share_snapshot_metadata_delete( 

2323 self.ctxt, share_snapshot_id=self.snapshot_1['id'], 

2324 key=key) 

2325 self.assertEqual( 

2326 should_be, db_api.share_snapshot_metadata_get( 

2327 self.ctxt, share_snapshot_id=self.snapshot_1['id'])) 

2328 

2329 

2330class ShareExportLocationsDatabaseAPITestCase(test.TestCase): 

2331 

2332 def setUp(self): 

2333 super(ShareExportLocationsDatabaseAPITestCase, self).setUp() 

2334 self.ctxt = context.get_admin_context() 

2335 

2336 def test_update_valid_order(self): 

2337 share = db_utils.create_share() 

2338 initial_locations = ['fake1/1/', 'fake2/2', 'fake3/3'] 

2339 update_locations = ['fake4/4', 'fake2/2', 'fake3/3'] 

2340 

2341 # add initial locations 

2342 db_api.export_locations_update( 

2343 self.ctxt, share.instance['id'], initial_locations, False) 

2344 # update locations 

2345 db_api.export_locations_update( 

2346 self.ctxt, share.instance['id'], update_locations, True) 

2347 actual_result = db_api.export_location_get_all( 

2348 self.ctxt, share['id']) 

2349 

2350 # actual result should contain locations in exact same order 

2351 self.assertEqual(actual_result, update_locations) 

2352 

2353 def test_update_export_locations_with_metadata(self): 

2354 share = db_utils.create_share() 

2355 original_export_locations = [ 

2356 { 

2357 'path': 'fake1/1/', 

2358 'is_admin_only': True, 

2359 'metadata': { 

2360 'foo': 'bar', 

2361 'preferred': '1' 

2362 }, 

2363 }, 

2364 { 

2365 'path': 'fake2/1/', 

2366 'is_admin_only': True, 

2367 'metadata': { 

2368 'clem': 'son', 

2369 'preferred': '0' 

2370 }, 

2371 }, 

2372 ] 

2373 

2374 # add initial locations 

2375 db_api.export_locations_update( 

2376 self.ctxt, share.instance['id'], original_export_locations, False) 

2377 

2378 updated_export_locations = [ 

2379 { 

2380 'path': 'fake1/1/', 

2381 'is_admin_only': True, 

2382 'metadata': { 

2383 'foo': 'quz', 

2384 'preferred': '0' 

2385 }, 

2386 }, 

2387 { 

2388 'path': 'fake2/1/', 

2389 'is_admin_only': True, 

2390 'metadata': { 

2391 'clem': 'son', 

2392 'preferred': '1', 

2393 }, 

2394 }, 

2395 ] 

2396 

2397 # update locations 

2398 db_api.export_locations_update( 

2399 self.ctxt, share.instance['id'], updated_export_locations, True) 

2400 actual_result = db_api.export_location_get_all_by_share_id( 

2401 self.ctxt, share['id']) 

2402 

2403 actual_export_locations = [ 

2404 { 

2405 'path': el['path'], 

2406 'is_admin_only': el['is_admin_only'], 

2407 'metadata': el['el_metadata'], 

2408 } for el in actual_result 

2409 ] 

2410 self.assertEqual(updated_export_locations, actual_export_locations) 

2411 

2412 def test_update_string(self): 

2413 share = db_utils.create_share() 

2414 initial_location = 'fake1/1/' 

2415 

2416 db_api.export_locations_update( 

2417 self.ctxt, share.instance['id'], initial_location, False) 

2418 actual_result = db_api.export_location_get_all( 

2419 self.ctxt, share['id']) 

2420 

2421 self.assertEqual(actual_result, [initial_location]) 

2422 

2423 def test_get_admin_export_locations(self): 

2424 ctxt_user = context.RequestContext( 

2425 user_id='fake user', project_id='fake project', is_admin=False) 

2426 share = db_utils.create_share() 

2427 locations = [ 

2428 {'path': 'fake1/1/', 'is_admin_only': True}, 

2429 {'path': 'fake2/2/', 'is_admin_only': True}, 

2430 {'path': 'fake3/3/', 'is_admin_only': True}, 

2431 ] 

2432 

2433 db_api.export_locations_update( 

2434 self.ctxt, share.instance['id'], locations, delete=False) 

2435 

2436 user_result = db_api.export_location_get_all(ctxt_user, share['id']) 

2437 self.assertEqual([], user_result) 

2438 

2439 admin_result = db_api.export_location_get_all( 

2440 self.ctxt, share['id']) 

2441 self.assertEqual(3, len(admin_result)) 

2442 for location in locations: 

2443 self.assertIn(location['path'], admin_result) 

2444 

2445 def test_get_user_export_locations(self): 

2446 ctxt_user = context.RequestContext( 

2447 user_id='fake user', project_id='fake project', is_admin=False) 

2448 share = db_utils.create_share() 

2449 locations = [ 

2450 {'path': 'fake1/1/', 'is_admin_only': False}, 

2451 {'path': 'fake2/2/', 'is_admin_only': False}, 

2452 {'path': 'fake3/3/', 'is_admin_only': False}, 

2453 ] 

2454 

2455 db_api.export_locations_update( 

2456 self.ctxt, share.instance['id'], locations, delete=False) 

2457 

2458 user_result = db_api.export_location_get_all(ctxt_user, share['id']) 

2459 self.assertEqual(3, len(user_result)) 

2460 for location in locations: 

2461 self.assertIn(location['path'], user_result) 

2462 

2463 admin_result = db_api.export_location_get_all( 

2464 self.ctxt, share['id']) 

2465 self.assertEqual(3, len(admin_result)) 

2466 for location in locations: 

2467 self.assertIn(location['path'], admin_result) 

2468 

2469 def test_get_user_export_locations_old_view(self): 

2470 ctxt_user = context.RequestContext( 

2471 user_id='fake user', project_id='fake project', is_admin=False) 

2472 share = db_utils.create_share() 

2473 locations = ['fake1/1/', 'fake2/2', 'fake3/3'] 

2474 

2475 db_api.export_locations_update( 

2476 self.ctxt, share.instance['id'], locations, delete=False) 

2477 

2478 user_result = db_api.export_location_get_all(ctxt_user, share['id']) 

2479 self.assertEqual(locations, user_result) 

2480 

2481 admin_result = db_api.export_location_get_all( 

2482 self.ctxt, share['id']) 

2483 self.assertEqual(locations, admin_result) 

2484 

2485 

2486@ddt.ddt 

2487class ShareInstanceExportLocationsMetadataDatabaseAPITestCase(test.TestCase): 

2488 

2489 def setUp(self): 

2490 clname = ShareInstanceExportLocationsMetadataDatabaseAPITestCase 

2491 super(clname, self).setUp() 

2492 self.ctxt = context.get_admin_context() 

2493 share_id = 'fake_share_id' 

2494 instances = [ 

2495 db_utils.create_share_instance( 

2496 share_id=share_id, 

2497 status=constants.STATUS_AVAILABLE), 

2498 db_utils.create_share_instance( 

2499 share_id=share_id, 

2500 status=constants.STATUS_MIGRATING), 

2501 db_utils.create_share_instance( 

2502 share_id=share_id, 

2503 status=constants.STATUS_MIGRATING_TO), 

2504 ] 

2505 self.share = db_utils.create_share( 

2506 id=share_id, 

2507 instances=instances) 

2508 self.initial_locations = ['/fake/foo/', '/fake/bar', '/fake/quuz'] 

2509 self.shown_locations = ['/fake/foo/', '/fake/bar'] 

2510 for i in range(0, 3): 

2511 db_api.export_locations_update( 

2512 self.ctxt, instances[i]['id'], self.initial_locations[i], 

2513 delete=False) 

2514 

2515 def _get_export_location_uuid_by_path(self, path): 

2516 els = db_api.export_location_get_all_by_share_id( 

2517 self.ctxt, self.share.id) 

2518 export_location_uuid = None 

2519 for el in els: 

2520 if el.path == path: 

2521 export_location_uuid = el.uuid 

2522 self.assertIsNotNone(export_location_uuid) 

2523 return export_location_uuid 

2524 

2525 def test_get_export_locations_by_share_id(self): 

2526 els = db_api.export_location_get_all_by_share_id( 

2527 self.ctxt, self.share.id) 

2528 self.assertEqual(3, len(els)) 

2529 for path in self.shown_locations: 

2530 self.assertTrue(any([path in el.path for el in els])) 

2531 

2532 def test_get_export_locations_by_share_id_ignore_migration_dest(self): 

2533 els = db_api.export_location_get_all_by_share_id( 

2534 self.ctxt, self.share.id, ignore_migration_destination=True) 

2535 self.assertEqual(2, len(els)) 

2536 for path in self.shown_locations: 

2537 self.assertTrue(any([path in el.path for el in els])) 

2538 

2539 def test_get_export_locations_by_share_instance_id(self): 

2540 els = db_api.export_location_get_all_by_share_instance_id( 

2541 self.ctxt, self.share.instance.id) 

2542 self.assertEqual(1, len(els)) 

2543 for path in [self.shown_locations[1]]: 

2544 self.assertTrue(any([path in el.path for el in els])) 

2545 

2546 def test_export_location_metadata_update_delete(self): 

2547 export_location_uuid = self._get_export_location_uuid_by_path( 

2548 self.initial_locations[0]) 

2549 metadata = { 

2550 'foo_key': 'foo_value', 

2551 'bar_key': 'bar_value', 

2552 'quuz_key': 'quuz_value', 

2553 } 

2554 

2555 db_api.export_location_metadata_update( 

2556 self.ctxt, export_location_uuid, metadata, False) 

2557 

2558 db_api.export_location_metadata_delete( 

2559 self.ctxt, export_location_uuid, list(metadata.keys())[0:-1]) 

2560 

2561 result = db_api.export_location_metadata_get( 

2562 self.ctxt, export_location_uuid) 

2563 

2564 key = list(metadata.keys())[-1] 

2565 self.assertEqual({key: metadata[key]}, result) 

2566 

2567 db_api.export_location_metadata_delete( 

2568 self.ctxt, export_location_uuid) 

2569 

2570 result = db_api.export_location_metadata_get( 

2571 self.ctxt, export_location_uuid) 

2572 self.assertEqual({}, result) 

2573 

2574 def test_export_location_metadata_update_get(self): 

2575 # Write metadata for target export location 

2576 export_location_uuid = self._get_export_location_uuid_by_path( 

2577 self.initial_locations[0]) 

2578 metadata = {'foo_key': 'foo_value', 'bar_key': 'bar_value'} 

2579 db_api.export_location_metadata_update( 

2580 self.ctxt, export_location_uuid, metadata, False) 

2581 

2582 # Write metadata for some concurrent export location 

2583 other_export_location_uuid = self._get_export_location_uuid_by_path( 

2584 self.initial_locations[1]) 

2585 other_metadata = {'key_from_other_el': 'value_of_key_from_other_el'} 

2586 db_api.export_location_metadata_update( 

2587 self.ctxt, other_export_location_uuid, other_metadata, False) 

2588 

2589 result = db_api.export_location_metadata_get( 

2590 self.ctxt, export_location_uuid) 

2591 

2592 self.assertEqual(metadata, result) 

2593 

2594 updated_metadata = { 

2595 'foo_key': metadata['foo_key'], 

2596 'quuz_key': 'quuz_value', 

2597 } 

2598 

2599 db_api.export_location_metadata_update( 

2600 self.ctxt, export_location_uuid, updated_metadata, True) 

2601 

2602 result = db_api.export_location_metadata_get( 

2603 self.ctxt, export_location_uuid) 

2604 

2605 self.assertEqual(updated_metadata, result) 

2606 

2607 def test_export_location_metadata_get_item(self): 

2608 export_location_uuid = self._get_export_location_uuid_by_path( 

2609 self.initial_locations[0]) 

2610 metadata = {'foo_key': 'foo_value', 'bar_key': 'bar_value'} 

2611 db_api.export_location_metadata_update( 

2612 self.ctxt, export_location_uuid, metadata, False) 

2613 result = db_api.export_location_metadata_get_item( 

2614 self.ctxt, export_location_uuid, 'foo_key') 

2615 self.assertEqual( 

2616 {'foo_key': 'foo_value'}, result) 

2617 

2618 def test_export_location_metadata_get_item_invalid(self): 

2619 export_location_uuid = self._get_export_location_uuid_by_path( 

2620 self.initial_locations[0]) 

2621 metadata = {'foo_key': 'foo_value', 'bar_key': 'bar_value'} 

2622 db_api.export_location_metadata_update( 

2623 self.ctxt, export_location_uuid, metadata, False) 

2624 self.assertRaises(exception.MetadataItemNotFound, 

2625 db_api.export_location_metadata_get_item, 

2626 self.ctxt, 

2627 export_location_uuid, 

2628 'foo') 

2629 

2630 @ddt.data( 

2631 ("k", "v"), 

2632 ("k" * 256, "v"), 

2633 ("k", "v" * 1024), 

2634 ("k" * 256, "v" * 1024), 

2635 ) 

2636 @ddt.unpack 

2637 def test_set_metadata_with_different_length(self, key, value): 

2638 export_location_uuid = self._get_export_location_uuid_by_path( 

2639 self.initial_locations[1]) 

2640 metadata = {key: value} 

2641 

2642 db_api.export_location_metadata_update( 

2643 self.ctxt, export_location_uuid, metadata, False) 

2644 

2645 result = db_api.export_location_metadata_get( 

2646 self.ctxt, export_location_uuid) 

2647 

2648 self.assertEqual(metadata, result) 

2649 

2650 

2651@ddt.ddt 

2652class DriverPrivateDataDatabaseAPITestCase(test.TestCase): 

2653 

2654 def setUp(self): 

2655 """Run before each test.""" 

2656 super(DriverPrivateDataDatabaseAPITestCase, self).setUp() 

2657 self.ctxt = context.get_admin_context() 

2658 

2659 def _get_driver_test_data(self): 

2660 return uuidutils.generate_uuid() 

2661 

2662 @ddt.data({"details": {"foo": "bar", "tee": "too"}, 

2663 "valid": {"foo": "bar", "tee": "too"}}, 

2664 {"details": {"foo": "bar", "tee": ["test"]}, 

2665 "valid": {"foo": "bar", "tee": str(["test"])}}) 

2666 @ddt.unpack 

2667 def test_update(self, details, valid): 

2668 test_id = self._get_driver_test_data() 

2669 

2670 initial_data = db_api.driver_private_data_get(self.ctxt, test_id) 

2671 db_api.driver_private_data_update(self.ctxt, test_id, details) 

2672 actual_data = db_api.driver_private_data_get(self.ctxt, test_id) 

2673 

2674 self.assertEqual({}, initial_data) 

2675 self.assertEqual(valid, actual_data) 

2676 

2677 @ddt.data({'with_deleted': True, 'append': False}, 

2678 {'with_deleted': True, 'append': True}, 

2679 {'with_deleted': False, 'append': False}, 

2680 {'with_deleted': False, 'append': True}) 

2681 @ddt.unpack 

2682 def test_update_with_more_values(self, with_deleted, append): 

2683 test_id = self._get_driver_test_data() 

2684 details = {"tee": "too"} 

2685 more_details = {"foo": "bar"} 

2686 result = {"tee": "too", "foo": "bar"} 

2687 

2688 db_api.driver_private_data_update(self.ctxt, test_id, details) 

2689 if with_deleted: 

2690 db_api.driver_private_data_delete(self.ctxt, test_id) 

2691 if append: 

2692 more_details.update(details) 

2693 if with_deleted and not append: 

2694 result.pop("tee") 

2695 db_api.driver_private_data_update(self.ctxt, test_id, more_details) 

2696 

2697 actual_result = db_api.driver_private_data_get(self.ctxt, 

2698 test_id) 

2699 

2700 self.assertEqual(result, actual_result) 

2701 

2702 @ddt.data(True, False) 

2703 def test_update_with_duplicate(self, with_deleted): 

2704 test_id = self._get_driver_test_data() 

2705 details = {"tee": "too"} 

2706 

2707 db_api.driver_private_data_update(self.ctxt, test_id, details) 

2708 if with_deleted: 

2709 db_api.driver_private_data_delete(self.ctxt, test_id) 

2710 db_api.driver_private_data_update(self.ctxt, test_id, details) 

2711 

2712 actual_result = db_api.driver_private_data_get(self.ctxt, 

2713 test_id) 

2714 

2715 self.assertEqual(details, actual_result) 

2716 

2717 def test_update_with_delete_existing(self): 

2718 test_id = self._get_driver_test_data() 

2719 details = {"key1": "val1", "key2": "val2", "key3": "val3"} 

2720 details_update = {"key1": "val1_upd", "key4": "new_val"} 

2721 

2722 # Create new details 

2723 db_api.driver_private_data_update(self.ctxt, test_id, details) 

2724 db_api.driver_private_data_update(self.ctxt, test_id, 

2725 details_update, delete_existing=True) 

2726 

2727 actual_result = db_api.driver_private_data_get( 

2728 self.ctxt, test_id) 

2729 

2730 self.assertEqual(details_update, actual_result) 

2731 

2732 def test_get(self): 

2733 test_id = self._get_driver_test_data() 

2734 test_key = "foo" 

2735 test_keys = [test_key, "tee"] 

2736 details = {test_keys[0]: "val", test_keys[1]: "val", "mee": "foo"} 

2737 db_api.driver_private_data_update(self.ctxt, test_id, details) 

2738 

2739 actual_result_all = db_api.driver_private_data_get( 

2740 self.ctxt, test_id) 

2741 actual_result_single_key = db_api.driver_private_data_get( 

2742 self.ctxt, test_id, test_key) 

2743 actual_result_list = db_api.driver_private_data_get( 

2744 self.ctxt, test_id, test_keys) 

2745 

2746 self.assertEqual(details, actual_result_all) 

2747 self.assertEqual(details[test_key], actual_result_single_key) 

2748 self.assertEqual(dict.fromkeys(test_keys, "val"), actual_result_list) 

2749 

2750 def test_delete_single(self): 

2751 test_id = self._get_driver_test_data() 

2752 test_key = "foo" 

2753 details = {test_key: "bar", "tee": "too"} 

2754 valid_result = {"tee": "too"} 

2755 db_api.driver_private_data_update(self.ctxt, test_id, details) 

2756 

2757 db_api.driver_private_data_delete(self.ctxt, test_id, test_key) 

2758 

2759 actual_result = db_api.driver_private_data_get( 

2760 self.ctxt, test_id) 

2761 

2762 self.assertEqual(valid_result, actual_result) 

2763 

2764 def test_delete_all(self): 

2765 test_id = self._get_driver_test_data() 

2766 details = {"foo": "bar", "tee": "too"} 

2767 db_api.driver_private_data_update(self.ctxt, test_id, details) 

2768 

2769 db_api.driver_private_data_delete(self.ctxt, test_id) 

2770 

2771 actual_result = db_api.driver_private_data_get( 

2772 self.ctxt, test_id) 

2773 

2774 self.assertEqual({}, actual_result) 

2775 

2776 

2777@ddt.ddt 

2778class ShareNetworkDatabaseAPITestCase(BaseDatabaseAPITestCase): 

2779 

2780 def __init__(self, *args, **kwargs): 

2781 super(ShareNetworkDatabaseAPITestCase, self).__init__(*args, **kwargs) 

2782 self.fake_context = context.RequestContext(user_id='fake user', 

2783 project_id='fake project', 

2784 is_admin=False) 

2785 

2786 def setUp(self): 

2787 super(ShareNetworkDatabaseAPITestCase, self).setUp() 

2788 self.share_nw_dict = {'id': 'fake network id', 

2789 'project_id': self.fake_context.project_id, 

2790 'user_id': 'fake_user_id', 

2791 'name': 'whatever', 

2792 'description': 'fake description'} 

2793 

2794 def test_create_one_network(self): 

2795 result = db_api.share_network_create(self.fake_context, 

2796 self.share_nw_dict) 

2797 

2798 self._check_fields(expected=self.share_nw_dict, actual=result) 

2799 self.assertEqual(0, len(result['share_instances'])) 

2800 self.assertEqual(0, len(result['security_services'])) 

2801 

2802 def test_create_two_networks_in_different_tenants(self): 

2803 share_nw_dict2 = self.share_nw_dict.copy() 

2804 share_nw_dict2['id'] = None 

2805 share_nw_dict2['project_id'] = 'fake project 2' 

2806 result1 = db_api.share_network_create(self.fake_context, 

2807 self.share_nw_dict) 

2808 result2 = db_api.share_network_create(self.fake_context.elevated(), 

2809 share_nw_dict2) 

2810 

2811 self._check_fields(expected=self.share_nw_dict, actual=result1) 

2812 self._check_fields(expected=share_nw_dict2, actual=result2) 

2813 

2814 def test_create_two_networks_in_one_tenant(self): 

2815 share_nw_dict2 = self.share_nw_dict.copy() 

2816 share_nw_dict2['id'] += "suffix" 

2817 result1 = db_api.share_network_create(self.fake_context, 

2818 self.share_nw_dict) 

2819 result2 = db_api.share_network_create(self.fake_context, 

2820 share_nw_dict2) 

2821 self._check_fields(expected=self.share_nw_dict, actual=result1) 

2822 self._check_fields(expected=share_nw_dict2, actual=result2) 

2823 

2824 def test_create_with_duplicated_id(self): 

2825 db_api.share_network_create(self.fake_context, self.share_nw_dict) 

2826 

2827 self.assertRaises(db_exception.DBDuplicateEntry, 

2828 db_api.share_network_create, 

2829 self.fake_context, 

2830 self.share_nw_dict) 

2831 

2832 def test_get(self): 

2833 db_api.share_network_create(self.fake_context, self.share_nw_dict) 

2834 result = db_api.share_network_get(self.fake_context, 

2835 self.share_nw_dict['id']) 

2836 

2837 self._check_fields(expected=self.share_nw_dict, actual=result) 

2838 self.assertEqual(0, len(result['share_instances'])) 

2839 self.assertEqual(0, len(result['security_services'])) 

2840 

2841 def _create_share_network_for_project(self, project_id): 

2842 ctx = context.RequestContext(user_id='fake user', 

2843 project_id=project_id, 

2844 is_admin=False) 

2845 

2846 share_data = self.share_nw_dict.copy() 

2847 share_data['project_id'] = project_id 

2848 

2849 db_api.share_network_create(ctx, share_data) 

2850 return share_data 

2851 

2852 def test_get_other_tenant_as_admin(self): 

2853 expected = self._create_share_network_for_project('fake project 2') 

2854 result = db_api.share_network_get(self.fake_context.elevated(), 

2855 self.share_nw_dict['id']) 

2856 

2857 self._check_fields(expected=expected, actual=result) 

2858 self.assertEqual(0, len(result['share_instances'])) 

2859 self.assertEqual(0, len(result['security_services'])) 

2860 

2861 def test_get_other_tenant(self): 

2862 self._create_share_network_for_project('fake project 2') 

2863 self.assertRaises(exception.ShareNetworkNotFound, 

2864 db_api.share_network_get, 

2865 self.fake_context, 

2866 self.share_nw_dict['id']) 

2867 

2868 @ddt.data([{'id': 'fake share id1'}], 

2869 [{'id': 'fake share id1'}, {'id': 'fake share id2'}],) 

2870 def test_get_with_shares(self, shares): 

2871 db_api.share_network_create(self.fake_context, self.share_nw_dict) 

2872 share_instances = [] 

2873 for share in shares: 

2874 share.update({'share_network_id': self.share_nw_dict['id']}) 

2875 share_instances.append( 

2876 db_api.share_create(self.fake_context, share).instance 

2877 ) 

2878 

2879 result = db_api.share_network_get(self.fake_context, 

2880 self.share_nw_dict['id']) 

2881 

2882 self.assertEqual(len(shares), len(result['share_instances'])) 

2883 for index, share_instance in enumerate(share_instances): 

2884 self.assertEqual( 

2885 share_instance['share_network_id'], 

2886 result['share_instances'][index]['share_network_id'] 

2887 ) 

2888 

2889 @ddt.data([{'id': 'fake security service id1', 'type': 'fake type'}], 

2890 [{'id': 'fake security service id1', 'type': 'fake type'}, 

2891 {'id': 'fake security service id2', 'type': 'fake type'}]) 

2892 def test_get_with_security_services(self, security_services): 

2893 db_api.share_network_create(self.fake_context, self.share_nw_dict) 

2894 

2895 for service in security_services: 

2896 service.update({'project_id': self.fake_context.project_id}) 

2897 db_api.security_service_create(self.fake_context, service) 

2898 db_api.share_network_add_security_service( 

2899 self.fake_context, self.share_nw_dict['id'], service['id']) 

2900 

2901 result = db_api.share_network_get(self.fake_context, 

2902 self.share_nw_dict['id']) 

2903 

2904 self.assertEqual(len(security_services), 

2905 len(result['security_services'])) 

2906 

2907 for index, service in enumerate(security_services): 

2908 self._check_fields(expected=service, 

2909 actual=result['security_services'][index]) 

2910 

2911 @ddt.data([{'id': 'fake_id_1', 'availability_zone_id': 'None'}], 

2912 [{'id': 'fake_id_2', 'availability_zone_id': 'None'}, 

2913 {'id': 'fake_id_3', 'availability_zone_id': 'fake_az_id'}]) 

2914 def test_get_with_subnets(self, subnets): 

2915 db_api.share_network_create(self.fake_context, self.share_nw_dict) 

2916 

2917 for subnet in subnets: 

2918 subnet['share_network_id'] = self.share_nw_dict['id'] 

2919 db_api.share_network_subnet_create(self.fake_context, subnet) 

2920 

2921 result = db_api.share_network_get(self.fake_context, 

2922 self.share_nw_dict['id']) 

2923 

2924 self.assertEqual(len(subnets), 

2925 len(result['share_network_subnets'])) 

2926 

2927 for index, subnet in enumerate(subnets): 

2928 self._check_fields(expected=subnet, 

2929 actual=result['share_network_subnets'][index]) 

2930 

2931 def test_get_not_found(self): 

2932 self.assertRaises(exception.ShareNetworkNotFound, 

2933 db_api.share_network_get, 

2934 self.fake_context, 

2935 'fake id') 

2936 

2937 def test_delete(self): 

2938 db_api.share_network_create(self.fake_context, self.share_nw_dict) 

2939 db_api.share_network_delete(self.fake_context, 

2940 self.share_nw_dict['id']) 

2941 

2942 self.assertRaises(exception.ShareNetworkNotFound, 

2943 db_api.share_network_get, 

2944 self.fake_context, 

2945 self.share_nw_dict['id']) 

2946 

2947 @ddt.data([{'id': 'fake_id_1', 'availability_zone_id': 'None'}], 

2948 [{'id': 'fake_id_2', 'availability_zone_id': 'None'}, 

2949 {'id': 'fake_id_3', 'availability_zone_id': 'fake_az_id'}]) 

2950 def test_delete_with_subnets(self, subnets): 

2951 db_api.share_network_create(self.fake_context, self.share_nw_dict) 

2952 

2953 for subnet in subnets: 

2954 subnet['share_network_id'] = self.share_nw_dict['id'] 

2955 db_api.share_network_subnet_create(self.fake_context, subnet) 

2956 

2957 db_api.share_network_delete(self.fake_context, 

2958 self.share_nw_dict['id']) 

2959 

2960 self.assertRaises(exception.ShareNetworkSubnetNotFound, 

2961 db_api.share_network_subnet_get, 

2962 self.fake_context, 

2963 subnets[0]['id']) 

2964 

2965 def test_delete_not_found(self): 

2966 self.assertRaises(exception.ShareNetworkNotFound, 

2967 db_api.share_network_delete, 

2968 self.fake_context, 

2969 'fake id') 

2970 

2971 def test_update(self): 

2972 new_name = 'fake_new_name' 

2973 db_api.share_network_create(self.fake_context, self.share_nw_dict) 

2974 result_update = db_api.share_network_update(self.fake_context, 

2975 self.share_nw_dict['id'], 

2976 {'name': new_name}) 

2977 result_get = db_api.share_network_get(self.fake_context, 

2978 self.share_nw_dict['id']) 

2979 

2980 self.assertEqual(new_name, result_update['name']) 

2981 self._check_fields(expected=dict(result_update.items()), 

2982 actual=dict(result_get.items())) 

2983 

2984 def test_update_not_found(self): 

2985 self.assertRaises(exception.ShareNetworkNotFound, 

2986 db_api.share_network_update, 

2987 self.fake_context, 

2988 'fake id', 

2989 {}) 

2990 

2991 @ddt.data(1, 2) 

2992 def test_get_all_one_record(self, records_count): 

2993 index = 0 

2994 share_networks = [] 

2995 while index < records_count: 

2996 share_network_dict = dict(self.share_nw_dict) 

2997 fake_id = 'fake_id%s' % index 

2998 share_network_dict.update({'id': fake_id, 

2999 'project_id': fake_id}) 

3000 share_networks.append(share_network_dict) 

3001 db_api.share_network_create(self.fake_context.elevated(), 

3002 share_network_dict) 

3003 index += 1 

3004 

3005 result = db_api.share_network_get_all(self.fake_context.elevated()) 

3006 

3007 self.assertEqual(len(share_networks), len(result)) 

3008 for index, net in enumerate(share_networks): 

3009 self._check_fields(expected=net, actual=result[index]) 

3010 

3011 def test_get_all_by_filter_with_project_id(self): 

3012 db_api.share_network_create(self.fake_context, self.share_nw_dict) 

3013 

3014 share_nw_dict2 = dict(self.share_nw_dict) 

3015 share_nw_dict2['id'] = 'fake share nw id2' 

3016 share_nw_dict2['project_id'] = 'fake project 2' 

3017 new_context = context.RequestContext(user_id='fake user 2', 

3018 project_id='fake project 2', 

3019 is_admin=False) 

3020 db_api.share_network_create(new_context, share_nw_dict2) 

3021 

3022 filters = {'project_id': share_nw_dict2['project_id']} 

3023 result = db_api.share_network_get_all_by_filter( 

3024 self.fake_context.elevated(), filters=filters) 

3025 

3026 self.assertEqual(1, len(result)) 

3027 self._check_fields(expected=share_nw_dict2, actual=result[0]) 

3028 

3029 def test_get_all_with_created_since_or_before_filter(self): 

3030 now = timeutils.utcnow() 

3031 

3032 share_nw1 = dict(self.share_nw_dict) 

3033 share_nw2 = dict(self.share_nw_dict) 

3034 share_nw3 = dict(self.share_nw_dict) 

3035 

3036 share_nw1['created_at'] = (now - datetime.timedelta(seconds=1)) 

3037 share_nw2['created_at'] = (now + datetime.timedelta(seconds=1)) 

3038 share_nw3['created_at'] = (now + datetime.timedelta(seconds=2)) 

3039 

3040 share_nw1['id'] = 'fake share nw id1' 

3041 share_nw2['id'] = 'fake share nw id2' 

3042 share_nw3['id'] = 'fake share nw id3' 

3043 

3044 db_api.share_network_create(self.fake_context, share_nw1) 

3045 db_api.share_network_create(self.fake_context, share_nw2) 

3046 db_api.share_network_create(self.fake_context, share_nw3) 

3047 

3048 filters1 = {'created_before': now} 

3049 filters2 = {'created_since': now} 

3050 

3051 result1 = db_api.share_network_get_all_by_filter( 

3052 self.fake_context.elevated(), filters=filters1) 

3053 result2 = db_api.share_network_get_all_by_filter( 

3054 self.fake_context.elevated(), filters=filters2) 

3055 

3056 self.assertEqual(1, len(result1)) 

3057 self.assertEqual(2, len(result2)) 

3058 

3059 def test_get_all_by_project(self): 

3060 db_api.share_network_create(self.fake_context, self.share_nw_dict) 

3061 

3062 share_nw_dict2 = dict(self.share_nw_dict) 

3063 share_nw_dict2['id'] = 'fake share nw id2' 

3064 share_nw_dict2['project_id'] = 'fake project 2' 

3065 new_context = context.RequestContext(user_id='fake user 2', 

3066 project_id='fake project 2', 

3067 is_admin=False) 

3068 db_api.share_network_create(new_context, share_nw_dict2) 

3069 

3070 result = db_api.share_network_get_all_by_project( 

3071 self.fake_context.elevated(), 

3072 share_nw_dict2['project_id']) 

3073 

3074 self.assertEqual(1, len(result)) 

3075 self._check_fields(expected=share_nw_dict2, actual=result[0]) 

3076 

3077 def test_add_security_service(self): 

3078 security_dict1 = {'id': 'fake security service id1', 

3079 'project_id': self.fake_context.project_id, 

3080 'type': 'fake type'} 

3081 

3082 db_api.share_network_create(self.fake_context, self.share_nw_dict) 

3083 db_api.security_service_create(self.fake_context, security_dict1) 

3084 db_api.share_network_add_security_service(self.fake_context, 

3085 self.share_nw_dict['id'], 

3086 security_dict1['id']) 

3087 

3088 with db_api.context_manager.reader.using(self.fake_context): 

3089 result = (db_api.model_query( 

3090 self.fake_context, 

3091 models.ShareNetworkSecurityServiceAssociation). 

3092 filter_by(security_service_id=security_dict1['id']). 

3093 filter_by(share_network_id=self.share_nw_dict['id']). 

3094 first()) 

3095 

3096 self.assertIsNotNone(result) 

3097 

3098 def test_add_security_service_not_found_01(self): 

3099 security_service_id = 'unknown security service' 

3100 db_api.share_network_create(self.fake_context, self.share_nw_dict) 

3101 

3102 self.assertRaises(exception.SecurityServiceNotFound, 

3103 db_api.share_network_add_security_service, 

3104 self.fake_context, 

3105 self.share_nw_dict['id'], 

3106 security_service_id) 

3107 

3108 def test_add_security_service_not_found_02(self): 

3109 security_dict1 = {'id': 'fake security service id1', 

3110 'project_id': self.fake_context.project_id, 

3111 'type': 'fake type'} 

3112 share_nw_id = 'unknown share network' 

3113 db_api.security_service_create(self.fake_context, security_dict1) 

3114 

3115 self.assertRaises(exception.ShareNetworkNotFound, 

3116 db_api.share_network_add_security_service, 

3117 self.fake_context, 

3118 share_nw_id, 

3119 security_dict1['id']) 

3120 

3121 def test_add_security_service_association_error_already_associated(self): 

3122 security_dict1 = {'id': 'fake security service id1', 

3123 'project_id': self.fake_context.project_id, 

3124 'type': 'fake type'} 

3125 

3126 db_api.share_network_create(self.fake_context, self.share_nw_dict) 

3127 db_api.security_service_create(self.fake_context, security_dict1) 

3128 db_api.share_network_add_security_service(self.fake_context, 

3129 self.share_nw_dict['id'], 

3130 security_dict1['id']) 

3131 

3132 self.assertRaises( 

3133 exception.ShareNetworkSecurityServiceAssociationError, 

3134 db_api.share_network_add_security_service, 

3135 self.fake_context, 

3136 self.share_nw_dict['id'], 

3137 security_dict1['id']) 

3138 

3139 def test_remove_security_service(self): 

3140 security_dict1 = {'id': 'fake security service id1', 

3141 'project_id': self.fake_context.project_id, 

3142 'type': 'fake type'} 

3143 

3144 db_api.share_network_create(self.fake_context, self.share_nw_dict) 

3145 db_api.security_service_create(self.fake_context, security_dict1) 

3146 db_api.share_network_add_security_service(self.fake_context, 

3147 self.share_nw_dict['id'], 

3148 security_dict1['id']) 

3149 

3150 db_api.share_network_remove_security_service(self.fake_context, 

3151 self.share_nw_dict['id'], 

3152 security_dict1['id']) 

3153 

3154 with db_api.context_manager.reader.using(self.fake_context): 

3155 result = (db_api.model_query( 

3156 self.fake_context, 

3157 models.ShareNetworkSecurityServiceAssociation). 

3158 filter_by(security_service_id=security_dict1['id']). 

3159 filter_by(share_network_id=self.share_nw_dict['id']). 

3160 first()) 

3161 

3162 self.assertIsNone(result) 

3163 

3164 share_nw_ref = db_api.share_network_get(self.fake_context, 

3165 self.share_nw_dict['id']) 

3166 self.assertEqual(0, len(share_nw_ref['security_services'])) 

3167 

3168 def test_remove_security_service_not_found_01(self): 

3169 security_service_id = 'unknown security service' 

3170 db_api.share_network_create(self.fake_context, self.share_nw_dict) 

3171 

3172 self.assertRaises(exception.SecurityServiceNotFound, 

3173 db_api.share_network_remove_security_service, 

3174 self.fake_context, 

3175 self.share_nw_dict['id'], 

3176 security_service_id) 

3177 

3178 def test_remove_security_service_not_found_02(self): 

3179 security_dict1 = {'id': 'fake security service id1', 

3180 'project_id': self.fake_context.project_id, 

3181 'type': 'fake type'} 

3182 share_nw_id = 'unknown share network' 

3183 db_api.security_service_create(self.fake_context, security_dict1) 

3184 

3185 self.assertRaises(exception.ShareNetworkNotFound, 

3186 db_api.share_network_remove_security_service, 

3187 self.fake_context, 

3188 share_nw_id, 

3189 security_dict1['id']) 

3190 

3191 def test_remove_security_service_dissociation_error(self): 

3192 security_dict1 = {'id': 'fake security service id1', 

3193 'project_id': self.fake_context.project_id, 

3194 'type': 'fake type'} 

3195 

3196 db_api.share_network_create(self.fake_context, self.share_nw_dict) 

3197 db_api.security_service_create(self.fake_context, security_dict1) 

3198 

3199 self.assertRaises( 

3200 exception.ShareNetworkSecurityServiceDissociationError, 

3201 db_api.share_network_remove_security_service, 

3202 self.fake_context, 

3203 self.share_nw_dict['id'], 

3204 security_dict1['id']) 

3205 

3206 def test_security_services_relation(self): 

3207 security_dict1 = {'id': 'fake security service id1', 

3208 'project_id': self.fake_context.project_id, 

3209 'type': 'fake type'} 

3210 

3211 db_api.share_network_create(self.fake_context, self.share_nw_dict) 

3212 db_api.security_service_create(self.fake_context, security_dict1) 

3213 

3214 result = db_api.share_network_get(self.fake_context, 

3215 self.share_nw_dict['id']) 

3216 

3217 self.assertEqual(0, len(result['security_services'])) 

3218 

3219 def test_shares_relation(self): 

3220 share_dict = {'id': 'fake share id1'} 

3221 

3222 db_api.share_network_create(self.fake_context, self.share_nw_dict) 

3223 db_api.share_create(self.fake_context, share_dict) 

3224 

3225 result = db_api.share_network_get(self.fake_context, 

3226 self.share_nw_dict['id']) 

3227 

3228 self.assertEqual(0, len(result['share_instances'])) 

3229 

3230 def test_association_get(self): 

3231 network = db_api.share_network_create( 

3232 self.fake_context, self.share_nw_dict) 

3233 security_service = db_api.security_service_create( 

3234 self.fake_context, security_service_dict) 

3235 network_id = network['id'] 

3236 security_service_id = security_service['id'] 

3237 

3238 db_api.share_network_add_security_service( 

3239 self.fake_context, network_id, security_service_id) 

3240 result = db_api.share_network_security_service_association_get( 

3241 self.fake_context, network_id, security_service_id) 

3242 

3243 self.assertEqual(result['share_network_id'], network_id) 

3244 self.assertEqual(result['security_service_id'], security_service_id) 

3245 

3246 def test_share_network_update_security_service(self): 

3247 new_sec_service = copy.copy(security_service_dict) 

3248 new_sec_service['id'] = 'fakeid' 

3249 share_network_id = self.share_nw_dict['id'] 

3250 db_api.share_network_create( 

3251 self.fake_context, self.share_nw_dict) 

3252 db_api.security_service_create( 

3253 self.fake_context, security_service_dict) 

3254 db_api.security_service_create(self.fake_context, new_sec_service) 

3255 db_api.share_network_add_security_service( 

3256 self.fake_context, share_network_id, 

3257 security_service_dict['id']) 

3258 db_api.share_network_update_security_service( 

3259 self.fake_context, share_network_id, security_service_dict['id'], 

3260 new_sec_service['id']) 

3261 

3262 association = db_api.share_network_security_service_association_get( 

3263 self.fake_context, share_network_id, new_sec_service['id']) 

3264 

3265 self.assertEqual(association['share_network_id'], share_network_id) 

3266 self.assertEqual( 

3267 association['security_service_id'], new_sec_service['id']) 

3268 

3269 

3270@ddt.ddt 

3271class ShareNetworkSubnetDatabaseAPITestCase(BaseDatabaseAPITestCase): 

3272 

3273 def __init__(self, *args, **kwargs): 

3274 super(ShareNetworkSubnetDatabaseAPITestCase, self).__init__( 

3275 *args, **kwargs) 

3276 self.fake_context = context.RequestContext(user_id='fake user', 

3277 project_id='fake project', 

3278 is_admin=False) 

3279 

3280 def setUp(self): 

3281 super(ShareNetworkSubnetDatabaseAPITestCase, self).setUp() 

3282 self.subnet_dict = {'id': 'fake network id', 

3283 'neutron_net_id': 'fake net id', 

3284 'neutron_subnet_id': 'fake subnet id', 

3285 'network_type': 'vlan', 

3286 'segmentation_id': 1000, 

3287 'share_network_id': 'fake_id', 

3288 'cidr': '10.0.0.0/24', 

3289 'ip_version': 4, 

3290 'availability_zone_id': None} 

3291 

3292 def test_create(self): 

3293 result = db_api.share_network_subnet_create( 

3294 self.fake_context, self.subnet_dict) 

3295 self._check_fields(expected=self.subnet_dict, actual=result) 

3296 

3297 def test_create_duplicated_id(self): 

3298 db_api.share_network_subnet_create(self.fake_context, self.subnet_dict) 

3299 

3300 self.assertRaises(db_exception.DBDuplicateEntry, 

3301 db_api.share_network_subnet_create, 

3302 self.fake_context, 

3303 self.subnet_dict) 

3304 

3305 def test_get(self): 

3306 db_api.share_network_subnet_create(self.fake_context, self.subnet_dict) 

3307 

3308 result = db_api.share_network_subnet_get(self.fake_context, 

3309 self.subnet_dict['id']) 

3310 self._check_fields(expected=self.subnet_dict, actual=result) 

3311 

3312 @ddt.data([{'id': 'fake_id_1', 'identifier': 'fake_identifier', 

3313 'host': 'fake_host'}], 

3314 [{'id': 'fake_id_2', 'identifier': 'fake_identifier', 

3315 'host': 'fake_host'}, 

3316 {'id': 'fake_id_3', 'identifier': 'fake_identifier', 

3317 'host': 'fake_host'}]) 

3318 def test_get_with_share_servers(self, share_servers): 

3319 share_net_subnets = [ 

3320 db_api.share_network_subnet_create( 

3321 self.fake_context, self.subnet_dict)] 

3322 

3323 for share_server in share_servers: 

3324 share_server['share_network_subnets'] = share_net_subnets 

3325 db_api.share_server_create(self.fake_context, share_server) 

3326 

3327 result = db_api.share_network_subnet_get(self.fake_context, 

3328 self.subnet_dict['id']) 

3329 

3330 self.assertEqual(len(share_servers), 

3331 len(result['share_servers'])) 

3332 

3333 for index, share_server in enumerate(share_servers): 

3334 result = db_api.share_network_subnet_get_all_by_share_server_id( 

3335 self.fake_context, share_server['id']) 

3336 for key, value in share_server['share_network_subnets'][0].items(): 

3337 if key != 'share_servers': 

3338 self.assertEqual(value, result[0][key]) 

3339 

3340 def test_get_not_found(self): 

3341 db_api.share_network_subnet_create(self.fake_context, self.subnet_dict) 

3342 

3343 self.assertRaises(exception.ShareNetworkSubnetNotFound, 

3344 db_api.share_network_subnet_get, 

3345 self.fake_context, 

3346 'fake_id') 

3347 

3348 def test_delete(self): 

3349 db_api.share_network_subnet_create(self.fake_context, self.subnet_dict) 

3350 db_api.share_network_subnet_delete(self.fake_context, 

3351 self.subnet_dict['id']) 

3352 

3353 self.assertRaises(exception.ShareNetworkSubnetNotFound, 

3354 db_api.share_network_subnet_delete, 

3355 self.fake_context, 

3356 self.subnet_dict['id']) 

3357 

3358 def test_delete_not_found(self): 

3359 self.assertRaises(exception.ShareNetworkSubnetNotFound, 

3360 db_api.share_network_subnet_delete, 

3361 self.fake_context, 

3362 'fake_id') 

3363 

3364 def test_update(self): 

3365 update_dict = { 

3366 'gateway': 'fake_gateway', 

3367 'ip_version': 6, 

3368 'mtu': '' 

3369 } 

3370 

3371 db_api.share_network_subnet_create(self.fake_context, self.subnet_dict) 

3372 db_api.share_network_subnet_update( 

3373 self.fake_context, self.subnet_dict['id'], update_dict) 

3374 

3375 result = db_api.share_network_subnet_get(self.fake_context, 

3376 self.subnet_dict['id']) 

3377 self._check_fields(expected=update_dict, actual=result) 

3378 

3379 def test_update_not_found(self): 

3380 self.assertRaises(exception.ShareNetworkSubnetNotFound, 

3381 db_api.share_network_subnet_update, 

3382 self.fake_context, 

3383 self.subnet_dict['id'], 

3384 {}) 

3385 

3386 @ddt.data([ 

3387 { 

3388 'id': 'sn_id1', 

3389 'project_id': 'fake project', 

3390 'user_id': 'fake' 

3391 } 

3392 ], [ 

3393 { 

3394 'id': 'fake_id', 

3395 'project_id': 'fake project', 

3396 'user_id': 'fake' 

3397 }, 

3398 { 

3399 'id': 'sn_id2', 

3400 'project_id': 'fake project', 

3401 'user_id': 'fake' 

3402 } 

3403 ]) 

3404 def test_get_all_by_share_network(self, share_networks): 

3405 

3406 for idx, share_network in enumerate(share_networks): 

3407 self.subnet_dict['share_network_id'] = share_network['id'] 

3408 self.subnet_dict['id'] = 'fake_id%s' % idx 

3409 

3410 db_api.share_network_create(self.fake_context, share_network) 

3411 db_api.share_network_subnet_create(self.fake_context, 

3412 self.subnet_dict) 

3413 for share_network in share_networks: 

3414 subnets = db_api.share_network_subnet_get_all_by_share_network( 

3415 self.fake_context, share_network['id']) 

3416 self.assertEqual(1, len(subnets)) 

3417 

3418 def test_get_by_availability_zone_id(self): 

3419 with db_api.context_manager.writer.using(self.fake_context): 

3420 az = db_api._availability_zone_create_if_not_exist( 

3421 self.fake_context, 'fake_zone_id', 

3422 ) 

3423 self.subnet_dict['availability_zone_id'] = az['id'] 

3424 db_api.share_network_subnet_create(self.fake_context, self.subnet_dict) 

3425 

3426 result = db_api.share_network_subnets_get_all_by_availability_zone_id( 

3427 self.fake_context, self.subnet_dict['share_network_id'], az['id']) 

3428 

3429 self._check_fields(expected=self.subnet_dict, actual=result[0]) 

3430 

3431 def test_get_az_subnets(self): 

3432 with db_api.context_manager.writer.using(self.fake_context): 

3433 az = db_api._availability_zone_create_if_not_exist( 

3434 self.fake_context, 'fake_zone_id', 

3435 ) 

3436 self.subnet_dict['availability_zone_id'] = az['id'] 

3437 db_api.share_network_subnet_create(self.fake_context, self.subnet_dict) 

3438 

3439 result = db_api.share_network_subnet_get_all_with_same_az( 

3440 self.fake_context, self.subnet_dict['id']) 

3441 

3442 self.subnet_dict['share_network'] = None 

3443 

3444 self._check_fields(expected=self.subnet_dict, actual=result[0]) 

3445 

3446 def test_get_az_subnets_not_found(self): 

3447 self.assertRaises( 

3448 exception.ShareNetworkSubnetNotFound, 

3449 db_api.share_network_subnet_get_all_with_same_az, 

3450 self.fake_context, 'share_network_subnet_id') 

3451 

3452 def test_get_default_subnet(self): 

3453 db_api.share_network_subnet_create(self.fake_context, self.subnet_dict) 

3454 

3455 result = db_api.share_network_subnet_get_default_subnets( 

3456 self.fake_context, self.subnet_dict['share_network_id']) 

3457 

3458 self._check_fields(expected=self.subnet_dict, actual=result[0]) 

3459 

3460 def test_get_by_share_server_id_not_found(self): 

3461 self.assertRaises( 

3462 exception.ShareNetworkSubnetNotFoundByShareServer, 

3463 db_api.share_network_subnet_get_all_by_share_server_id, 

3464 self.fake_context, 'share_server_id') 

3465 

3466 def test_share_network_subnet_metadata_get(self): 

3467 metadata = {'a': 'b', 'c': 'd'} 

3468 

3469 subnet_1 = db_api.share_network_subnet_create( 

3470 self.fake_context, self.subnet_dict) 

3471 db_api.share_network_subnet_metadata_update( 

3472 self.fake_context, share_network_subnet_id=subnet_1['id'], 

3473 metadata=metadata, delete=False) 

3474 self.assertEqual( 

3475 metadata, db_api.share_network_subnet_metadata_get( 

3476 self.fake_context, share_network_subnet_id=subnet_1['id'])) 

3477 

3478 def test_share_network_subnet_metadata_get_item(self): 

3479 metadata = {'a': 'b', 'c': 'd'} 

3480 key = 'a' 

3481 shouldbe = {'a': 'b'} 

3482 subnet_1 = db_api.share_network_subnet_create( 

3483 self.fake_context, self.subnet_dict) 

3484 db_api.share_network_subnet_metadata_update( 

3485 self.fake_context, share_network_subnet_id=subnet_1['id'], 

3486 metadata=metadata, delete=False) 

3487 self.assertEqual( 

3488 shouldbe, db_api.share_network_subnet_metadata_get_item( 

3489 self.fake_context, share_network_subnet_id=subnet_1['id'], 

3490 key=key)) 

3491 

3492 def test_share_network_subnet_metadata_update(self): 

3493 metadata1 = {'a': '1', 'c': '2'} 

3494 metadata2 = {'a': '3', 'd': '5'} 

3495 should_be = {'a': '3', 'c': '2', 'd': '5'} 

3496 subnet_1 = db_api.share_network_subnet_create( 

3497 self.fake_context, self.subnet_dict) 

3498 db_api.share_network_subnet_metadata_update( 

3499 self.fake_context, share_network_subnet_id=subnet_1['id'], 

3500 metadata=metadata1, delete=False) 

3501 db_api.share_network_subnet_metadata_update( 

3502 self.fake_context, share_network_subnet_id=subnet_1['id'], 

3503 metadata=metadata2, delete=False) 

3504 self.assertEqual( 

3505 should_be, db_api.share_network_subnet_metadata_get( 

3506 self.fake_context, share_network_subnet_id=subnet_1['id'])) 

3507 

3508 def test_share_network_subnet_metadata_delete(self): 

3509 key = 'a' 

3510 metadata = {'a': '1', 'c': '2'} 

3511 should_be = {'c': '2'} 

3512 subnet_1 = db_api.share_network_subnet_create( 

3513 self.fake_context, self.subnet_dict) 

3514 db_api.share_network_subnet_metadata_update( 

3515 self.fake_context, share_network_subnet_id=subnet_1['id'], 

3516 metadata=metadata, delete=False) 

3517 db_api.share_network_subnet_metadata_delete( 

3518 self.fake_context, share_network_subnet_id=subnet_1['id'], 

3519 key=key) 

3520 self.assertEqual( 

3521 should_be, db_api.share_network_subnet_metadata_get( 

3522 self.fake_context, share_network_subnet_id=subnet_1['id'])) 

3523 

3524 

3525@ddt.ddt 

3526class SecurityServiceDatabaseAPITestCase(BaseDatabaseAPITestCase): 

3527 

3528 def __init__(self, *args, **kwargs): 

3529 super(SecurityServiceDatabaseAPITestCase, self).__init__(*args, 

3530 **kwargs) 

3531 

3532 self.fake_context = context.RequestContext(user_id='fake user', 

3533 project_id='fake project', 

3534 is_admin=False) 

3535 

3536 def _check_expected_fields(self, result, expected): 

3537 for key in expected: 

3538 self.assertEqual(expected[key], result[key]) 

3539 

3540 def test_create(self): 

3541 result = db_api.security_service_create(self.fake_context, 

3542 security_service_dict) 

3543 

3544 self._check_expected_fields(result, security_service_dict) 

3545 

3546 def test_create_with_duplicated_id(self): 

3547 db_api.security_service_create(self.fake_context, 

3548 security_service_dict) 

3549 

3550 self.assertRaises(db_exception.DBDuplicateEntry, 

3551 db_api.security_service_create, 

3552 self.fake_context, 

3553 security_service_dict) 

3554 

3555 def test_get(self): 

3556 db_api.security_service_create(self.fake_context, 

3557 security_service_dict) 

3558 

3559 result = db_api.security_service_get(self.fake_context, 

3560 security_service_dict['id']) 

3561 

3562 self._check_expected_fields(result, security_service_dict) 

3563 

3564 def test_get_not_found(self): 

3565 self.assertRaises(exception.SecurityServiceNotFound, 

3566 db_api.security_service_get, 

3567 self.fake_context, 

3568 'wrong id') 

3569 

3570 def test_get_all_by_share_network(self): 

3571 dict1 = security_service_dict 

3572 dict2 = security_service_dict.copy() 

3573 dict2['id'] = 'fake id 2' 

3574 db_api.security_service_create(self.fake_context, 

3575 dict1) 

3576 db_api.security_service_create(self.fake_context, 

3577 dict2) 

3578 share_nw_dict = {'id': 'fake network id', 

3579 'project_id': 'fake project', 

3580 'user_id': 'fake_user_id'} 

3581 db_api.share_network_create(self.fake_context, share_nw_dict) 

3582 db_api.share_network_add_security_service( 

3583 self.fake_context, 

3584 share_nw_dict['id'], dict1['id']) 

3585 

3586 result = db_api.security_service_get_all_by_share_network( 

3587 self.fake_context, share_nw_dict['id']) 

3588 self._check_expected_fields(result[0], dict1) 

3589 self.assertEqual(1, len(result)) 

3590 

3591 def test_delete(self): 

3592 db_api.security_service_create(self.fake_context, 

3593 security_service_dict) 

3594 

3595 db_api.security_service_delete(self.fake_context, 

3596 security_service_dict['id']) 

3597 

3598 self.assertRaises(exception.SecurityServiceNotFound, 

3599 db_api.security_service_get, 

3600 self.fake_context, 

3601 security_service_dict['id']) 

3602 

3603 def test_update(self): 

3604 update_dict = { 

3605 'dns_ip': 'new dns', 

3606 'server': 'new ldap server', 

3607 'domain': 'new ldap domain', 

3608 'default_ad_site': 'new ldap default_ad_site', 

3609 'ou': 'new ldap ou', 

3610 'user': 'new user', 

3611 'password': 'new password', 

3612 'name': 'new whatever', 

3613 'description': 'new nevermind', 

3614 } 

3615 

3616 db_api.security_service_create(self.fake_context, 

3617 security_service_dict) 

3618 

3619 result = db_api.security_service_update(self.fake_context, 

3620 security_service_dict['id'], 

3621 update_dict) 

3622 

3623 self._check_expected_fields(result, update_dict) 

3624 

3625 def test_update_no_updates(self): 

3626 db_api.security_service_create(self.fake_context, 

3627 security_service_dict) 

3628 

3629 result = db_api.security_service_update(self.fake_context, 

3630 security_service_dict['id'], 

3631 {}) 

3632 

3633 self._check_expected_fields(result, security_service_dict) 

3634 

3635 def test_update_not_found(self): 

3636 self.assertRaises(exception.SecurityServiceNotFound, 

3637 db_api.security_service_update, 

3638 self.fake_context, 

3639 'wrong id', 

3640 {}) 

3641 

3642 def test_get_all_no_records(self): 

3643 result = db_api.security_service_get_all(self.fake_context) 

3644 

3645 self.assertEqual(0, len(result)) 

3646 

3647 @ddt.data(1, 2) 

3648 def test_get_all(self, records_count): 

3649 index = 0 

3650 services = [] 

3651 while index < records_count: 

3652 service_dict = dict(security_service_dict) 

3653 service_dict.update({'id': 'fake_id%s' % index}) 

3654 services.append(service_dict) 

3655 db_api.security_service_create(self.fake_context, service_dict) 

3656 index += 1 

3657 

3658 result = db_api.security_service_get_all(self.fake_context) 

3659 

3660 self.assertEqual(len(services), len(result)) 

3661 for index, service in enumerate(services): 

3662 self._check_fields(expected=service, actual=result[index]) 

3663 

3664 def test_get_all_two_records(self): 

3665 dict1 = security_service_dict 

3666 dict2 = security_service_dict.copy() 

3667 dict2['id'] = 'fake id 2' 

3668 db_api.security_service_create(self.fake_context, 

3669 dict1) 

3670 db_api.security_service_create(self.fake_context, 

3671 dict2) 

3672 

3673 result = db_api.security_service_get_all(self.fake_context) 

3674 

3675 self.assertEqual(2, len(result)) 

3676 

3677 def test_get_all_by_project(self): 

3678 dict1 = security_service_dict 

3679 dict2 = security_service_dict.copy() 

3680 dict2['id'] = 'fake id 2' 

3681 dict2['project_id'] = 'fake project 2' 

3682 db_api.security_service_create(self.fake_context, 

3683 dict1) 

3684 db_api.security_service_create(self.fake_context, 

3685 dict2) 

3686 

3687 result1 = db_api.security_service_get_all_by_project( 

3688 self.fake_context, 

3689 dict1['project_id']) 

3690 

3691 self.assertEqual(1, len(result1)) 

3692 self._check_expected_fields(result1[0], dict1) 

3693 

3694 result2 = db_api.security_service_get_all_by_project( 

3695 self.fake_context, 

3696 dict2['project_id']) 

3697 

3698 self.assertEqual(1, len(result2)) 

3699 self._check_expected_fields(result2[0], dict2) 

3700 

3701 

3702@ddt.ddt 

3703class ShareServerDatabaseAPITestCase(test.TestCase): 

3704 

3705 def setUp(self): 

3706 super(ShareServerDatabaseAPITestCase, self).setUp() 

3707 self.ctxt = context.RequestContext(user_id='user_id', 

3708 project_id='project_id', 

3709 is_admin=True) 

3710 self.share_net_subnets = [ 

3711 db_utils.create_share_network_subnet( 

3712 id=uuidutils.generate_uuid(), 

3713 share_network_id=uuidutils.generate_uuid())] 

3714 

3715 def test_share_server_get(self): 

3716 expected = db_utils.create_share_server( 

3717 share_network_subnets=self.share_net_subnets) 

3718 server = db_api.share_server_get(self.ctxt, expected['id']) 

3719 self.assertEqual(expected['id'], server['id']) 

3720 self.assertEqual(expected.share_network_subnets[0]['id'], 

3721 server.share_network_subnets[0]['id']) 

3722 self.assertEqual( 

3723 expected.share_network_subnets[0]['share_network_id'], 

3724 server.share_network_subnets[0]['share_network_id']) 

3725 self.assertEqual(expected.host, server.host) 

3726 self.assertEqual(expected.status, server.status) 

3727 

3728 def test_get_not_found(self): 

3729 fake_id = 'FAKE_UUID' 

3730 self.assertRaises(exception.ShareServerNotFound, 

3731 db_api.share_server_get, self.ctxt, fake_id) 

3732 

3733 def test_create(self): 

3734 server = db_utils.create_share_server( 

3735 share_network_subnets=self.share_net_subnets) 

3736 self.assertTrue(server['id']) 

3737 self.assertEqual(server.share_network_subnets[0]['id'], 

3738 server['share_network_subnets'][0]['id']) 

3739 self.assertEqual( 

3740 server.share_network_subnets[0]['share_network_id'], 

3741 server['share_network_subnets'][0]['share_network_id']) 

3742 self.assertEqual(server.host, server['host']) 

3743 self.assertEqual(server.status, server['status']) 

3744 

3745 def test_delete(self): 

3746 server = db_utils.create_share_server() 

3747 num_records = len(db_api.share_server_get_all(self.ctxt)) 

3748 db_api.share_server_delete(self.ctxt, server['id']) 

3749 self.assertEqual(num_records - 1, 

3750 len(db_api.share_server_get_all(self.ctxt))) 

3751 

3752 def test_delete_not_found(self): 

3753 fake_id = 'FAKE_UUID' 

3754 self.assertRaises(exception.ShareServerNotFound, 

3755 db_api.share_server_delete, 

3756 self.ctxt, fake_id) 

3757 

3758 def test_update(self): 

3759 share_net_subnets_update = [ 

3760 db_utils.create_share_network_subnet( 

3761 id=uuidutils.generate_uuid(), 

3762 share_network_id=uuidutils.generate_uuid())] 

3763 update = { 

3764 'share_network_subnets': share_net_subnets_update, 

3765 'host': 'update_host', 

3766 'status': constants.STATUS_ACTIVE, 

3767 } 

3768 server = db_utils.create_share_server( 

3769 share_network_subnets=self.share_net_subnets) 

3770 updated_server = db_api.share_server_update(self.ctxt, server['id'], 

3771 update) 

3772 self.assertEqual(server['id'], updated_server['id']) 

3773 self.assertEqual( 

3774 update['share_network_subnets'][0]['share_network_id'], 

3775 updated_server.share_network_subnets[0]['share_network_id']) 

3776 self.assertEqual(update['host'], updated_server.host) 

3777 self.assertEqual(update['status'], updated_server.status) 

3778 

3779 def test_update_not_found(self): 

3780 fake_id = 'FAKE_UUID' 

3781 self.assertRaises(exception.ShareServerNotFound, 

3782 db_api.share_server_update, 

3783 self.ctxt, fake_id, {}) 

3784 

3785 def test_get_all_by_host_and_share_subnet_valid(self): 

3786 subnet_1 = { 

3787 'id': '1', 

3788 'share_network_id': '1', 

3789 } 

3790 subnet_2 = { 

3791 'id': '2', 

3792 'share_network_id': '2', 

3793 } 

3794 share_net_subnets1 = db_utils.create_share_network_subnet(**subnet_1) 

3795 share_net_subnets2 = db_utils.create_share_network_subnet(**subnet_2) 

3796 valid = { 

3797 'share_network_subnets': [share_net_subnets1], 

3798 'host': 'host1', 

3799 'status': constants.STATUS_ACTIVE, 

3800 } 

3801 invalid = { 

3802 'share_network_subnets': [share_net_subnets2], 

3803 'host': 'host1', 

3804 'status': constants.STATUS_ERROR, 

3805 } 

3806 other = { 

3807 'share_network_subnets': [share_net_subnets1], 

3808 'host': 'host2', 

3809 'status': constants.STATUS_ACTIVE, 

3810 } 

3811 valid = db_utils.create_share_server(**valid) 

3812 db_utils.create_share_server(**invalid) 

3813 db_utils.create_share_server(**other) 

3814 

3815 servers = db_api.share_server_get_all_by_host_and_share_subnet_valid( 

3816 self.ctxt, 

3817 host='host1', 

3818 share_subnet_id='1') 

3819 

3820 self.assertEqual(valid['id'], servers[0]['id']) 

3821 

3822 def test_get_all_by_host_and_share_subnet_valid_not_found(self): 

3823 self.assertRaises( 

3824 exception.ShareServerNotFound, 

3825 db_api.share_server_get_all_by_host_and_share_subnet_valid, 

3826 self.ctxt, host='fake', share_subnet_id='fake' 

3827 ) 

3828 

3829 def test_get_all_by_host_and_share_subnet(self): 

3830 subnet_1 = { 

3831 'id': '1', 

3832 'share_network_id': '1', 

3833 } 

3834 share_net_subnets1 = db_utils.create_share_network_subnet(**subnet_1) 

3835 valid = { 

3836 'share_network_subnets': [share_net_subnets1], 

3837 'host': 'host1', 

3838 'status': constants.STATUS_SERVER_NETWORK_CHANGE, 

3839 } 

3840 other = { 

3841 'share_network_subnets': [share_net_subnets1], 

3842 'host': 'host1', 

3843 'status': constants.STATUS_ERROR, 

3844 } 

3845 invalid = { 

3846 'share_network_subnets': [share_net_subnets1], 

3847 'host': 'host2', 

3848 'status': constants.STATUS_ACTIVE, 

3849 } 

3850 valid = db_utils.create_share_server(**valid) 

3851 invalid = db_utils.create_share_server(**invalid) 

3852 other = db_utils.create_share_server(**other) 

3853 

3854 servers = db_api.share_server_get_all_by_host_and_or_share_subnet( 

3855 self.ctxt, 

3856 host='host1', 

3857 share_subnet_id='1') 

3858 

3859 self.assertEqual(2, len(servers)) 

3860 ids = [s['id'] for s in servers] 

3861 self.assertIn(valid['id'], ids) 

3862 self.assertIn(other['id'], ids) 

3863 self.assertNotIn(invalid['id'], ids) 

3864 

3865 def test_get_all_by_host_and_share_subnet_not_found(self): 

3866 self.assertRaises( 

3867 exception.ShareServerNotFound, 

3868 db_api.share_server_get_all_by_host_and_or_share_subnet, 

3869 self.ctxt, host='fake', share_subnet_id='fake' 

3870 ) 

3871 

3872 def test_get_all(self): 

3873 srv1 = { 

3874 'host': 'host1', 

3875 'status': constants.STATUS_ACTIVE, 

3876 } 

3877 srv2 = { 

3878 'host': 'host1', 

3879 'status': constants.STATUS_ERROR, 

3880 } 

3881 srv3 = { 

3882 'host': 'host2', 

3883 'status': constants.STATUS_ACTIVE, 

3884 } 

3885 servers = db_api.share_server_get_all(self.ctxt) 

3886 self.assertEqual(0, len(servers)) 

3887 

3888 to_delete = db_utils.create_share_server(**srv1) 

3889 db_utils.create_share_server(**srv2) 

3890 db_utils.create_share_server(**srv3) 

3891 

3892 servers = db_api.share_server_get_all(self.ctxt) 

3893 self.assertEqual(3, len(servers)) 

3894 

3895 db_api.share_server_delete(self.ctxt, to_delete['id']) 

3896 servers = db_api.share_server_get_all(self.ctxt) 

3897 self.assertEqual(2, len(servers)) 

3898 

3899 def test_backend_details_set(self): 

3900 details = { 

3901 'value1': '1', 

3902 'value2': '2', 

3903 } 

3904 server = db_utils.create_share_server() 

3905 db_api.share_server_backend_details_set(self.ctxt, server['id'], 

3906 details) 

3907 

3908 self.assertDictEqual( 

3909 details, 

3910 db_api.share_server_get(self.ctxt, server['id'])['backend_details'] 

3911 ) 

3912 

3913 details.update({'value2': '4'}) 

3914 db_api.share_server_backend_details_set(self.ctxt, server['id'], 

3915 details) 

3916 self.assertDictEqual( 

3917 details, 

3918 db_api.share_server_get(self.ctxt, server['id'])['backend_details'] 

3919 ) 

3920 

3921 def test_backend_details_set_not_found(self): 

3922 fake_id = 'FAKE_UUID' 

3923 self.assertRaises(exception.ShareServerNotFound, 

3924 db_api.share_server_backend_details_set, 

3925 self.ctxt, fake_id, {}) 

3926 

3927 def test_get_with_details(self): 

3928 values = { 

3929 'share_network_subnets': [ 

3930 db_utils.create_share_network_subnet( 

3931 id='fake_subnet_id', 

3932 share_network_id='fake_share_net_id')], 

3933 'host': 'hostname', 

3934 'status': constants.STATUS_ACTIVE, 

3935 } 

3936 details = { 

3937 'value1': '1', 

3938 'value2': '2', 

3939 } 

3940 srv_id = db_utils.create_share_server(**values)['id'] 

3941 db_api.share_server_backend_details_set(self.ctxt, srv_id, details) 

3942 server = db_api.share_server_get(self.ctxt, srv_id) 

3943 self.assertEqual(srv_id, server['id']) 

3944 self.assertEqual(values['share_network_subnets'][0]['id'], 

3945 server.share_network_subnets[0]['id']) 

3946 self.assertEqual( 

3947 values['share_network_subnets'][0]['share_network_id'], 

3948 server.share_network_subnets[0]['share_network_id']) 

3949 self.assertEqual(values['host'], server.host) 

3950 self.assertEqual(values['status'], server.status) 

3951 self.assertDictEqual(server['backend_details'], details) 

3952 self.assertIn('backend_details', server.to_dict()) 

3953 

3954 def test_delete_with_details(self): 

3955 server = db_utils.create_share_server(backend_details={ 

3956 'value1': '1', 

3957 'value2': '2', 

3958 }) 

3959 

3960 num_records = len(db_api.share_server_get_all(self.ctxt)) 

3961 db_api.share_server_delete(self.ctxt, server['id']) 

3962 self.assertEqual(num_records - 1, 

3963 len(db_api.share_server_get_all(self.ctxt))) 

3964 

3965 @ddt.data('foobar', 'fake', '-fake-', 'some_fake_', 'some-fake-', 

3966 '-fake-identifier', '_fake_identifier', 'some-fake-identifier', 

3967 'some_fake_identifier') 

3968 def test_share_server_search_by_identifier(self, identifier): 

3969 

3970 server = { 

3971 'host': 'hostname', 

3972 'status': constants.STATUS_ACTIVE, 

3973 'is_auto_deletable': True, 

3974 'updated_at': datetime.datetime(2018, 5, 1), 

3975 'identifier': 'some_fake_identifier', 

3976 } 

3977 

3978 server = db_utils.create_share_server(**server) 

3979 if identifier in ('foobar', 'fake', '-fake-', 'some_fake_', 

3980 'some-fake-'): 

3981 self.assertRaises(exception.ShareServerNotFound, 

3982 db_api.share_server_search_by_identifier, 

3983 self.ctxt, identifier) 

3984 else: 

3985 result = db_api.share_server_search_by_identifier( 

3986 self.ctxt, identifier) 

3987 self.assertEqual(server['id'], result[0]['id']) 

3988 

3989 @ddt.data((True, True, True, 3), 

3990 (True, True, False, 2), 

3991 (True, False, False, 1), 

3992 (False, False, False, 0)) 

3993 @ddt.unpack 

3994 def test_share_server_get_all_unused_deletable(self, 

3995 server_1_is_auto_deletable, 

3996 server_2_is_auto_deletable, 

3997 server_3_is_auto_deletable, 

3998 expected_len): 

3999 server1 = { 

4000 'host': 'hostname', 

4001 'status': constants.STATUS_ACTIVE, 

4002 'is_auto_deletable': server_1_is_auto_deletable, 

4003 'updated_at': datetime.datetime(2018, 5, 1) 

4004 } 

4005 server2 = { 

4006 'host': 'hostname', 

4007 'status': constants.STATUS_ACTIVE, 

4008 'is_auto_deletable': server_2_is_auto_deletable, 

4009 'updated_at': datetime.datetime(2018, 5, 1) 

4010 } 

4011 server3 = { 

4012 'host': 'hostname', 

4013 'status': constants.STATUS_ACTIVE, 

4014 'is_auto_deletable': server_3_is_auto_deletable, 

4015 'updated_at': datetime.datetime(2018, 5, 1) 

4016 } 

4017 db_utils.create_share_server(**server1) 

4018 db_utils.create_share_server(**server2) 

4019 db_utils.create_share_server(**server3) 

4020 host = 'hostname' 

4021 updated_before = datetime.datetime(2019, 5, 1) 

4022 

4023 unused_deletable = db_api.share_server_get_all_unused_deletable( 

4024 self.ctxt, host, updated_before) 

4025 self.assertEqual(expected_len, len(unused_deletable)) 

4026 

4027 @ddt.data({'host': 'fakepool@fakehost'}, 

4028 {'status': constants.STATUS_SERVER_MIGRATING_TO}, 

4029 {'source_share_server_id': 'fake_ss_id'}, 

4030 {'share_network_id': uuidutils.generate_uuid()}) 

4031 def test_share_server_get_all_with_filters(self, filters): 

4032 server_data = copy.copy(filters) 

4033 share_network_id = server_data.pop('share_network_id', None) 

4034 share_network_subnet = {} 

4035 if share_network_id: 

4036 db_utils.create_share_network(id=share_network_id) 

4037 share_network_subnet = db_utils.create_share_network_subnet( 

4038 id=uuidutils.generate_uuid(), 

4039 share_network_id=share_network_id) 

4040 server_data['share_network_subnets'] = [share_network_subnet] 

4041 db_utils.create_share_server(**server_data) 

4042 db_utils.create_share_server() 

4043 filter_keys = filters.keys() 

4044 

4045 results = db_api.share_server_get_all_with_filters(self.ctxt, filters) 

4046 

4047 self.assertEqual(1, len(results)) 

4048 for result in results: 

4049 for key in filter_keys: 

4050 if key == 'share_network_id': 

4051 self.assertEqual(share_network_subnet['share_network_id'], 

4052 filters[key]) 

4053 self.assertEqual(share_network_subnet['id'], 

4054 result['share_network_subnets'][0]['id']) 

4055 else: 

4056 self.assertEqual(result[key], filters[key]) 

4057 

4058 @ddt.data('fake@fake', 'host1@backend1') 

4059 def test_share_server_get_all_by_host(self, host): 

4060 db_utils.create_share_server(host='fake@fake') 

4061 db_utils.create_share_server(host='host1@backend1') 

4062 

4063 share_servers = db_api.share_server_get_all_by_host(self.ctxt, host) 

4064 

4065 self.assertEqual(1, len(share_servers)) 

4066 for share_server in share_servers: 

4067 self.assertEqual(host, share_server['host']) 

4068 

4069 def test_share_servers_update(self): 

4070 servers = [db_utils.create_share_server() 

4071 for __ in range(1, 3)] 

4072 server_ids = [server['id'] for server in servers] 

4073 values = {'status': constants.STATUS_NETWORK_CHANGE} 

4074 

4075 db_api.share_servers_update( 

4076 self.ctxt, server_ids, values) 

4077 

4078 share_servers = [ 

4079 db_api.share_server_get(self.ctxt, server_id) 

4080 for server_id in server_ids] 

4081 

4082 for ss in share_servers: 

4083 self.assertEqual(constants.STATUS_NETWORK_CHANGE, ss['status']) 

4084 

4085 def test_encryption_keys_get_count(self): 

4086 servers = [db_utils.create_share_server( 

4087 encryption_key_ref=uuidutils.generate_uuid()) 

4088 for __ in range(1, 4)] 

4089 count = db_api.encryption_keys_get_count(context.get_admin_context()) 

4090 self.assertEqual(count, len(servers)) 

4091 

4092 

4093class ServiceDatabaseAPITestCase(test.TestCase): 

4094 

4095 def setUp(self): 

4096 super(ServiceDatabaseAPITestCase, self).setUp() 

4097 self.ctxt = context.RequestContext(user_id='user_id', 

4098 project_id='project_id', 

4099 is_admin=True) 

4100 

4101 self.service_data = {'host': "fake_host", 

4102 'binary': "fake_binary", 

4103 'topic': "fake_topic", 

4104 'report_count': 0, 

4105 'availability_zone': "fake_zone"} 

4106 

4107 def test_create(self): 

4108 """Ensure we create a new AZ if necessary.""" 

4109 service = db_api.service_create(self.ctxt, self.service_data) 

4110 az = db_api.availability_zone_get(self.ctxt, "fake_zone") 

4111 

4112 self.assertEqual(az.id, service.availability_zone_id) 

4113 self.assertSubDictMatch(self.service_data, service.to_dict()) 

4114 

4115 def test_create__az_exists(self): 

4116 """Ensure we use an AZ is it already exists.""" 

4117 with db_api.context_manager.writer.using(self.ctxt): 

4118 az = db_api._availability_zone_create_if_not_exist( 

4119 self.ctxt, 'fake_zone', 

4120 ) 

4121 

4122 service = db_api.service_create(self.ctxt, self.service_data) 

4123 

4124 self.assertEqual(az.id, service.availability_zone_id) 

4125 self.assertSubDictMatch(self.service_data, service.to_dict()) 

4126 

4127 def test_create__az_missing(self): 

4128 """Ensure we fail if AZ info is missing.""" 

4129 self.service_data.pop('availability_zone') 

4130 exc = self.assertRaises( 

4131 ValueError, 

4132 db_api.service_create, 

4133 self.ctxt, 

4134 self.service_data, 

4135 ) 

4136 self.assertIn( 

4137 "Values dict should have 'availability_zone' field.", 

4138 str(exc), 

4139 ) 

4140 

4141 def test_update(self): 

4142 az_name = 'fake_zone2' 

4143 update_data = {"availability_zone": az_name} 

4144 

4145 service = db_api.service_create(self.ctxt, self.service_data) 

4146 db_api.service_update(self.ctxt, service['id'], update_data) 

4147 

4148 service = db_api.service_get(self.ctxt, service['id']) 

4149 az = db_api.availability_zone_get(self.ctxt, az_name) 

4150 

4151 self.assertEqual(az.id, service.availability_zone_id) 

4152 valid_values = self.service_data 

4153 valid_values.update(update_data) 

4154 self.assertSubDictMatch(valid_values, service.to_dict()) 

4155 

4156 

4157@ddt.ddt 

4158class AvailabilityZonesDatabaseAPITestCase(test.TestCase): 

4159 

4160 def setUp(self): 

4161 super(AvailabilityZonesDatabaseAPITestCase, self).setUp() 

4162 self.ctxt = context.RequestContext(user_id='user_id', 

4163 project_id='project_id', 

4164 is_admin=True) 

4165 

4166 @ddt.data({'fake': 'fake'}, {}, {'fakeavailability_zone': 'fake'}, 

4167 {'availability_zone': None}, {'availability_zone': ''}) 

4168 def test_ensure_availability_zone_exists_invalid(self, test_values): 

4169 self.assertRaises(ValueError, db_api.ensure_availability_zone_exists, 

4170 self.ctxt, test_values) 

4171 

4172 def test_az_get(self): 

4173 az_name = 'test_az' 

4174 with db_api.context_manager.writer.using(self.ctxt): 

4175 az = db_api._availability_zone_create_if_not_exist( 

4176 self.ctxt, az_name 

4177 ) 

4178 

4179 az_by_id = db_api.availability_zone_get(self.ctxt, az['id']) 

4180 az_by_name = db_api.availability_zone_get(self.ctxt, az_name) 

4181 

4182 self.assertEqual(az_name, az_by_id['name']) 

4183 self.assertEqual(az_name, az_by_name['name']) 

4184 self.assertEqual(az['id'], az_by_id['id']) 

4185 self.assertEqual(az['id'], az_by_name['id']) 

4186 

4187 def test_az_get_all(self): 

4188 with db_api.context_manager.writer.using(self.ctxt): 

4189 db_api._availability_zone_create_if_not_exist(self.ctxt, 'test1') 

4190 db_api._availability_zone_create_if_not_exist(self.ctxt, 'test2') 

4191 db_api._availability_zone_create_if_not_exist(self.ctxt, 'test3') 

4192 

4193 db_api.service_create(self.ctxt, {'availability_zone': 'test2'}) 

4194 

4195 actual_result = db_api.availability_zone_get_all(self.ctxt) 

4196 

4197 self.assertEqual(1, len(actual_result)) 

4198 self.assertEqual('test2', actual_result[0]['name']) 

4199 

4200 

4201@ddt.ddt 

4202class NetworkAllocationsDatabaseAPITestCase(test.TestCase): 

4203 

4204 def setUp(self): 

4205 super(NetworkAllocationsDatabaseAPITestCase, self).setUp() 

4206 self.user_id = 'user_id' 

4207 self.project_id = 'project_id' 

4208 self.share_server_id = 'foo_share_server_id' 

4209 self.share_network_subnet_id = 'foo_share_network_subnet_id' 

4210 self.ctxt = context.RequestContext( 

4211 user_id=self.user_id, project_id=self.project_id, is_admin=True) 

4212 self.user_network_allocations = [ 

4213 {'share_server_id': self.share_server_id, 

4214 'ip_address': '1.1.1.1', 

4215 'status': constants.STATUS_ACTIVE, 

4216 'label': None, 

4217 'share_network_subnet_id': self.share_network_subnet_id}, 

4218 {'share_server_id': self.share_server_id, 

4219 'ip_address': '2.2.2.2', 

4220 'status': constants.STATUS_ACTIVE, 

4221 'label': 'user', 

4222 'share_network_subnet_id': self.share_network_subnet_id}, 

4223 ] 

4224 self.admin_network_allocations = [ 

4225 {'share_server_id': self.share_server_id, 

4226 'ip_address': '3.3.3.3', 

4227 'status': constants.STATUS_ACTIVE, 

4228 'label': 'admin', 

4229 'share_network_subnet_id': None}, 

4230 {'share_server_id': self.share_server_id, 

4231 'ip_address': '4.4.4.4', 

4232 'status': constants.STATUS_ACTIVE, 

4233 'label': 'admin', 

4234 'share_network_subnet_id': None}, 

4235 ] 

4236 

4237 def _setup_network_allocations_get_for_share_server(self): 

4238 # Create share network 

4239 share_network_data = { 

4240 'id': 'foo_share_network_id', 

4241 'user_id': self.user_id, 

4242 'project_id': self.project_id, 

4243 } 

4244 db_api.share_network_create(self.ctxt, share_network_data) 

4245 

4246 # Create share network subnet 

4247 share_network_subnet_data = { 

4248 'id': self.share_network_subnet_id, 

4249 'share_network_id': self.user_id, 

4250 } 

4251 db_api.share_network_subnet_create(self.ctxt, 

4252 share_network_subnet_data) 

4253 

4254 # Create share server 

4255 share_server_data = { 

4256 'id': self.share_server_id, 

4257 'host': 'fake_host', 

4258 'status': 'active', 

4259 } 

4260 db_api.share_server_create(self.ctxt, share_server_data) 

4261 

4262 # Create user network allocations 

4263 for user_network_allocation in self.user_network_allocations: 

4264 db_api.network_allocation_create( 

4265 self.ctxt, user_network_allocation) 

4266 

4267 # Create admin network allocations 

4268 for admin_network_allocation in self.admin_network_allocations: 

4269 db_api.network_allocation_create( 

4270 self.ctxt, admin_network_allocation) 

4271 

4272 def test_get_only_user_network_allocations(self): 

4273 self._setup_network_allocations_get_for_share_server() 

4274 

4275 result = db_api.network_allocations_get_for_share_server( 

4276 self.ctxt, self.share_server_id, label='user') 

4277 

4278 self.assertEqual( 

4279 len(self.user_network_allocations), len(result)) 

4280 for na in result: 

4281 self.assertIn(na.label, (None, 'user')) 

4282 

4283 def test_get_only_admin_network_allocations(self): 

4284 self._setup_network_allocations_get_for_share_server() 

4285 

4286 result = db_api.network_allocations_get_for_share_server( 

4287 self.ctxt, self.share_server_id, label='admin') 

4288 

4289 self.assertEqual( 

4290 len(self.admin_network_allocations), len(result)) 

4291 for na in result: 

4292 self.assertEqual(na.label, 'admin') 

4293 

4294 def test_get_all_network_allocations(self): 

4295 self._setup_network_allocations_get_for_share_server() 

4296 

4297 result = db_api.network_allocations_get_for_share_server( 

4298 self.ctxt, self.share_server_id, label=None) 

4299 

4300 self.assertEqual( 

4301 len(self.user_network_allocations + 

4302 self.admin_network_allocations), 

4303 len(result) 

4304 ) 

4305 for na in result: 

4306 self.assertIn(na.label, ('admin', 'user', None)) 

4307 

4308 def test_network_allocation_get(self): 

4309 self._setup_network_allocations_get_for_share_server() 

4310 

4311 for allocation in self.admin_network_allocations: 

4312 result = db_api.network_allocation_get(self.ctxt, allocation['id']) 

4313 

4314 self.assertIsInstance(result, models.NetworkAllocation) 

4315 self.assertEqual(allocation['id'], result.id) 

4316 

4317 for allocation in self.user_network_allocations: 

4318 result = db_api.network_allocation_get(self.ctxt, allocation['id']) 

4319 

4320 self.assertIsInstance(result, models.NetworkAllocation) 

4321 self.assertEqual(allocation['id'], result.id) 

4322 

4323 def test_network_allocation_get_no_result(self): 

4324 self._setup_network_allocations_get_for_share_server() 

4325 

4326 self.assertRaises(exception.NotFound, 

4327 db_api.network_allocation_get, 

4328 self.ctxt, 

4329 id='fake') 

4330 

4331 def test_network_allocation_get_by_subnet_id(self): 

4332 self._setup_network_allocations_get_for_share_server() 

4333 

4334 result = db_api.network_allocations_get_for_share_server( 

4335 self.ctxt, self.share_server_id, 

4336 subnet_id=self.share_network_subnet_id) 

4337 

4338 self.assertEqual(2, len(result)) 

4339 

4340 for network_allocation in result: 

4341 self.assertIsInstance(network_allocation, models.NetworkAllocation) 

4342 self.assertEqual(self.share_network_subnet_id, 

4343 network_allocation.share_network_subnet_id) 

4344 

4345 @ddt.data(True, False) 

4346 def test_network_allocation_get_read_deleted(self, read_deleted): 

4347 self._setup_network_allocations_get_for_share_server() 

4348 

4349 deleted_allocation = { 

4350 'share_server_id': self.share_server_id, 

4351 'ip_address': '1.1.1.1', 

4352 'status': constants.STATUS_ACTIVE, 

4353 'label': None, 

4354 'deleted': True, 

4355 } 

4356 

4357 new_obj = db_api.network_allocation_create(self.ctxt, 

4358 deleted_allocation) 

4359 if read_deleted: 

4360 result = db_api.network_allocation_get(self.ctxt, new_obj.id, 

4361 read_deleted=read_deleted) 

4362 self.assertIsInstance(result, models.NetworkAllocation) 

4363 self.assertEqual(new_obj.id, result.id) 

4364 else: 

4365 self.assertRaises(exception.NotFound, 

4366 db_api.network_allocation_get, 

4367 self.ctxt, 

4368 id=self.share_server_id) 

4369 

4370 def test_network_allocation_update(self): 

4371 self._setup_network_allocations_get_for_share_server() 

4372 

4373 for allocation in self.admin_network_allocations: 

4374 old_obj = db_api.network_allocation_get(self.ctxt, 

4375 allocation['id']) 

4376 self.assertEqual('False', old_obj.deleted) 

4377 updated_object = db_api.network_allocation_update( 

4378 self.ctxt, allocation['id'], {'deleted': 'True'}) 

4379 

4380 self.assertEqual('True', updated_object.deleted) 

4381 

4382 @ddt.data(True, False) 

4383 def test_network_allocation_update_read_deleted(self, read_deleted): 

4384 self._setup_network_allocations_get_for_share_server() 

4385 

4386 db_api.network_allocation_update( 

4387 self.ctxt, 

4388 self.admin_network_allocations[0]['id'], 

4389 {'deleted': 'True'} 

4390 ) 

4391 

4392 if read_deleted: 

4393 updated_object = db_api.network_allocation_update( 

4394 self.ctxt, self.admin_network_allocations[0]['id'], 

4395 {'deleted': 'False'}, read_deleted=read_deleted 

4396 ) 

4397 self.assertEqual('False', updated_object.deleted) 

4398 else: 

4399 self.assertRaises(exception.NotFound, 

4400 db_api.network_allocation_update, 

4401 self.ctxt, 

4402 id=self.share_server_id, 

4403 values={'deleted': read_deleted}, 

4404 read_deleted=read_deleted) 

4405 

4406 

4407class ReservationDatabaseAPITest(test.TestCase): 

4408 

4409 def setUp(self): 

4410 super(ReservationDatabaseAPITest, self).setUp() 

4411 self.context = context.get_admin_context() 

4412 

4413 def test_reservation_expire(self): 

4414 quota_usage = db_api.quota_usage_create(self.context, 'fake_project', 

4415 'fake_user', 'fake_resource', 

4416 0, 12, until_refresh=None) 

4417 with db_api.context_manager.writer.using(self.context): 

4418 for time_s in (-1, 1): 

4419 reservation = db_api._reservation_create( 

4420 self.context, 'fake_uuid', 

4421 quota_usage, 'fake_project', 

4422 'fake_user', 'fake_resource', 10, 

4423 timeutils.utcnow() + 

4424 datetime.timedelta(days=time_s), 

4425 ) 

4426 

4427 db_api.reservation_expire(self.context) 

4428 

4429 with db_api.context_manager.reader.using(self.context): 

4430 reservations = db_api._quota_reservations_query( 

4431 self.context, ['fake_uuid'], 

4432 ).all() 

4433 quota_usage = db_api.quota_usage_get(self.context, 'fake_project', 

4434 'fake_resource') 

4435 self.assertEqual(1, len(reservations)) 

4436 self.assertEqual(reservation['id'], reservations[0]['id']) 

4437 self.assertEqual(2, quota_usage['reserved']) 

4438 

4439 

4440@ddt.ddt 

4441class PurgeDeletedTest(test.TestCase): 

4442 

4443 def setUp(self): 

4444 super(PurgeDeletedTest, self).setUp() 

4445 self.context = context.get_admin_context() 

4446 

4447 def _days_ago(self, begin, end): 

4448 return timeutils.utcnow() - datetime.timedelta( 

4449 days=random.randint(begin, end)) 

4450 

4451 def _turn_on_foreign_key(self): 

4452 engine = db_api.get_engine() 

4453 connection = engine.raw_connection() 

4454 try: 

4455 cursor = connection.cursor() 

4456 cursor.execute("PRAGMA foreign_keys = ON") 

4457 finally: 

4458 connection.close() 

4459 

4460 @ddt.data({"del_days": 0, "num_left": 0}, 

4461 {"del_days": 10, "num_left": 2}, 

4462 {"del_days": 20, "num_left": 4}) 

4463 @ddt.unpack 

4464 def test_purge_records_with_del_days(self, del_days, num_left): 

4465 fake_now = timeutils.utcnow() 

4466 with mock.patch.object(timeutils, 'utcnow', 

4467 mock.Mock(return_value=fake_now)): 

4468 # create resources soft-deleted in 0~9, 10~19 days ago 

4469 for start, end in ((0, 9), (10, 19)): 

4470 for unused in range(2): 

4471 # share type 

4472 db_utils.create_share_type(id=uuidutils.generate_uuid(), 

4473 deleted_at=self._days_ago(start, 

4474 end)) 

4475 # share 

4476 share = db_utils.create_share_without_instance( 

4477 metadata={}, 

4478 deleted_at=self._days_ago(start, end)) 

4479 # create share network 

4480 network = db_utils.create_share_network( 

4481 id=uuidutils.generate_uuid(), 

4482 deleted_at=self._days_ago(start, end)) 

4483 # create security service 

4484 db_utils.create_security_service( 

4485 id=uuidutils.generate_uuid(), 

4486 share_network_id=network.id, 

4487 deleted_at=self._days_ago(start, end)) 

4488 # create share instance 

4489 s_instance = db_utils.create_share_instance( 

4490 id=uuidutils.generate_uuid(), 

4491 share_network_id=network.id, 

4492 share_id=share.id) 

4493 # share access 

4494 db_utils.create_share_access( 

4495 id=uuidutils.generate_uuid(), 

4496 share_id=share['id'], 

4497 deleted_at=self._days_ago(start, end)) 

4498 # create share server 

4499 db_utils.create_share_server( 

4500 id=uuidutils.generate_uuid(), 

4501 deleted_at=self._days_ago(start, end)) 

4502 # create snapshot 

4503 db_api.share_snapshot_create( 

4504 self.context, {'share_id': share['id'], 

4505 'deleted_at': self._days_ago(start, 

4506 end)}, 

4507 create_snapshot_instance=False) 

4508 # update share instance 

4509 db_api.share_instance_update( 

4510 self.context, 

4511 s_instance.id, 

4512 {'deleted_at': self._days_ago(start, end)}) 

4513 

4514 db_api.purge_deleted_records(self.context, age_in_days=del_days) 

4515 

4516 for model in [models.ShareTypes, models.Share, 

4517 models.ShareNetwork, models.ShareAccessMapping, 

4518 models.ShareInstance, models.ShareServer, 

4519 models.ShareSnapshot, models.SecurityService]: 

4520 with db_api.context_manager.reader.using(self.context): 

4521 rows = db_api.model_query(self.context, model).count() 

4522 self.assertEqual(num_left, rows) 

4523 

4524 def test_purge_records_with_illegal_args(self): 

4525 self.assertRaises(TypeError, db_api.purge_deleted_records, 

4526 self.context) 

4527 self.assertRaises(exception.InvalidParameterValue, 

4528 db_api.purge_deleted_records, 

4529 self.context, 

4530 age_in_days=-1) 

4531 

4532 def test_purge_records_with_constraint(self): 

4533 self._turn_on_foreign_key() 

4534 type_id = uuidutils.generate_uuid() 

4535 # create share type1 

4536 db_utils.create_share_type(id=type_id, 

4537 deleted_at=self._days_ago(1, 1)) 

4538 # create share type2 

4539 db_utils.create_share_type(id=uuidutils.generate_uuid(), 

4540 deleted_at=self._days_ago(1, 1)) 

4541 # create share 

4542 share = db_utils.create_share(share_type_id=type_id) 

4543 

4544 db_api.purge_deleted_records(self.context, age_in_days=0) 

4545 with db_api.context_manager.reader.using(self.context): 

4546 type_row = db_api.model_query( 

4547 self.context, models.ShareTypes 

4548 ).count() 

4549 # share type1 should not be deleted 

4550 self.assertEqual(1, type_row) 

4551 with db_api.context_manager.writer.using(self.context): 

4552 db_api.model_query(self.context, models.ShareInstance).delete() 

4553 db_api.share_delete(self.context, share['id']) 

4554 

4555 db_api.purge_deleted_records(self.context, age_in_days=0) 

4556 with db_api.context_manager.reader.using(self.context): 

4557 s_row = db_api.model_query(self.context, models.Share).count() 

4558 type_row = db_api.model_query( 

4559 self.context, models.ShareTypes 

4560 ).count() 

4561 self.assertEqual(0, s_row + type_row) 

4562 

4563 

4564@ddt.ddt 

4565class ShareTypeAPITestCase(test.TestCase): 

4566 

4567 def setUp(self): 

4568 super(ShareTypeAPITestCase, self).setUp() 

4569 self.ctxt = context.RequestContext( 

4570 user_id='user_id', project_id='project_id', is_admin=True) 

4571 

4572 @ddt.data({'used_by_shares': True, 'used_by_group_types': False}, 

4573 {'used_by_shares': False, 'used_by_group_types': True}, 

4574 {'used_by_shares': True, 'used_by_group_types': True}) 

4575 @ddt.unpack 

4576 def test_share_type_destroy_in_use(self, used_by_shares, 

4577 used_by_group_types): 

4578 share_type_1 = db_utils.create_share_type( 

4579 name='orange', extra_specs={'somekey': 'someval'}, 

4580 is_public=False, override_defaults=True) 

4581 share_type_2 = db_utils.create_share_type( 

4582 name='regalia', override_defaults=True) 

4583 db_api.share_type_access_add(self.ctxt, 

4584 share_type_1['id'], 

4585 "2018ndaetfigovnsaslcahfavmrpions") 

4586 db_api.share_type_access_add(self.ctxt, 

4587 share_type_1['id'], 

4588 "2016ndaetfigovnsaslcahfavmrpions") 

4589 if used_by_shares: 

4590 share_1 = db_utils.create_share(share_type_id=share_type_1['id']) 

4591 db_utils.create_share(share_type_id=share_type_2['id']) 

4592 if used_by_group_types: 

4593 group_type_1 = db_utils.create_share_group_type( 

4594 name='crimson', share_types=[share_type_1['id']]) 

4595 db_utils.create_share_group_type( 

4596 name='tide', share_types=[share_type_2['id']]) 

4597 share_group_1 = db_utils.create_share_group( 

4598 share_group_type_id=group_type_1['id'], 

4599 share_types=[share_type_1['id']]) 

4600 

4601 self.assertRaises(exception.ShareTypeInUse, 

4602 db_api.share_type_destroy, 

4603 self.ctxt, share_type_1['id']) 

4604 self.assertRaises(exception.ShareTypeInUse, 

4605 db_api.share_type_destroy, 

4606 self.ctxt, share_type_2['id']) 

4607 

4608 # Let's cleanup share_type_1 and verify it is gone 

4609 if used_by_shares: 

4610 db_api.share_instance_delete(self.ctxt, share_1.instance.id) 

4611 if used_by_group_types: 

4612 db_api.share_group_destroy(self.ctxt, share_group_1['id']) 

4613 db_api.share_group_type_destroy(self.ctxt, 

4614 group_type_1['id']) 

4615 

4616 self.assertIsNone( 

4617 db_api.share_type_destroy(self.ctxt, share_type_1['id'])) 

4618 self.assertDictEqual( 

4619 {}, db_api.share_type_extra_specs_get( 

4620 self.ctxt, share_type_1['id'])) 

4621 self.assertRaises(exception.ShareTypeNotFound, 

4622 db_api.share_type_access_get_all, 

4623 self.ctxt, share_type_1['id']) 

4624 self.assertRaises(exception.ShareTypeNotFound, 

4625 db_api.share_type_get, 

4626 self.ctxt, share_type_1['id']) 

4627 

4628 # share_type_2 must still be around 

4629 self.assertEqual( 

4630 share_type_2['id'], 

4631 db_api.share_type_get(self.ctxt, share_type_2['id'])['id']) 

4632 

4633 @ddt.data({'usages': False, 'reservations': False}, 

4634 {'usages': False, 'reservations': True}, 

4635 {'usages': True, 'reservations': False}) 

4636 @ddt.unpack 

4637 def test_share_type_destroy_quotas_and_reservations(self, usages, 

4638 reservations): 

4639 share_type = db_utils.create_share_type(name='clemsontigers') 

4640 shares_quota = db_api.quota_create( 

4641 self.ctxt, "fake-project-id", 'shares', 10, 

4642 share_type_id=share_type['id']) 

4643 snapshots_quota = db_api.quota_create( 

4644 self.ctxt, "fake-project-id", 'snapshots', 30, 

4645 share_type_id=share_type['id']) 

4646 

4647 if reservations: 

4648 resources = { 

4649 'shares': quota.ReservableResource('shares', '_sync_shares'), 

4650 'snapshots': quota.ReservableResource( 

4651 'snapshots', '_sync_snapshots'), 

4652 } 

4653 project_quotas = { 

4654 'shares': shares_quota.hard_limit, 

4655 'snapshots': snapshots_quota.hard_limit, 

4656 } 

4657 user_quotas = { 

4658 'shares': shares_quota.hard_limit, 

4659 'snapshots': snapshots_quota.hard_limit, 

4660 } 

4661 deltas = {'shares': 1, 'snapshots': 3} 

4662 expire = timeutils.utcnow() + datetime.timedelta(seconds=86400) 

4663 reservation_uuids = db_api.quota_reserve( 

4664 self.ctxt, resources, project_quotas, user_quotas, 

4665 project_quotas, deltas, expire, False, 30, 

4666 project_id='fake-project-id', share_type_id=share_type['id']) 

4667 

4668 with db_api.context_manager.reader.using(self.ctxt): 

4669 q_reservations = db_api._quota_reservations_query( 

4670 self.ctxt, reservation_uuids, 

4671 ).all() 

4672 # There should be 2 "user" reservations and 2 "share-type" 

4673 # quota reservations 

4674 self.assertEqual(4, len(q_reservations)) 

4675 q_share_type_reservations = [qr for qr in q_reservations 

4676 if qr['share_type_id'] is not None] 

4677 # There should be exactly two "share type" quota reservations 

4678 self.assertEqual(2, len(q_share_type_reservations)) 

4679 for q_reservation in q_share_type_reservations: 

4680 self.assertEqual(q_reservation['share_type_id'], 

4681 share_type['id']) 

4682 

4683 if usages: 

4684 db_api.quota_usage_create(self.ctxt, 'fake-project-id', 

4685 'fake-user-id', 'shares', 3, 2, False, 

4686 share_type_id=share_type['id']) 

4687 db_api.quota_usage_create(self.ctxt, 'fake-project-id', 

4688 'fake-user-id', 'snapshots', 2, 2, False, 

4689 share_type_id=share_type['id']) 

4690 q_usages = db_api.quota_usage_get_all_by_project_and_share_type( 

4691 self.ctxt, 'fake-project-id', share_type['id']) 

4692 self.assertEqual(3, q_usages['shares']['in_use']) 

4693 self.assertEqual(2, q_usages['shares']['reserved']) 

4694 self.assertEqual(2, q_usages['snapshots']['in_use']) 

4695 self.assertEqual(2, q_usages['snapshots']['reserved']) 

4696 

4697 # Validate that quotas exist 

4698 share_type_quotas = db_api.quota_get_all_by_project_and_share_type( 

4699 self.ctxt, 'fake-project-id', share_type['id']) 

4700 expected_quotas = { 

4701 'project_id': 'fake-project-id', 

4702 'share_type_id': share_type['id'], 

4703 'shares': 10, 

4704 'snapshots': 30, 

4705 } 

4706 self.assertDictEqual(expected_quotas, share_type_quotas) 

4707 

4708 db_api.share_type_destroy(self.ctxt, share_type['id']) 

4709 

4710 self.assertRaises(exception.ShareTypeNotFound, 

4711 db_api.share_type_get, 

4712 self.ctxt, share_type['id']) 

4713 # Quotas must be gone 

4714 share_type_quotas = db_api.quota_get_all_by_project_and_share_type( 

4715 self.ctxt, 'fake-project-id', share_type['id']) 

4716 self.assertEqual({'project_id': 'fake-project-id', 

4717 'share_type_id': share_type['id']}, 

4718 share_type_quotas) 

4719 

4720 # Check usages and reservations 

4721 if usages: 

4722 q_usages = db_api.quota_usage_get_all_by_project_and_share_type( 

4723 self.ctxt, 'fake-project-id', share_type['id']) 

4724 expected_q_usages = {'project_id': 'fake-project-id', 

4725 'share_type_id': share_type['id']} 

4726 self.assertDictEqual(expected_q_usages, q_usages) 

4727 if reservations: 

4728 with db_api.context_manager.reader.using(self.ctxt): 

4729 q_reservations = db_api._quota_reservations_query( 

4730 self.ctxt, reservation_uuids, 

4731 ).all() 

4732 # just "user" quota reservations should be left, since we didn't 

4733 # clean them up. 

4734 self.assertEqual(2, len(q_reservations)) 

4735 for q_reservation in q_reservations: 

4736 self.assertIsNone(q_reservation['share_type_id']) 

4737 

4738 @ddt.data( 

4739 (None, None, 5), 

4740 ('fake2', None, 2), 

4741 (None, 'fake', 3), 

4742 ) 

4743 @ddt.unpack 

4744 def test_share_replica_data_get_for_project( 

4745 self, user_id, share_type_id, expected_result): 

4746 kwargs = {} 

4747 if share_type_id: 

4748 kwargs.update({'id': share_type_id}) 

4749 share_type_1 = db_utils.create_share_type(**kwargs) 

4750 share_type_2 = db_utils.create_share_type() 

4751 

4752 share_1 = db_utils.create_share(size=1, user_id='fake', 

4753 share_type_id=share_type_1['id']) 

4754 share_2 = db_utils.create_share(size=1, user_id='fake2', 

4755 share_type_id=share_type_2['id']) 

4756 project_id = share_1['project_id'] 

4757 db_utils.create_share_replica( 

4758 replica_state=constants.REPLICA_STATE_ACTIVE, 

4759 share_id=share_1['id'], share_type_id=share_type_1['id']) 

4760 db_utils.create_share_replica( 

4761 replica_state=constants.REPLICA_STATE_IN_SYNC, 

4762 share_id=share_1['id'], share_type_id=share_type_1['id']) 

4763 db_utils.create_share_replica( 

4764 replica_state=constants.REPLICA_STATE_IN_SYNC, 

4765 share_id=share_1['id'], share_type_id=share_type_1['id']) 

4766 

4767 db_utils.create_share_replica( 

4768 replica_state=constants.REPLICA_STATE_ACTIVE, 

4769 share_id=share_2['id'], share_type_id=share_type_2['id']) 

4770 db_utils.create_share_replica( 

4771 replica_state=constants.REPLICA_STATE_IN_SYNC, 

4772 share_id=share_2['id'], share_type_id=share_type_2['id']) 

4773 

4774 kwargs = {} 

4775 if user_id: 

4776 kwargs.update({'user_id': user_id}) 

4777 if share_type_id: 

4778 kwargs.update({'share_type_id': share_type_id}) 

4779 

4780 with db_api.context_manager.reader.using(self.ctxt): 

4781 total_amt, total_size = db_api._share_replica_data_get_for_project( 

4782 self.ctxt, project_id, **kwargs, 

4783 ) 

4784 self.assertEqual(expected_result, total_amt) 

4785 self.assertEqual(expected_result, total_size) 

4786 

4787 def test_share_type_get_by_name_or_id_found_by_id(self): 

4788 share_type = db_utils.create_share_type() 

4789 

4790 result = db_api.share_type_get_by_name_or_id( 

4791 self.ctxt, share_type['id']) 

4792 

4793 self.assertIsNotNone(result) 

4794 self.assertEqual(share_type['id'], result['id']) 

4795 

4796 def test_share_type_get_by_name_or_id_found_by_name(self): 

4797 name = uuidutils.generate_uuid() 

4798 db_utils.create_share_type(name=name) 

4799 

4800 result = db_api.share_type_get_by_name_or_id(self.ctxt, name) 

4801 

4802 self.assertIsNotNone(result) 

4803 self.assertEqual(name, result['name']) 

4804 self.assertNotEqual(name, result['id']) 

4805 

4806 def test_share_type_get_by_name_or_id_when_does_not_exist(self): 

4807 fake_id = uuidutils.generate_uuid() 

4808 

4809 result = db_api.share_type_get_by_name_or_id(self.ctxt, fake_id) 

4810 

4811 self.assertIsNone(result) 

4812 

4813 def test_share_type_get_with_none_id(self): 

4814 self.assertRaises(exception.DefaultShareTypeNotConfigured, 

4815 db_api.share_type_get, self.ctxt, None) 

4816 

4817 @ddt.data( 

4818 {'name': 'st_1', 'description': 'des_1', 'is_public': True}, 

4819 {'name': 'st_2', 'description': 'des_2', 'is_public': None}, 

4820 {'name': 'st_3', 'description': None, 'is_public': False}, 

4821 {'name': None, 'description': 'des_4', 'is_public': True}, 

4822 ) 

4823 @ddt.unpack 

4824 def test_share_type_update(self, name, description, is_public): 

4825 values = {} 

4826 if name: 

4827 values.update({'name': name}) 

4828 if description: 

4829 values.update({'description': description}) 

4830 if is_public is not None: 

4831 values.update({'is_public': is_public}) 

4832 share_type = db_utils.create_share_type(name='st_name') 

4833 db_api.share_type_update(self.ctxt, share_type['id'], values) 

4834 updated_st = db_api.share_type_get_by_name_or_id(self.ctxt, 

4835 share_type['id']) 

4836 if name: 

4837 self.assertEqual(name, updated_st['name']) 

4838 if description: 

4839 self.assertEqual(description, updated_st['description']) 

4840 if is_public is not None: 

4841 self.assertEqual(is_public, updated_st['is_public']) 

4842 

4843 def test_share_type_update_not_found(self): 

4844 share_type = db_utils.create_share_type(name='st_update_test') 

4845 db_api.share_type_destroy(self.ctxt, share_type['id']) 

4846 values = {"name": "not_exist"} 

4847 self.assertRaises(exception.ShareTypeNotFound, 

4848 db_api.share_type_update, 

4849 self.ctxt, share_type['id'], values) 

4850 

4851 

4852class MessagesDatabaseAPITestCase(test.TestCase): 

4853 

4854 def setUp(self): 

4855 super(MessagesDatabaseAPITestCase, self).setUp() 

4856 self.user_id = uuidutils.generate_uuid() 

4857 self.project_id = uuidutils.generate_uuid() 

4858 self.ctxt = context.RequestContext( 

4859 user_id=self.user_id, project_id=self.project_id, is_admin=False) 

4860 

4861 def test_message_create(self): 

4862 result = db_utils.create_message(project_id=self.project_id, 

4863 action_id='001') 

4864 

4865 self.assertIsNotNone(result['id']) 

4866 

4867 def test_message_delete(self): 

4868 result = db_utils.create_message(project_id=self.project_id, 

4869 action_id='001') 

4870 

4871 db_api.message_destroy(self.ctxt, result) 

4872 

4873 self.assertRaises(exception.NotFound, db_api.message_get, 

4874 self.ctxt, result['id']) 

4875 

4876 def test_message_get(self): 

4877 message = db_utils.create_message(project_id=self.project_id, 

4878 action_id='001') 

4879 

4880 result = db_api.message_get(self.ctxt, message['id']) 

4881 

4882 self.assertEqual(message['id'], result['id']) 

4883 self.assertEqual(message['action_id'], result['action_id']) 

4884 self.assertEqual(message['detail_id'], result['detail_id']) 

4885 self.assertEqual(message['project_id'], result['project_id']) 

4886 self.assertEqual(message['message_level'], result['message_level']) 

4887 

4888 def test_message_get_not_found(self): 

4889 self.assertRaises(exception.MessageNotFound, db_api.message_get, 

4890 self.ctxt, 'fake_id') 

4891 

4892 def test_message_get_different_project(self): 

4893 message = db_utils.create_message(project_id='another-project', 

4894 action_id='001') 

4895 

4896 self.assertRaises(exception.MessageNotFound, db_api.message_get, 

4897 self.ctxt, message['id']) 

4898 

4899 def test_message_get_all(self): 

4900 db_utils.create_message(project_id=self.project_id, action_id='001') 

4901 db_utils.create_message(project_id=self.project_id, action_id='001') 

4902 db_utils.create_message(project_id='another-project', action_id='001') 

4903 

4904 result = db_api.message_get_all(self.ctxt) 

4905 

4906 self.assertEqual(2, len(result)) 

4907 

4908 def test_message_get_all_as_admin(self): 

4909 db_utils.create_message(project_id=self.project_id, action_id='001') 

4910 db_utils.create_message(project_id=self.project_id, action_id='001') 

4911 db_utils.create_message(project_id='another-project', action_id='001') 

4912 

4913 result = db_api.message_get_all(self.ctxt.elevated()) 

4914 

4915 self.assertEqual(3, len(result)) 

4916 

4917 def test_message_get_all_with_filter(self): 

4918 for i in ['001', '002', '002']: 

4919 db_utils.create_message(project_id=self.project_id, action_id=i) 

4920 

4921 result = db_api.message_get_all(self.ctxt, 

4922 filters={'action_id': '002'}) 

4923 

4924 self.assertEqual(2, len(result)) 

4925 

4926 def test_message_get_all_with_created_since_or_before_filter(self): 

4927 now = timeutils.utcnow() 

4928 db_utils.create_message(project_id=self.project_id, 

4929 action_id='001', 

4930 created_at=now - datetime.timedelta(seconds=1)) 

4931 db_utils.create_message(project_id=self.project_id, 

4932 action_id='001', 

4933 created_at=now + datetime.timedelta(seconds=1)) 

4934 db_utils.create_message(project_id=self.project_id, 

4935 action_id='001', 

4936 created_at=now + datetime.timedelta(seconds=2)) 

4937 result1 = db_api.message_get_all(self.ctxt, 

4938 filters={'created_before': now}) 

4939 result2 = db_api.message_get_all(self.ctxt, 

4940 filters={'created_since': now}) 

4941 self.assertEqual(1, len(result1)) 

4942 self.assertEqual(2, len(result2)) 

4943 

4944 def test_message_get_all_with_invalid_sort_key(self): 

4945 self.assertRaises(exception.InvalidInput, db_api.message_get_all, 

4946 self.ctxt, sort_key='invalid_key') 

4947 

4948 def test_message_get_all_sorted_asc(self): 

4949 ids = [] 

4950 for i in ['001', '002', '003']: 

4951 msg = db_utils.create_message(project_id=self.project_id, 

4952 action_id=i) 

4953 ids.append(msg.id) 

4954 

4955 result = db_api.message_get_all(self.ctxt, 

4956 sort_key='action_id', 

4957 sort_dir='asc') 

4958 result_ids = [r.id for r in result] 

4959 self.assertEqual(result_ids, ids) 

4960 

4961 def test_message_get_all_with_limit_and_offset(self): 

4962 for i in ['001', '002']: 

4963 db_utils.create_message(project_id=self.project_id, 

4964 action_id=i) 

4965 

4966 result = db_api.message_get_all(self.ctxt, limit=1, offset=1) 

4967 self.assertEqual(1, len(result)) 

4968 

4969 def test_message_get_all_sorted(self): 

4970 ids = [] 

4971 for i in ['003', '002', '001']: 

4972 msg = db_utils.create_message(project_id=self.project_id, 

4973 action_id=i) 

4974 ids.append(msg.id) 

4975 

4976 # Default the sort direction to descending 

4977 result = db_api.message_get_all(self.ctxt, sort_key='action_id') 

4978 result_ids = [r.id for r in result] 

4979 self.assertEqual(result_ids, ids) 

4980 

4981 def test_cleanup_expired_messages(self): 

4982 adm_context = self.ctxt.elevated() 

4983 

4984 now = timeutils.utcnow() 

4985 db_utils.create_message(project_id=self.project_id, 

4986 action_id='001', 

4987 expires_at=now) 

4988 db_utils.create_message(project_id=self.project_id, 

4989 action_id='001', 

4990 expires_at=now - datetime.timedelta(days=1)) 

4991 db_utils.create_message(project_id=self.project_id, 

4992 action_id='001', 

4993 expires_at=now + datetime.timedelta(days=1)) 

4994 

4995 with mock.patch.object(timeutils, 'utcnow') as mock_time_now: 

4996 mock_time_now.return_value = now 

4997 db_api.cleanup_expired_messages(adm_context) 

4998 messages = db_api.message_get_all(adm_context) 

4999 self.assertEqual(2, len(messages)) 

5000 

5001 

5002class BackendInfoDatabaseAPITestCase(test.TestCase): 

5003 

5004 def setUp(self): 

5005 """Run before each test.""" 

5006 super(BackendInfoDatabaseAPITestCase, self).setUp() 

5007 self.ctxt = context.get_admin_context() 

5008 

5009 def test_create(self): 

5010 host = "fake_host" 

5011 value = "fake_hash_value" 

5012 

5013 initial_data = db_api.backend_info_get(self.ctxt, host) 

5014 db_api.backend_info_update(self.ctxt, host, value) 

5015 actual_data = db_api.backend_info_get(self.ctxt, host) 

5016 

5017 self.assertIsNone(initial_data) 

5018 self.assertEqual(value, actual_data['info_hash']) 

5019 self.assertEqual(host, actual_data['host']) 

5020 

5021 def test_get(self): 

5022 host = "fake_host" 

5023 value = "fake_hash_value" 

5024 

5025 db_api.backend_info_update(self.ctxt, host, value, False) 

5026 actual_result = db_api.backend_info_get(self.ctxt, host) 

5027 

5028 self.assertEqual(value, actual_result['info_hash']) 

5029 self.assertEqual(host, actual_result['host']) 

5030 

5031 def test_delete(self): 

5032 host = "fake_host" 

5033 value = "fake_hash_value" 

5034 

5035 db_api.backend_info_update(self.ctxt, host, value) 

5036 initial_data = db_api.backend_info_get(self.ctxt, host) 

5037 

5038 db_api.backend_info_update(self.ctxt, host, delete_existing=True) 

5039 actual_data = db_api.backend_info_get(self.ctxt, host) 

5040 

5041 self.assertEqual(value, initial_data['info_hash']) 

5042 self.assertEqual(host, initial_data['host']) 

5043 self.assertIsNone(actual_data) 

5044 

5045 def test_double_update(self): 

5046 host = "fake_host" 

5047 value_1 = "fake_hash_value_1" 

5048 value_2 = "fake_hash_value_2" 

5049 

5050 initial_data = db_api.backend_info_get(self.ctxt, host) 

5051 db_api.backend_info_update(self.ctxt, host, value_1) 

5052 db_api.backend_info_update(self.ctxt, host, value_2) 

5053 actual_data = db_api.backend_info_get(self.ctxt, host) 

5054 

5055 self.assertIsNone(initial_data) 

5056 self.assertEqual(value_2, actual_data['info_hash']) 

5057 self.assertEqual(host, actual_data['host']) 

5058 

5059 

5060@ddt.ddt 

5061class ShareResourcesAPITestCase(test.TestCase): 

5062 

5063 def setUp(self): 

5064 super(ShareResourcesAPITestCase, self).setUp() 

5065 self.context = context.get_admin_context() 

5066 

5067 @ddt.data('controller-100', 'controller-0@otherstore03', 

5068 'controller-0@otherstore01#pool200') 

5069 def test_share_resources_host_update_no_matches(self, current_host): 

5070 share_id = uuidutils.generate_uuid() 

5071 share_network_id = uuidutils.generate_uuid() 

5072 share_network_subnet_id = uuidutils.generate_uuid() 

5073 share_net_subnets = [db_utils.create_share_network_subnet( 

5074 id=share_network_subnet_id, 

5075 share_network_id=share_network_id)] 

5076 if '@' in current_host: 

5077 if '#' in current_host: 

5078 new_host = 'new-controller-X@backendX#poolX' 

5079 else: 

5080 new_host = 'new-controller-X@backendX' 

5081 else: 

5082 new_host = 'new-controller-X' 

5083 resources = [ # noqa 

5084 # share 

5085 db_utils.create_share_without_instance( 

5086 id=share_id, 

5087 status=constants.STATUS_AVAILABLE), 

5088 # share instances 

5089 db_utils.create_share_instance( 

5090 share_id=share_id, 

5091 host='controller-0@fancystore01#pool100', 

5092 status=constants.STATUS_AVAILABLE), 

5093 db_utils.create_share_instance( 

5094 share_id=share_id, 

5095 host='controller-0@otherstore02#pool100', 

5096 status=constants.STATUS_ERROR), 

5097 db_utils.create_share_instance( 

5098 share_id=share_id, 

5099 host='controller-2@beststore07#pool200', 

5100 status=constants.STATUS_DELETING), 

5101 # share groups 

5102 db_utils.create_share_group( 

5103 share_network_id=share_network_id, 

5104 host='controller-0@fancystore01#pool200', 

5105 status=constants.STATUS_AVAILABLE), 

5106 db_utils.create_share_group( 

5107 share_network_id=share_network_id, 

5108 host='controller-0@otherstore02#pool100', 

5109 status=constants.STATUS_ERROR), 

5110 db_utils.create_share_group( 

5111 share_network_id=share_network_id, 

5112 host='controller-2@beststore07#pool100', 

5113 status=constants.STATUS_DELETING), 

5114 # share servers 

5115 db_utils.create_share_server( 

5116 share_network_subnets=share_net_subnets, 

5117 host='controller-0@fancystore01', 

5118 status=constants.STATUS_ACTIVE), 

5119 db_utils.create_share_server( 

5120 share_network_subnets=share_net_subnets, 

5121 host='controller-0@otherstore02#pool100', 

5122 status=constants.STATUS_ERROR), 

5123 db_utils.create_share_server( 

5124 share_network_subnets=share_net_subnets, 

5125 host='controller-2@beststore07', 

5126 status=constants.STATUS_DELETING), 

5127 

5128 ] 

5129 

5130 updates = db_api.share_resources_host_update(self.context, 

5131 current_host, 

5132 new_host) 

5133 

5134 expected_updates = {'instances': 0, 'servers': 0, 'groups': 0} 

5135 self.assertDictEqual(expected_updates, updates) 

5136 # validate that resources are unmodified: 

5137 share_instances = db_api.share_instance_get_all( 

5138 self.context, filters={'share_id': share_id}) 

5139 share_groups = db_api.share_group_get_all( 

5140 self.context, filters={'share_network_id': share_network_id}) 

5141 with db_api.context_manager.reader.using(self.context): 

5142 share_servers = db_api._share_server_get_query( 

5143 self.context 

5144 ).filter( 

5145 models.ShareServer.share_network_subnets.any( 

5146 id=share_net_subnets[0]['id'] 

5147 ) 

5148 ).all() 

5149 self.assertEqual(3, len(share_instances)) 

5150 self.assertEqual(3, len(share_groups)) 

5151 self.assertEqual(3, len(share_servers)) 

5152 for share_instance in share_instances: 

5153 self.assertTrue(not share_instance['host'].startswith(new_host)) 

5154 for share_group in share_groups: 

5155 self.assertTrue(not share_group['host'].startswith(new_host)) 

5156 for share_server in share_servers: 

5157 self.assertTrue(not share_server['host'].startswith(new_host)) 

5158 

5159 @ddt.data( 

5160 {'current_host': 'controller-2', 

5161 'expected_updates': {'instances': 1, 'servers': 2, 'groups': 1}}, 

5162 {'current_host': 'controller-0@fancystore01', 

5163 'expected_updates': {'instances': 2, 'servers': 1, 'groups': 2}}, 

5164 {'current_host': 'controller-0@fancystore01#pool100', 

5165 'expected_updates': {'instances': 1, 'servers': 1, 'groups': 0}}) 

5166 @ddt.unpack 

5167 def test_share_resources_host_update_partial_matches(self, current_host, 

5168 expected_updates): 

5169 share_id = uuidutils.generate_uuid() 

5170 share_network_id = uuidutils.generate_uuid() 

5171 share_network_subnet_id = uuidutils.generate_uuid() 

5172 share_net_subnets = [db_utils.create_share_network_subnet( 

5173 id=share_network_subnet_id, 

5174 share_network_id=share_network_id)] 

5175 if '@' in current_host: 

5176 if '#' in current_host: 

5177 new_host = 'new-controller-X@backendX#poolX' 

5178 else: 

5179 new_host = 'new-controller-X@backendX' 

5180 else: 

5181 new_host = 'new-controller-X' 

5182 total_updates_expected = (expected_updates['instances'] 

5183 + expected_updates['groups'] 

5184 + expected_updates['servers']) 

5185 resources = [ # noqa 

5186 # share 

5187 db_utils.create_share_without_instance( 

5188 id=share_id, 

5189 status=constants.STATUS_AVAILABLE), 

5190 # share instances 

5191 db_utils.create_share_instance( 

5192 share_id=share_id, 

5193 host='controller-0@fancystore01#pool100', 

5194 status=constants.STATUS_AVAILABLE), 

5195 db_utils.create_share_instance( 

5196 share_id=share_id, 

5197 host='controller-0@fancystore01#pool200', 

5198 status=constants.STATUS_ERROR), 

5199 db_utils.create_share_instance( 

5200 share_id=share_id, 

5201 host='controller-2@beststore07#pool200', 

5202 status=constants.STATUS_DELETING), 

5203 # share groups 

5204 db_utils.create_share_group( 

5205 share_network_id=share_network_id, 

5206 host='controller-0@fancystore01#pool101', 

5207 status=constants.STATUS_ACTIVE), 

5208 db_utils.create_share_group( 

5209 share_network_id=share_network_id, 

5210 host='controller-0@fancystore01#pool101', 

5211 status=constants.STATUS_ERROR), 

5212 db_utils.create_share_group( 

5213 share_network_id=share_network_id, 

5214 host='controller-2@beststore07#pool200', 

5215 status=constants.STATUS_DELETING), 

5216 # share servers 

5217 db_utils.create_share_server( 

5218 share_network_subnets=share_net_subnets, 

5219 host='controller-0@fancystore01#pool100', 

5220 status=constants.STATUS_ACTIVE), 

5221 db_utils.create_share_server( 

5222 share_network_subnets=share_net_subnets, 

5223 host='controller-2@fancystore01', 

5224 status=constants.STATUS_ERROR), 

5225 db_utils.create_share_server( 

5226 share_network_subnets=share_net_subnets, 

5227 host='controller-2@beststore07#pool200', 

5228 status=constants.STATUS_DELETING), 

5229 ] 

5230 

5231 actual_updates = db_api.share_resources_host_update( 

5232 self.context, current_host, new_host) 

5233 

5234 share_instances = db_api.share_instance_get_all( 

5235 self.context, filters={'share_id': share_id}) 

5236 share_groups = db_api.share_group_get_all( 

5237 self.context, filters={'share_network_id': share_network_id}) 

5238 with db_api.context_manager.reader.using(self.context): 

5239 share_servers = db_api._share_server_get_query( 

5240 self.context 

5241 ).filter( 

5242 models.ShareServer.share_network_subnets.any( 

5243 id=share_net_subnets[0]['id'] 

5244 ) 

5245 ).all() 

5246 

5247 updated_resources = [ 

5248 res for res in share_instances + share_groups + share_servers 

5249 if res['host'].startswith(new_host) 

5250 ] 

5251 self.assertEqual(expected_updates, actual_updates) 

5252 self.assertEqual(total_updates_expected, len(updated_resources)) 

5253 

5254 def test_share_instance_status_update(self): 

5255 for i in range(1, 3): 

5256 instances = [ 

5257 db_utils.create_share_instance( 

5258 status=constants.STATUS_SERVER_MIGRATING, share_id='fake') 

5259 for __ in range(1, 3)] 

5260 share_instance_ids = [instance['id'] for instance in instances] 

5261 values = {'status': constants.STATUS_AVAILABLE} 

5262 

5263 db_api.share_instance_status_update( 

5264 self.context, share_instance_ids, values) 

5265 

5266 instances = [ 

5267 db_api.share_instance_get(self.context, instance_id) 

5268 for instance_id in share_instance_ids] 

5269 

5270 for instance in instances: 

5271 self.assertEqual(constants.STATUS_AVAILABLE, instance['status']) 

5272 

5273 def test_share_snapshot_instances_status_update(self): 

5274 share_instance = db_utils.create_share_instance( 

5275 status=constants.STATUS_AVAILABLE, share_id='fake') 

5276 instances = [ 

5277 db_utils.create_snapshot_instance( 

5278 'fake_snapshot_id_1', status=constants.STATUS_CREATING, 

5279 share_instance_id=share_instance['id']) 

5280 for __ in range(1, 3)] 

5281 

5282 snapshot_instance_ids = [instance['id'] for instance in instances] 

5283 values = {'status': constants.STATUS_AVAILABLE} 

5284 

5285 db_api.share_snapshot_instances_status_update( 

5286 self.context, snapshot_instance_ids, values) 

5287 

5288 instances = [ 

5289 db_api.share_snapshot_instance_get(self.context, instance_id) 

5290 for instance_id in snapshot_instance_ids] 

5291 

5292 for instance in instances: 

5293 self.assertEqual(constants.STATUS_AVAILABLE, instance['status']) 

5294 

5295 def test_share_and_snapshot_instances_status_update(self): 

5296 share_instance = db_utils.create_share_instance( 

5297 status=constants.STATUS_AVAILABLE, share_id='fake') 

5298 share_instance_ids = [share_instance['id']] 

5299 snap_instances = [ 

5300 db_utils.create_snapshot_instance( 

5301 'fake_snapshot_id_1', status=constants.STATUS_CREATING, 

5302 share_instance_id=share_instance['id']) 

5303 for __ in range(1, 3)] 

5304 

5305 snapshot_instance_ids = [instance['id'] for instance in snap_instances] 

5306 values = {'status': constants.STATUS_AVAILABLE} 

5307 

5308 mock_update_share_instances = self.mock_object( 

5309 db_api, '_share_instance_status_update', 

5310 mock.Mock(return_value=[share_instance])) 

5311 mock_update_snap_instances = self.mock_object( 

5312 db_api, '_share_snapshot_instances_status_update', 

5313 mock.Mock(return_value=snap_instances)) 

5314 

5315 updated_share_instances, updated_snap_instances = ( 

5316 db_api.share_and_snapshot_instances_status_update( 

5317 self.context, values, share_instance_ids=share_instance_ids, 

5318 snapshot_instance_ids=snapshot_instance_ids)) 

5319 

5320 mock_update_share_instances.assert_called_once_with( 

5321 self.context, share_instance_ids, values) 

5322 mock_update_snap_instances.assert_called_once_with( 

5323 self.context, snapshot_instance_ids, values) 

5324 self.assertEqual(updated_share_instances, [share_instance]) 

5325 self.assertEqual(updated_snap_instances, snap_instances) 

5326 

5327 @ddt.data( 

5328 { 

5329 'share_instance_status': constants.STATUS_ERROR, 

5330 'snap_instance_status': constants.STATUS_AVAILABLE, 

5331 'expected_exc': exception.InvalidShareInstance 

5332 }, 

5333 { 

5334 'share_instance_status': constants.STATUS_AVAILABLE, 

5335 'snap_instance_status': constants.STATUS_ERROR, 

5336 'expected_exc': exception.InvalidShareSnapshotInstance 

5337 } 

5338 ) 

5339 @ddt.unpack 

5340 def test_share_and_snapshot_instances_status_update_invalid_status( 

5341 self, share_instance_status, snap_instance_status, expected_exc): 

5342 share_instance = db_utils.create_share_instance( 

5343 status=share_instance_status, share_id='fake') 

5344 share_snapshot_instance = db_utils.create_snapshot_instance( 

5345 'fake_snapshot_id_1', status=snap_instance_status, 

5346 share_instance_id=share_instance['id']) 

5347 share_instance_ids = [share_instance['id']] 

5348 snap_instance_ids = [share_snapshot_instance['id']] 

5349 values = {'status': constants.STATUS_AVAILABLE} 

5350 

5351 mock_instances_get_all = self.mock_object( 

5352 db_api, '_share_instance_get_all', 

5353 mock.Mock(return_value=[share_instance])) 

5354 mock_snap_instances_get_all = self.mock_object( 

5355 db_api, '_share_snapshot_instance_get_all_with_filters', 

5356 mock.Mock(return_value=[share_snapshot_instance])) 

5357 

5358 self.assertRaises(expected_exc, 

5359 db_api.share_and_snapshot_instances_status_update, 

5360 self.context, 

5361 values, 

5362 share_instance_ids=share_instance_ids, 

5363 snapshot_instance_ids=snap_instance_ids, 

5364 current_expected_status=constants.STATUS_AVAILABLE) 

5365 

5366 mock_instances_get_all.assert_called_once_with( 

5367 self.context, filters={'instance_ids': share_instance_ids}, 

5368 ) 

5369 if snap_instance_status == constants.STATUS_ERROR: 

5370 mock_snap_instances_get_all.assert_called_once_with( 

5371 self.context, {'instance_ids': snap_instance_ids}, 

5372 ) 

5373 

5374 

5375@ddt.ddt 

5376class AsyncOperationDatabaseAPITestCase(test.TestCase): 

5377 

5378 def setUp(self): 

5379 """Run before each test.""" 

5380 super(AsyncOperationDatabaseAPITestCase, self).setUp() 

5381 self.user_id = uuidutils.generate_uuid() 

5382 self.project_id = uuidutils.generate_uuid() 

5383 self.ctxt = context.RequestContext( 

5384 user_id=self.user_id, project_id=self.project_id, is_admin=False) 

5385 

5386 def _get_async_operation_test_data(self): 

5387 return uuidutils.generate_uuid() 

5388 

5389 @ddt.data({"details": {"foo": "bar", "tee": "too"}, 

5390 "valid": {"foo": "bar", "tee": "too"}}, 

5391 {"details": {"foo": "bar", "tee": ["test"]}, 

5392 "valid": {"foo": "bar", "tee": str(["test"])}}) 

5393 @ddt.unpack 

5394 def test_update(self, details, valid): 

5395 entity_id = self._get_async_operation_test_data() 

5396 

5397 initial_data = db_api.async_operation_data_get(self.ctxt, entity_id) 

5398 db_api.async_operation_data_update(self.ctxt, entity_id, details) 

5399 actual_data = db_api.async_operation_data_get(self.ctxt, entity_id) 

5400 

5401 self.assertEqual({}, initial_data) 

5402 self.assertEqual(valid, actual_data) 

5403 

5404 @ddt.data({'with_deleted': True, 'append': False}, 

5405 {'with_deleted': True, 'append': True}, 

5406 {'with_deleted': False, 'append': False}, 

5407 {'with_deleted': False, 'append': True}) 

5408 @ddt.unpack 

5409 def test_update_with_more_values(self, with_deleted, append): 

5410 entity_id = self._get_async_operation_test_data() 

5411 details = {"tee": "too"} 

5412 more_details = {"foo": "bar"} 

5413 result = {"tee": "too", "foo": "bar"} 

5414 

5415 db_api.async_operation_data_update(self.ctxt, entity_id, details) 

5416 if with_deleted: 

5417 db_api.async_operation_data_delete(self.ctxt, entity_id) 

5418 if append: 

5419 more_details.update(details) 

5420 if with_deleted and not append: 

5421 result.pop("tee") 

5422 db_api.async_operation_data_update(self.ctxt, entity_id, more_details) 

5423 

5424 actual_result = db_api.async_operation_data_get(self.ctxt, entity_id) 

5425 

5426 self.assertEqual(result, actual_result) 

5427 

5428 @ddt.data(True, False) 

5429 def test_update_with_duplicate(self, with_deleted): 

5430 entity_id = self._get_async_operation_test_data() 

5431 details = {"tee": "too"} 

5432 

5433 db_api.async_operation_data_update(self.ctxt, entity_id, details) 

5434 if with_deleted: 

5435 db_api.async_operation_data_delete(self.ctxt, entity_id) 

5436 db_api.async_operation_data_update(self.ctxt, entity_id, details) 

5437 

5438 actual_result = db_api.async_operation_data_get(self.ctxt, 

5439 entity_id) 

5440 

5441 self.assertEqual(details, actual_result) 

5442 

5443 def test_update_with_delete_existing(self): 

5444 resource_id = self._get_async_operation_test_data() 

5445 details = {"key1": "val1", "key2": "val2", "key3": "val3"} 

5446 details_update = {"key1": "val1_upd", "key4": "new_val"} 

5447 

5448 # Create new details 

5449 db_api.async_operation_data_update(self.ctxt, resource_id, details) 

5450 db_api.async_operation_data_update(self.ctxt, resource_id, 

5451 details_update, 

5452 delete_existing=True) 

5453 

5454 actual_result = db_api.async_operation_data_get(self.ctxt, resource_id) 

5455 

5456 self.assertEqual(details_update, actual_result) 

5457 

5458 def test_get(self): 

5459 resource_id = self._get_async_operation_test_data() 

5460 test_key = "foo" 

5461 test_keys = [test_key, "tee"] 

5462 details = {test_keys[0]: "val", test_keys[1]: "val", "mee": "foo"} 

5463 db_api.async_operation_data_update(self.ctxt, resource_id, details) 

5464 

5465 actual_result_all = db_api.async_operation_data_get( 

5466 self.ctxt, resource_id) 

5467 actual_result_single_key = db_api.async_operation_data_get( 

5468 self.ctxt, resource_id, test_key) 

5469 actual_result_list = db_api.async_operation_data_get( 

5470 self.ctxt, resource_id, test_keys) 

5471 

5472 self.assertEqual(details, actual_result_all) 

5473 self.assertEqual(details[test_key], actual_result_single_key) 

5474 self.assertEqual(dict.fromkeys(test_keys, "val"), actual_result_list) 

5475 

5476 def test_delete_single(self): 

5477 test_id = self._get_async_operation_test_data() 

5478 test_key = "foo" 

5479 details = {test_key: "bar", "tee": "too"} 

5480 valid_result = {"tee": "too"} 

5481 db_api.async_operation_data_update(self.ctxt, test_id, details) 

5482 

5483 db_api.async_operation_data_delete(self.ctxt, test_id, test_key) 

5484 

5485 actual_result = db_api.async_operation_data_get( 

5486 self.ctxt, test_id) 

5487 

5488 self.assertEqual(valid_result, actual_result) 

5489 

5490 def test_delete_all(self): 

5491 test_id = self._get_async_operation_test_data() 

5492 details = {"foo": "bar", "tee": "too"} 

5493 db_api.async_operation_data_update(self.ctxt, test_id, details) 

5494 

5495 db_api.async_operation_data_delete(self.ctxt, test_id) 

5496 

5497 actual_result = db_api.async_operation_data_get( 

5498 self.ctxt, test_id) 

5499 

5500 self.assertEqual({}, actual_result) 

5501 

5502 

5503class TransfersTestCase(test.TestCase): 

5504 """Test case for transfers.""" 

5505 

5506 def setUp(self): 

5507 super(TransfersTestCase, self).setUp() 

5508 self.user_id = uuidutils.generate_uuid() 

5509 self.project_id = uuidutils.generate_uuid() 

5510 self.ctxt = context.RequestContext(user_id=self.user_id, 

5511 project_id=self.project_id) 

5512 

5513 @staticmethod 

5514 def _create_transfer(resource_type='share', 

5515 resource_id=None, source_project_id=None): 

5516 """Create a transfer object.""" 

5517 if resource_id and source_project_id: 

5518 transfer = db_utils.create_transfer( 

5519 resource_type=resource_type, 

5520 resource_id=resource_id, 

5521 source_project_id=source_project_id) 

5522 elif resource_id: 

5523 transfer = db_utils.create_transfer( 

5524 resource_type=resource_type, 

5525 resource_id=resource_id) 

5526 elif source_project_id: 5526 ↛ 5527line 5526 didn't jump to line 5527 because the condition on line 5526 was never true

5527 transfer = db_utils.create_transfer( 

5528 resource_type=resource_type, 

5529 source_project_id=source_project_id) 

5530 else: 

5531 transfer = db_utils.create_transfer( 

5532 resource_type=resource_type) 

5533 return transfer['id'] 

5534 

5535 def test_transfer_create(self): 

5536 # If the resource_id is Null a KeyError exception will be raised. 

5537 self.assertRaises(KeyError, self._create_transfer) 

5538 

5539 share = db_utils.create_share(size=1, user_id=self.user_id, 

5540 project_id=self.project_id) 

5541 share_id = share['id'] 

5542 self._create_transfer(resource_id=share_id) 

5543 

5544 def test_transfer_get(self): 

5545 share_id = db_utils.create_share(size=1, user_id=self.user_id, 

5546 project_id=self.project_id)['id'] 

5547 transfer_id = self._create_transfer(resource_id=share_id) 

5548 

5549 transfer = db_api.transfer_get(self.ctxt, transfer_id) 

5550 self.assertEqual(share_id, transfer['resource_id']) 

5551 

5552 new_ctxt = context.RequestContext(user_id='new_user_id', 

5553 project_id='new_project_id') 

5554 self.assertRaises(exception.TransferNotFound, 

5555 db_api.transfer_get, new_ctxt, transfer_id) 

5556 

5557 transfer = db_api.transfer_get(new_ctxt.elevated(), transfer_id) 

5558 self.assertEqual(share_id, transfer['resource_id']) 

5559 

5560 def test_transfer_get_all(self): 

5561 share_id1 = db_utils.create_share(size=1, user_id=self.user_id, 

5562 project_id=self.project_id)['id'] 

5563 share_id2 = db_utils.create_share(size=1, user_id=self.user_id, 

5564 project_id=self.project_id)['id'] 

5565 self._create_transfer(resource_id=share_id1, 

5566 source_project_id=self.project_id) 

5567 self._create_transfer(resource_id=share_id2, 

5568 source_project_id=self.project_id) 

5569 

5570 self.assertRaises(exception.NotAuthorized, 

5571 db_api.transfer_get_all, 

5572 self.ctxt) 

5573 transfers = db_api.transfer_get_all(context.get_admin_context()) 

5574 self.assertEqual(2, len(transfers)) 

5575 

5576 transfers = db_api.transfer_get_all_by_project(self.ctxt, 

5577 self.project_id) 

5578 self.assertEqual(2, len(transfers)) 

5579 

5580 new_ctxt = context.RequestContext(user_id='new_user_id', 

5581 project_id='new_project_id') 

5582 transfers = db_api.transfer_get_all_by_project(new_ctxt, 

5583 'new_project_id') 

5584 self.assertEqual(0, len(transfers)) 

5585 

5586 def test_transfer_destroy(self): 

5587 share_id1 = db_utils.create_share(size=1, user_id=self.user_id, 

5588 project_id=self.project_id)['id'] 

5589 share_id2 = db_utils.create_share(size=1, user_id=self.user_id, 

5590 project_id=self.project_id)['id'] 

5591 transfer_id1 = self._create_transfer(resource_id=share_id1, 

5592 source_project_id=self.project_id) 

5593 transfer_id2 = self._create_transfer(resource_id=share_id2, 

5594 source_project_id=self.project_id) 

5595 

5596 transfers = db_api.transfer_get_all(context.get_admin_context()) 

5597 self.assertEqual(2, len(transfers)) 

5598 

5599 db_api.transfer_destroy(self.ctxt, transfer_id1) 

5600 transfers = db_api.transfer_get_all(context.get_admin_context()) 

5601 self.assertEqual(1, len(transfers)) 

5602 

5603 db_api.transfer_destroy(self.ctxt, transfer_id2) 

5604 transfers = db_api.transfer_get_all(context.get_admin_context()) 

5605 self.assertEqual(0, len(transfers)) 

5606 

5607 def test_transfer_accept_then_rollback(self): 

5608 share = db_utils.create_share(size=1, user_id=self.user_id, 

5609 project_id=self.project_id) 

5610 transfer_id = self._create_transfer(resource_id=share['id'], 

5611 source_project_id=self.project_id) 

5612 new_ctxt = context.RequestContext(user_id='new_user_id', 

5613 project_id='new_project_id') 

5614 

5615 transfer = db_api.transfer_get(new_ctxt.elevated(), transfer_id) 

5616 self.assertEqual(share['project_id'], transfer['source_project_id']) 

5617 self.assertFalse(transfer['accepted']) 

5618 self.assertIsNone(transfer['destination_project_id']) 

5619 # accept the transfer 

5620 db_api.transfer_accept(new_ctxt.elevated(), transfer_id, 

5621 'new_user_id', 'new_project_id') 

5622 

5623 admin_context = new_ctxt.elevated() 

5624 with db_api.context_manager.reader.using(admin_context): 

5625 transfer = db_api.model_query( 

5626 admin_context, models.Transfer, read_deleted='yes', 

5627 ).filter_by(id=transfer_id).first() 

5628 share = db_api.share_get(new_ctxt.elevated(), share['id']) 

5629 

5630 self.assertEqual(share['project_id'], 'new_project_id') 

5631 self.assertEqual(share['user_id'], 'new_user_id') 

5632 self.assertTrue(transfer['accepted']) 

5633 self.assertEqual('new_project_id', transfer['destination_project_id']) 

5634 

5635 # then test rollback the transfer 

5636 db_api.transfer_accept_rollback(new_ctxt.elevated(), transfer_id, 

5637 self.user_id, self.project_id) 

5638 with db_api.context_manager.reader.using(admin_context): 

5639 transfer = db_api.model_query( 

5640 admin_context, models.Transfer, 

5641 ).filter_by(id=transfer_id).first() 

5642 share = db_api.share_get(new_ctxt.elevated(), share['id']) 

5643 

5644 self.assertEqual(share['project_id'], self.project_id) 

5645 self.assertEqual(share['user_id'], self.user_id) 

5646 self.assertFalse(transfer['accepted']) 

5647 

5648 

5649class ShareBackupDatabaseAPITestCase(BaseDatabaseAPITestCase): 

5650 

5651 def setUp(self): 

5652 """Run before each test.""" 

5653 super(ShareBackupDatabaseAPITestCase, self).setUp() 

5654 self.ctxt = context.get_admin_context() 

5655 self.backup = { 

5656 'id': 'fake_backup_id', 

5657 'host': "fake_host", 

5658 'user_id': 'fake', 

5659 'project_id': 'fake', 

5660 'availability_zone': 'fake_availability_zone', 

5661 'status': constants.STATUS_CREATING, 

5662 'progress': '0', 

5663 'display_name': 'fake_name', 

5664 'display_description': 'fake_description', 

5665 'size': 1, 

5666 } 

5667 self.share_id = "fake_share_id" 

5668 

5669 def test_create_share_backup(self): 

5670 result = db_api.share_backup_create( 

5671 self.ctxt, self.share_id, self.backup) 

5672 self._check_fields(expected=self.backup, actual=result) 

5673 

5674 def test_get(self): 

5675 db_api.share_backup_create( 

5676 self.ctxt, self.share_id, self.backup) 

5677 result = db_api.share_backup_get( 

5678 self.ctxt, self.backup['id']) 

5679 self._check_fields(expected=self.backup, actual=result) 

5680 

5681 def test_delete(self): 

5682 db_api.share_backup_create( 

5683 self.ctxt, self.share_id, self.backup) 

5684 db_api.share_backup_delete(self.ctxt, 

5685 self.backup['id']) 

5686 

5687 self.assertRaises(exception.ShareBackupNotFound, 

5688 db_api.share_backup_get, 

5689 self.ctxt, 

5690 self.backup['id']) 

5691 

5692 def test_delete_not_found(self): 

5693 self.assertRaises(exception.ShareBackupNotFound, 

5694 db_api.share_backup_delete, 

5695 self.ctxt, 

5696 'fake not exist id') 

5697 

5698 def test_update(self): 

5699 new_status = constants.STATUS_ERROR 

5700 db_api.share_backup_create( 

5701 self.ctxt, self.share_id, self.backup) 

5702 result_update = db_api.share_backup_update( 

5703 self.ctxt, self.backup['id'], 

5704 {'status': constants.STATUS_ERROR}) 

5705 result_get = db_api.share_backup_get(self.ctxt, 

5706 self.backup['id']) 

5707 self.assertEqual(new_status, result_update['status']) 

5708 self._check_fields(expected=dict(result_update.items()), 

5709 actual=dict(result_get.items())) 

5710 

5711 def test_update_not_found(self): 

5712 self.assertRaises(exception.ShareBackupNotFound, 

5713 db_api.share_backup_update, 

5714 self.ctxt, 

5715 'fake id', 

5716 {}) 

5717 

5718 

5719class ResourceLocksTestCase(test.TestCase): 

5720 """Test case for resource locks.""" 

5721 

5722 def setUp(self): 

5723 super(ResourceLocksTestCase, self).setUp() 

5724 self.user_id = uuidutils.generate_uuid(dashed=False) 

5725 self.project_id = uuidutils.generate_uuid(dashed=False) 

5726 self.ctxt = context.RequestContext(user_id=self.user_id, 

5727 project_id=self.project_id) 

5728 

5729 def test_resource_lock_create(self): 

5730 lock_data = { 

5731 'resource_id': uuidutils.generate_uuid(), 

5732 'resource_type': 'share', 

5733 'resource_action': 'delete', 

5734 'lock_context': 'user', 

5735 'user_id': self.user_id, 

5736 'project_id': self.project_id, 

5737 'lock_reason': 'xyzzyspoon!', 

5738 } 

5739 lock = db_api.resource_lock_create(self.ctxt, lock_data) 

5740 

5741 self.assertTrue(uuidutils.is_uuid_like(lock['id'])) 

5742 self.assertEqual(lock_data['user_id'], lock['user_id']) 

5743 self.assertEqual(lock_data['project_id'], lock['project_id']) 

5744 self.assertIsNone(lock['updated_at']) 

5745 self.assertEqual('False', lock['deleted']) 

5746 

5747 def test_resource_lock_update_invalid(self): 

5748 self.assertRaises(exception.ResourceLockNotFound, 

5749 db_api.resource_lock_update, 

5750 self.ctxt, 

5751 'invalid-lock-id', 

5752 {'lock_reason': 'yadayada'}) 

5753 

5754 def test_resource_lock_update(self): 

5755 lock = db_utils.create_lock(project_id=self.project_id) 

5756 updated_lock = db_api.resource_lock_update( 

5757 self.ctxt, 

5758 lock['id'], 

5759 {'lock_reason': 'new reason'}, 

5760 ) 

5761 

5762 self.assertEqual(lock['id'], updated_lock['id']) 

5763 self.assertEqual('new reason', updated_lock['lock_reason']) 

5764 self.assertEqual(lock['user_id'], updated_lock['user_id']) 

5765 self.assertEqual(lock['project_id'], updated_lock['project_id']) 

5766 

5767 lock_get = db_api.resource_lock_get(self.ctxt, lock['id']) 

5768 

5769 self.assertEqual(lock['id'], lock_get['id']) 

5770 self.assertEqual('new reason', lock_get['lock_reason']) 

5771 self.assertEqual(lock['user_id'], lock_get['user_id']) 

5772 self.assertEqual(lock['project_id'], lock_get['project_id']) 

5773 

5774 def test_resource_lock_delete_invalid(self): 

5775 self.assertRaises(exception.ResourceLockNotFound, 

5776 db_api.resource_lock_delete, 

5777 self.ctxt, 

5778 'invalid-lock-id') 

5779 

5780 def test_resource_lock_delete(self): 

5781 lock = db_utils.create_lock(project_id=self.project_id) 

5782 lock_get = db_api.resource_lock_get(self.ctxt, lock['id']) 

5783 

5784 return_value = db_api.resource_lock_delete(self.ctxt, lock['id']) 

5785 

5786 self.assertIsNone(return_value) 

5787 with db_api.context_manager.reader.using(self.ctxt): 

5788 self.assertRaises(exception.ResourceLockNotFound, 

5789 db_api._resource_lock_get, 

5790 self.ctxt, 

5791 lock_get['id']) 

5792 

5793 def test_resource_lock_get_invalid(self): 

5794 self.assertRaises(exception.ResourceLockNotFound, 

5795 db_api.resource_lock_get, 

5796 self.ctxt, 

5797 'invalid-lock-id') 

5798 

5799 def test_resource_lock_get(self): 

5800 lock = db_utils.create_lock(project_id=self.project_id) 

5801 

5802 lock_get = db_api.resource_lock_get(self.ctxt, lock['id']) 

5803 

5804 self.assertEqual(lock['id'], lock_get['id']) 

5805 self.assertEqual('for the tests', lock_get['lock_reason']) 

5806 self.assertEqual(lock['user_id'], lock_get['user_id']) 

5807 self.assertEqual(lock['project_id'], lock_get['project_id']) 

5808 

5809 def test_resource_lock_get_all_basic_filters(self): 

5810 user_id_2 = uuidutils.generate_uuid(dashed=False) 

5811 project_id_2 = uuidutils.generate_uuid(dashed=False) 

5812 

5813 lk_1 = db_utils.create_lock(lock_reason='austin', 

5814 user_id=self.user_id, 

5815 project_id=self.project_id) 

5816 lk_2 = db_utils.create_lock(lock_reason='bexar', 

5817 user_id=self.user_id, 

5818 project_id=self.project_id) 

5819 lk_3 = db_utils.create_lock(lock_reason='cactus', 

5820 user_id=self.user_id, 

5821 project_id=self.project_id) 

5822 lk_4 = db_utils.create_lock(lock_reason='diablo', 

5823 user_id=user_id_2, 

5824 project_id=project_id_2) 

5825 lk_5 = db_utils.create_lock(lock_reason='essex') 

5826 

5827 project_locks_limited_offset, count = db_api.resource_lock_get_all( 

5828 self.ctxt, limit=2, offset=1, show_count=True) 

5829 self.assertEqual(2, len(project_locks_limited_offset)) 

5830 self.assertEqual(3, count) 

5831 order_expected = [lk_2['id'], lk_1['id']] 

5832 self.assertEqual(order_expected, 

5833 [lock['id'] for lock in project_locks_limited_offset]) 

5834 

5835 all_project_locks, count = db_api.resource_lock_get_all( 

5836 self.ctxt, filters={'all_projects': True}, sort_dir='asc') 

5837 self.assertEqual(5, len(all_project_locks)) 

5838 order_expected = [ 

5839 lk_1['id'], lk_2['id'], lk_3['id'], lk_4['id'], lk_5['id'] 

5840 ] 

5841 self.assertEqual(order_expected, 

5842 [lock['id'] for lock in all_project_locks]) 

5843 self.assertNotIn(lk_5['project_id'], [self.project_id, project_id_2]) 

5844 self.assertIsNone(count) 

5845 

5846 filtered_locks, count = db_api.resource_lock_get_all( 

5847 self.ctxt, filters={'lock_reason~': 'xar'}) 

5848 self.assertEqual(1, len(filtered_locks)) 

5849 self.assertIsNone(count) 

5850 self.assertEqual(lk_2['id'], filtered_locks[0]['id']) 

5851 

5852 def test_resource_locks_get_all_time_filters(self): 

5853 now = timeutils.utcnow() 

5854 lock_1 = db_utils.create_lock( 

5855 lock_reason='folsom', 

5856 project_id=self.project_id, 

5857 created_at=now - datetime.timedelta(seconds=1), 

5858 ) 

5859 lock_2 = db_utils.create_lock( 

5860 lock_reason='grizly', 

5861 project_id=self.project_id, 

5862 created_at=now + datetime.timedelta(seconds=1), 

5863 ) 

5864 lock_3 = db_utils.create_lock( 

5865 lock_reason='havana', 

5866 project_id=self.project_id, 

5867 created_at=now + datetime.timedelta(seconds=2), 

5868 ) 

5869 

5870 filters1 = {'created_before': now} 

5871 filters2 = {'created_since': now} 

5872 

5873 result1, count1 = db_api.resource_lock_get_all( 

5874 self.ctxt, filters=filters1) 

5875 result2, count2 = db_api.resource_lock_get_all( 

5876 self.ctxt, filters=filters2) 

5877 

5878 self.assertEqual(1, len(result1)) 

5879 self.assertEqual(lock_1['id'], result1[0]['id']) 

5880 self.assertEqual(2, len(result2)) 

5881 self.assertEqual([lock_3['id'], lock_2['id']], 

5882 [lock['id'] for lock in result2]) 

5883 self.assertIsNone(count1) 

5884 self.assertIsNone(count2) 

5885 

5886 filters1.update(filters2) 

5887 result3, count3 = db_api.resource_lock_get_all( 

5888 self.ctxt, filters=filters1, show_count=True) 

5889 self.assertEqual(0, len(result3)) 

5890 self.assertEqual(0, count3)