Coverage for manila/tests/api/v2/test_share_groups.py: 99%

492 statements  

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

1# Copyright 2015 Alex Meade 

2# All Rights Reserved. 

3# 

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

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

6# a copy of the License at 

7# 

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

9# 

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

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

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

13# License for the specific language governing permissions and limitations 

14# under the License. 

15 

16import copy 

17import datetime 

18from unittest import mock 

19 

20import ddt 

21from oslo_config import cfg 

22from oslo_serialization import jsonutils 

23from oslo_utils import uuidutils 

24import webob 

25 

26from manila.api.openstack import wsgi 

27import manila.api.v2.share_groups as share_groups 

28from manila.common import constants 

29from manila import context 

30from manila import db 

31from manila import exception 

32from manila import policy 

33from manila.share import share_types 

34from manila.share_group import api as share_group_api 

35from manila.share_group import share_group_types 

36from manila import test 

37from manila.tests.api import fakes 

38from manila.tests import db_utils 

39 

40 

41CONF = cfg.CONF 

42SG_GRADUATION_VERSION = '2.55' 

43 

44 

45@ddt.ddt 

46class ShareGroupAPITest(test.TestCase): 

47 """Consistency Groups API Test suite.""" 

48 

49 def setUp(self): 

50 super(ShareGroupAPITest, self).setUp() 

51 self.controller = share_groups.ShareGroupController() 

52 self.resource_name = self.controller.resource_name 

53 self.fake_share_type = {'id': uuidutils.generate_uuid()} 

54 self.fake_share_group_type = { 

55 'id': uuidutils.generate_uuid()} 

56 self.api_version = '2.34' 

57 self.request = fakes.HTTPRequest.blank( 

58 '/share-groups', version=self.api_version, experimental=True) 

59 self.flags(transport_url='rabbit://fake:fake@mqhost:5672') 

60 self.admin_context = context.RequestContext('admin', 'fake', True) 

61 self.member_context = context.RequestContext('fake', 'fake') 

62 self.mock_policy_check = self.mock_object( 

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

64 self.context = self.request.environ['manila.context'] 

65 self.mock_object(share_group_types, 'get_default', 

66 mock.Mock(return_value=self.fake_share_group_type)) 

67 self.mock_object(share_types, 'get_default_share_type', 

68 mock.Mock(return_value=self.fake_share_type)) 

69 

70 def _get_context(self, role): 

71 return getattr(self, '%s_context' % role) 

72 

73 def _setup_share_group_data(self, share_group=None, version='2.31'): 

74 if share_group is None: 74 ↛ 77line 74 didn't jump to line 77 because the condition on line 74 was always true

75 share_group = db_utils.create_share_group( 

76 status=constants.STATUS_AVAILABLE) 

77 path = '/v2/fake/share-groups/%s/action' % share_group['id'] 

78 req = fakes.HTTPRequest.blank(path, script_name=path, version=version) 

79 req.headers[wsgi.API_VERSION_REQUEST_HEADER] = version 

80 req.headers[wsgi.EXPERIMENTAL_API_REQUEST_HEADER] = 'True' 

81 

82 return share_group, req 

83 

84 def _get_fake_share_group(self, ctxt=None, **values): 

85 if ctxt is None: 

86 ctxt = self.context 

87 

88 share_group_db_dict = { 

89 'id': 'fake_id', 

90 'user_id': 'fakeuser', 

91 'project_id': 'fakeproject', 

92 'status': constants.STATUS_CREATING, 

93 'name': 'fake name', 

94 'description': 'fake description', 

95 'host': None, 

96 'availability_zone': None, 

97 'consistent_snapshot_support': None, 

98 'source_share_group_snapshot_id': None, 

99 'share_group_type_id': self.fake_share_group_type.get('id'), 

100 'share_network_id': uuidutils.generate_uuid(), 

101 'share_server_id': uuidutils.generate_uuid(), 

102 'share_types': [], 

103 'created_at': datetime.datetime(1, 1, 1, 1, 1, 1), 

104 } 

105 

106 share_group_db_dict.update(**values) 

107 

108 expected_share_group = { 

109 'id': share_group_db_dict['id'], 

110 'project_id': share_group_db_dict['project_id'], 

111 'status': share_group_db_dict['status'], 

112 'name': share_group_db_dict['name'], 

113 'description': share_group_db_dict['description'], 

114 'host': share_group_db_dict['host'], 

115 'availability_zone': share_group_db_dict['availability_zone'], 

116 'consistent_snapshot_support': share_group_db_dict[ 

117 'consistent_snapshot_support'], 

118 'source_share_group_snapshot_id': share_group_db_dict[ 

119 'source_share_group_snapshot_id'], 

120 'share_group_type_id': share_group_db_dict['share_group_type_id'], 

121 'share_network_id': share_group_db_dict['share_network_id'], 

122 'share_server_id': share_group_db_dict['share_server_id'], 

123 'share_types': [st['share_type_id'] 

124 for st in share_group_db_dict.get('share_types')], 

125 'created_at': datetime.datetime(1, 1, 1, 1, 1, 1), 

126 'links': mock.ANY, 

127 } 

128 if not ctxt.is_admin: 

129 del expected_share_group['share_server_id'] 

130 

131 return share_group_db_dict, expected_share_group 

132 

133 def _get_fake_simple_share_group(self, **values): 

134 share_group = {'id': 'fake_id', 'name': None} 

135 share_group.update(**values) 

136 expected_share_group = copy.deepcopy(share_group) 

137 expected_share_group['links'] = mock.ANY 

138 return share_group, expected_share_group 

139 

140 def _get_fake_custom_request_and_context(self, microversion, experimental): 

141 req = fakes.HTTPRequest.blank( 

142 '/share-groups', version=microversion, experimental=experimental) 

143 req_context = req.environ['manila.context'] 

144 return req, req_context 

145 

146 @ddt.data({'microversion': '2.34', 'experimental': True}, 

147 {'microversion': SG_GRADUATION_VERSION, 'experimental': False}) 

148 @ddt.unpack 

149 def test_share_group_create(self, microversion, experimental): 

150 fake, expected = self._get_fake_share_group() 

151 self.mock_object(share_types, 'get_default_share_type', 

152 mock.Mock(return_value=self.fake_share_type)) 

153 self.mock_object(self.controller.share_group_api, 'create', 

154 mock.Mock(return_value=fake)) 

155 req, req_context = self._get_fake_custom_request_and_context( 

156 microversion, experimental) 

157 body = {"share_group": {}} 

158 

159 res_dict = self.controller.create(req, body) 

160 

161 self.controller.share_group_api.create.assert_called_once_with( 

162 req_context, share_group_type_id=self.fake_share_group_type['id'], 

163 share_type_ids=[self.fake_share_type['id']]) 

164 self.assertEqual(expected, res_dict['share_group']) 

165 self.mock_policy_check.assert_called_once_with( 

166 req_context, self.resource_name, 'create') 

167 

168 def test_group_create_invalid_group_snapshot_state(self): 

169 fake_snap_id = uuidutils.generate_uuid() 

170 self.mock_object( 

171 self.controller.share_group_api, 'create', 

172 mock.Mock(side_effect=exception.InvalidShareGroupSnapshot( 

173 reason='bad status', 

174 ))) 

175 body = { 

176 "share_group": { 

177 "source_share_group_snapshot_id": fake_snap_id 

178 } 

179 } 

180 

181 self.assertRaises(webob.exc.HTTPConflict, 

182 self.controller.create, self.request, body) 

183 

184 self.mock_policy_check.assert_called_once_with( 

185 self.context, self.resource_name, 'create') 

186 

187 def test_share_group_create_no_default_share_type(self): 

188 fake_group, expected_group = self._get_fake_share_group() 

189 self.mock_object(share_types, 'get_default_share_type', 

190 mock.Mock(return_value=None)) 

191 self.mock_object(self.controller.share_group_api, 'create', 

192 mock.Mock(return_value=fake_group)) 

193 body = {"share_group": {}} 

194 

195 self.assertRaises( 

196 webob.exc.HTTPBadRequest, 

197 self.controller.create, self.request, body) 

198 

199 self.mock_policy_check.assert_called_once_with( 

200 self.context, self.resource_name, 'create') 

201 

202 def test_share_group_create_no_default_group_type(self): 

203 fake_group, expected_group = self._get_fake_share_group() 

204 self.mock_object( 

205 share_group_types, 'get_default', mock.Mock(return_value=None)) 

206 self.mock_object( 

207 self.controller.share_group_api, 'create', 

208 mock.Mock(return_value=fake_group)) 

209 body = {"share_group": {}} 

210 

211 self.assertRaises( 

212 webob.exc.HTTPBadRequest, 

213 self.controller.create, self.request, body) 

214 

215 self.mock_policy_check.assert_called_once_with( 

216 self.context, self.resource_name, 'create') 

217 

218 def test_share_group_create_with_group_type_specified(self): 

219 fake_share_group, expected_group = self._get_fake_share_group() 

220 self.mock_object( 

221 share_group_types, 'get_default', mock.Mock(return_value=None)) 

222 self.mock_object( 

223 self.controller.share_group_api, 'create', 

224 mock.Mock(return_value=fake_share_group)) 

225 body = { 

226 "share_group": { 

227 "share_group_type_id": self.fake_share_group_type.get('id'), 

228 } 

229 } 

230 

231 self.controller.create(self.request, body) 

232 

233 self.controller.share_group_api.create.assert_called_once_with( 

234 self.context, 

235 share_group_type_id=self.fake_share_group_type['id'], 

236 share_type_ids=[self.fake_share_type['id']]) 

237 self.mock_policy_check.assert_called_once_with( 

238 self.context, self.resource_name, 'create') 

239 

240 def test_share_group_create_with_invalid_group_type_specified(self): 

241 fake_share_group, expected_share_group = self._get_fake_share_group() 

242 self.mock_object( 

243 share_group_types, 'get_default', mock.Mock(return_value=None)) 

244 self.mock_object(self.controller.share_group_api, 'create', 

245 mock.Mock(return_value=fake_share_group)) 

246 body = {"share_group": {"group_type_id": "invalid"}} 

247 

248 self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, 

249 self.request, body) 

250 

251 self.mock_policy_check.assert_called_once_with( 

252 self.context, self.resource_name, 'create') 

253 

254 def test_share_group_create_with_az(self): 

255 fake_az_name = 'fake_az_name' 

256 fake_az_id = 'fake_az_id' 

257 fake_share_group, expected_share_group = self._get_fake_share_group( 

258 availability_zone_id=fake_az_id) 

259 self.mock_object( 

260 self.controller.share_group_api, 'create', 

261 mock.Mock(return_value=fake_share_group)) 

262 self.mock_object( 

263 share_groups.db, 'availability_zone_get', 

264 mock.Mock(return_value=type( 

265 'FakeAZ', (object, ), { 

266 'id': fake_az_id, 

267 'name': fake_az_name, 

268 }))) 

269 

270 body = {"share_group": {"availability_zone": fake_az_name}} 

271 

272 res_dict = self.controller.create(self.request, body) 

273 

274 self.controller.share_group_api.create.assert_called_once_with( 

275 self.context, availability_zone_id=fake_az_id, 

276 availability_zone=fake_az_name, 

277 share_group_type_id=self.fake_share_group_type['id'], 

278 share_type_ids=[self.fake_share_type['id']]) 

279 share_groups.db.availability_zone_get.assert_called_once_with( 

280 self.context, fake_az_name) 

281 self.assertEqual(expected_share_group, res_dict['share_group']) 

282 self.mock_policy_check.assert_called_once_with( 

283 self.context, self.resource_name, 'create') 

284 

285 def test_share_group_create_with_az_and_source_share_group_snapshot(self): 

286 fake_az_name = 'fake_az_name' 

287 fake_az_id = 'fake_az_id' 

288 fake_share_group, expected_share_group = self._get_fake_share_group( 

289 availability_zone_id=fake_az_id) 

290 self.mock_object( 

291 self.controller.share_group_api, 'create', 

292 mock.Mock(return_value=fake_share_group)) 

293 self.mock_object( 

294 share_groups.db, 'availability_zone_get', 

295 mock.Mock(return_value=type( 

296 'FakeAZ', (object, ), { 

297 'id': fake_az_id, 

298 'name': fake_az_name, 

299 }))) 

300 

301 body = {"share_group": { 

302 "availability_zone": fake_az_name, 

303 "source_share_group_snapshot_id": 'fake_sgs_id', 

304 }} 

305 

306 self.assertRaises( 

307 webob.exc.HTTPBadRequest, 

308 self.controller.create, 

309 self.request, body) 

310 

311 self.controller.share_group_api.create.assert_not_called() 

312 share_groups.db.availability_zone_get.assert_not_called() 

313 self.mock_policy_check.assert_called_once_with( 

314 self.context, self.resource_name, 'create') 

315 

316 def test_share_group_create_with_nonexistent_az(self): 

317 fake_az_name = 'fake_az_name' 

318 fake_az_id = 'fake_az_id' 

319 fake_share_group, expected_share_group = self._get_fake_share_group( 

320 availability_zone_id=fake_az_id) 

321 self.mock_object( 

322 self.controller.share_group_api, 'create', 

323 mock.Mock(return_value=fake_share_group)) 

324 self.mock_object( 

325 share_groups.db, 'availability_zone_get', 

326 mock.Mock( 

327 side_effect=exception.AvailabilityZoneNotFound(id=fake_az_id))) 

328 

329 body = {"share_group": {"availability_zone": fake_az_name}} 

330 

331 self.assertRaises( 

332 webob.exc.HTTPNotFound, 

333 self.controller.create, self.request, body) 

334 

335 self.assertEqual(0, self.controller.share_group_api.create.call_count) 

336 share_groups.db.availability_zone_get.assert_called_once_with( 

337 self.context, fake_az_name) 

338 self.mock_policy_check.assert_called_once_with( 

339 self.context, self.resource_name, 'create') 

340 

341 def test_share_group_create_with_name(self): 

342 fake_name = 'fake_name' 

343 fake_share_group, expected_share_group = self._get_fake_share_group( 

344 name=fake_name) 

345 self.mock_object(self.controller.share_group_api, 'create', 

346 mock.Mock(return_value=fake_share_group)) 

347 body = {"share_group": {"name": fake_name}} 

348 

349 res_dict = self.controller.create(self.request, body) 

350 

351 self.controller.share_group_api.create.assert_called_once_with( 

352 self.context, name=fake_name, 

353 share_group_type_id=self.fake_share_group_type['id'], 

354 share_type_ids=[self.fake_share_type['id']]) 

355 self.assertEqual(expected_share_group, res_dict['share_group']) 

356 self.mock_policy_check.assert_called_once_with( 

357 self.context, self.resource_name, 'create') 

358 

359 def test_share_group_create_with_description(self): 

360 fake_description = 'fake_description' 

361 fake_share_group, expected_share_group = self._get_fake_share_group( 

362 description=fake_description) 

363 self.mock_object(share_types, 'get_default_share_type', 

364 mock.Mock(return_value=self.fake_share_type)) 

365 self.mock_object(self.controller.share_group_api, 'create', 

366 mock.Mock(return_value=fake_share_group)) 

367 body = {"share_group": {"description": fake_description}} 

368 

369 res_dict = self.controller.create(self.request, body) 

370 

371 self.controller.share_group_api.create.assert_called_once_with( 

372 self.context, description=fake_description, 

373 share_group_type_id=self.fake_share_group_type['id'], 

374 share_type_ids=[self.fake_share_type['id']]) 

375 self.assertEqual(expected_share_group, res_dict['share_group']) 

376 self.mock_policy_check.assert_called_once_with( 

377 self.context, self.resource_name, 'create') 

378 

379 def test_share_group_create_with_share_types(self): 

380 fake_share_types = [{"share_type_id": self.fake_share_type['id']}] 

381 fake_group, expected_group = self._get_fake_share_group( 

382 share_types=fake_share_types) 

383 self.mock_object(self.controller.share_group_api, 'create', 

384 mock.Mock(return_value=fake_group)) 

385 body = { 

386 "share_group": { 

387 "share_types": [self.fake_share_type['id']] 

388 } 

389 } 

390 

391 res_dict = self.controller.create(self.request, body) 

392 

393 self.controller.share_group_api.create.assert_called_once_with( 

394 self.context, share_group_type_id=self.fake_share_group_type['id'], 

395 share_type_ids=[self.fake_share_type['id']]) 

396 self.assertEqual(expected_group, res_dict['share_group']) 

397 self.mock_policy_check.assert_called_once_with( 

398 self.context, self.resource_name, 'create') 

399 

400 def test_sg_create_with_source_sg_snapshot_id_and_share_network(self): 

401 fake_snap_id = uuidutils.generate_uuid() 

402 fake_net_id = uuidutils.generate_uuid() 

403 self.mock_object(share_types, 'get_default_share_type', 

404 mock.Mock(return_value=self.fake_share_type)) 

405 mock_api_call = self.mock_object( 

406 self.controller.share_group_api, 'create') 

407 body = { 

408 "share_group": { 

409 "source_share_group_snapshot_id": fake_snap_id, 

410 "share_network_id": fake_net_id, 

411 } 

412 } 

413 

414 self.assertRaises(webob.exc.HTTPBadRequest, 

415 self.controller.create, 

416 self.request, body) 

417 

418 self.assertFalse(mock_api_call.called) 

419 self.mock_policy_check.assert_called_once_with( 

420 self.context, self.resource_name, 'create') 

421 

422 def test_share_group_create_with_source_sg_snapshot_id(self): 

423 fake_snap_id = uuidutils.generate_uuid() 

424 fake_share_group, expected_group = self._get_fake_share_group( 

425 source_share_group_snapshot_id=fake_snap_id) 

426 self.mock_object(share_types, 'get_default_share_type', 

427 mock.Mock(return_value=self.fake_share_type)) 

428 self.mock_object(self.controller.share_group_api, 'create', 

429 mock.Mock(return_value=fake_share_group)) 

430 

431 body = { 

432 "share_group": { 

433 "source_share_group_snapshot_id": fake_snap_id, 

434 } 

435 } 

436 

437 res_dict = self.controller.create(self.request, body) 

438 

439 self.controller.share_group_api.create.assert_called_once_with( 

440 self.context, share_group_type_id=self.fake_share_group_type['id'], 

441 source_share_group_snapshot_id=fake_snap_id) 

442 self.assertEqual(expected_group, res_dict['share_group']) 

443 self.mock_policy_check.assert_called_once_with( 

444 self.context, self.resource_name, 'create') 

445 

446 def test_share_group_create_with_share_network_id(self): 

447 fake_net_id = uuidutils.generate_uuid() 

448 fake_group, expected_group = self._get_fake_share_group( 

449 share_network_id=fake_net_id) 

450 

451 self.mock_object(share_types, 'get_default_share_type', 

452 mock.Mock(return_value=self.fake_share_type)) 

453 self.mock_object(self.controller.share_group_api, 'create', 

454 mock.Mock(return_value=fake_group)) 

455 body = { 

456 "share_group": { 

457 "share_network_id": fake_net_id, 

458 } 

459 } 

460 

461 res_dict = self.controller.create(self.request, body) 

462 

463 self.controller.share_group_api.create.assert_called_once_with( 

464 self.context, share_network_id=fake_net_id, 

465 share_group_type_id=self.fake_share_group_type['id'], 

466 share_type_ids=mock.ANY) 

467 self.assertEqual(expected_group, res_dict['share_group']) 

468 self.mock_policy_check.assert_called_once_with( 

469 self.context, self.resource_name, 'create') 

470 

471 def test_sg_create_no_default_share_type_with_share_group_snapshot(self): 

472 fake_snap_id = uuidutils.generate_uuid() 

473 fake, expected = self._get_fake_share_group() 

474 self.mock_object(share_types, 'get_default_share_type', 

475 mock.Mock(return_value=None)) 

476 self.mock_object(self.controller.share_group_api, 'create', 

477 mock.Mock(return_value=fake)) 

478 body = { 

479 "share_group": { 

480 "source_share_group_snapshot_id": fake_snap_id, 

481 } 

482 } 

483 

484 res_dict = self.controller.create(self.request, body) 

485 

486 self.controller.share_group_api.create.assert_called_once_with( 

487 self.context, share_group_type_id=self.fake_share_group_type['id'], 

488 source_share_group_snapshot_id=fake_snap_id) 

489 self.assertEqual(expected, res_dict['share_group']) 

490 self.mock_policy_check.assert_called_once_with( 

491 self.context, self.resource_name, 'create') 

492 

493 def test_share_group_create_with_name_and_description(self): 

494 fake_name = 'fake_name' 

495 fake_description = 'fake_description' 

496 fake_group, expected_group = self._get_fake_share_group( 

497 name=fake_name, description=fake_description) 

498 self.mock_object(share_types, 'get_default_share_type', 

499 mock.Mock(return_value=self.fake_share_type)) 

500 self.mock_object(self.controller.share_group_api, 'create', 

501 mock.Mock(return_value=fake_group)) 

502 body = { 

503 "share_group": { 

504 "name": fake_name, 

505 "description": fake_description 

506 } 

507 } 

508 

509 res_dict = self.controller.create(self.request, body) 

510 

511 self.controller.share_group_api.create.assert_called_once_with( 

512 self.context, name=fake_name, description=fake_description, 

513 share_group_type_id=self.fake_share_group_type['id'], 

514 share_type_ids=[self.fake_share_type['id']]) 

515 self.assertEqual(expected_group, res_dict['share_group']) 

516 self.mock_policy_check.assert_called_once_with( 

517 self.context, self.resource_name, 'create') 

518 

519 def test_share_group_create_invalid_body(self): 

520 body = {"not_group": {}} 

521 

522 self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, 

523 self.request, body) 

524 

525 self.mock_policy_check.assert_called_once_with( 

526 self.context, self.resource_name, 'create') 

527 

528 def test_group_create_invalid_body_share_types_and_source_group_snapshot( 

529 self): 

530 body = { 

531 "share_group": { 

532 "share_types": [], 

533 "source_share_group_snapshot_id": "", 

534 } 

535 } 

536 self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, 

537 self.request, body) 

538 self.mock_policy_check.assert_called_once_with( 

539 self.context, self.resource_name, 'create') 

540 

541 def test_share_group_create_source_group_snapshot_not_in_available(self): 

542 fake_snap_id = uuidutils.generate_uuid() 

543 body = { 

544 "share_group": { 

545 "source_share_group_snapshot_id": fake_snap_id, 

546 } 

547 } 

548 self.mock_object(self.controller.share_group_api, 'create', mock.Mock( 

549 side_effect=exception.InvalidShareGroupSnapshot(reason='blah'))) 

550 

551 self.assertRaises( 

552 webob.exc.HTTPConflict, self.controller.create, self.request, body) 

553 

554 self.mock_policy_check.assert_called_once_with( 

555 self.context, self.resource_name, 'create') 

556 

557 def test_share_group_create_source_group_snapshot_does_not_exist(self): 

558 fake_snap_id = uuidutils.generate_uuid() 

559 body = { 

560 "share_group": {"source_share_group_snapshot_id": fake_snap_id} 

561 } 

562 self.mock_object( 

563 self.controller.share_group_api, 'create', 

564 mock.Mock(side_effect=exception.ShareGroupSnapshotNotFound( 

565 share_group_snapshot_id=fake_snap_id))) 

566 

567 self.assertRaises( 

568 webob.exc.HTTPBadRequest, 

569 self.controller.create, self.request, body) 

570 

571 self.mock_policy_check.assert_called_once_with( 

572 self.context, self.resource_name, 'create') 

573 

574 def test_share_group_create_invalid_input(self): 

575 fake_snap_id = uuidutils.generate_uuid() 

576 body = { 

577 "share_group": {"source_share_group_snapshot_id": fake_snap_id} 

578 } 

579 self.mock_object( 

580 self.controller.share_group_api, 'create', 

581 mock.Mock(side_effect=exception.InvalidInput( 

582 reason='invalid input'))) 

583 

584 self.assertRaises( 

585 webob.exc.HTTPBadRequest, 

586 self.controller.create, self.request, body) 

587 

588 self.mock_policy_check.assert_called_once_with( 

589 self.context, self.resource_name, 'create') 

590 

591 def test_share_group_create_source_group_snapshot_not_a_uuid(self): 

592 fake_snap_id = "Not a uuid" 

593 body = { 

594 "share_group": { 

595 "source_share_group_snapshot_id": fake_snap_id, 

596 } 

597 } 

598 

599 self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, 

600 self.request, body) 

601 

602 self.mock_policy_check.assert_called_once_with( 

603 self.context, self.resource_name, 'create') 

604 

605 def test_share_group_create_share_network_id_not_a_uuid(self): 

606 fake_net_id = "Not a uuid" 

607 body = {"share_group": {"share_network_id": fake_net_id}} 

608 

609 self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, 

610 self.request, body) 

611 

612 self.mock_policy_check.assert_called_once_with( 

613 self.context, self.resource_name, 'create') 

614 

615 def test_share_group_create_invalid_body_share_types_not_a_list(self): 

616 body = {"share_group": {"share_types": ""}} 

617 

618 self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, 

619 self.request, body) 

620 

621 self.mock_policy_check.assert_called_once_with( 

622 self.context, self.resource_name, 'create') 

623 

624 def test_share_group_create_invalid_body_invalid_field(self): 

625 body = {"share_group": {"unknown_field": ""}} 

626 

627 exc = self.assertRaises(webob.exc.HTTPBadRequest, 

628 self.controller.create, 

629 self.request, body) 

630 

631 self.assertIn('unknown_field', str(exc)) 

632 self.mock_policy_check.assert_called_once_with( 

633 self.context, self.resource_name, 'create') 

634 

635 def test_share_group_create_with_invalid_share_types_field(self): 

636 body = {"share_group": {"share_types": 'iamastring'}} 

637 

638 self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, 

639 self.request, body) 

640 

641 self.mock_policy_check.assert_called_once_with( 

642 self.context, self.resource_name, 'create') 

643 

644 def test_share_group_create_with_invalid_share_types_field_not_uuids(self): 

645 body = {"share_group": {"share_types": ['iamastring']}} 

646 

647 self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, 

648 self.request, body) 

649 

650 self.mock_policy_check.assert_called_once_with( 

651 self.context, self.resource_name, 'create') 

652 

653 @ddt.data({'microversion': '2.34', 'experimental': True}, 

654 {'microversion': SG_GRADUATION_VERSION, 'experimental': False}) 

655 @ddt.unpack 

656 def test_share_group_update_with_name_and_description( 

657 self, microversion, experimental): 

658 fake_name = 'fake_name' 

659 fake_description = 'fake_description' 

660 fake_group, expected_group = self._get_fake_share_group( 

661 name=fake_name, description=fake_description) 

662 self.mock_object(self.controller.share_group_api, 'get', 

663 mock.Mock(return_value=fake_group)) 

664 self.mock_object(self.controller.share_group_api, 'update', 

665 mock.Mock(return_value=fake_group)) 

666 req, req_context = self._get_fake_custom_request_and_context( 

667 microversion, experimental) 

668 body = { 

669 "share_group": { 

670 "name": fake_name, 

671 "description": fake_description, 

672 } 

673 } 

674 

675 res_dict = self.controller.update(req, fake_group['id'], body) 

676 

677 self.controller.share_group_api.update.assert_called_once_with( 

678 req_context, fake_group, 

679 {"name": fake_name, "description": fake_description}) 

680 self.assertEqual(expected_group, res_dict['share_group']) 

681 self.mock_policy_check.assert_called_once_with( 

682 req_context, self.resource_name, 'update') 

683 

684 def test_share_group_update_group_not_found(self): 

685 body = {"share_group": {}} 

686 self.mock_object(self.controller.share_group_api, 'get', 

687 mock.Mock(side_effect=exception.NotFound)) 

688 

689 self.assertRaises(webob.exc.HTTPNotFound, 

690 self.controller.update, 

691 self.request, 'fake_id', body) 

692 

693 self.mock_policy_check.assert_called_once_with( 

694 self.context, self.resource_name, 'update') 

695 

696 def test_share_group_update_invalid_body(self): 

697 body = {"not_group": {}} 

698 

699 self.assertRaises(webob.exc.HTTPBadRequest, 

700 self.controller.update, 

701 self.request, 'fake_id', body) 

702 

703 self.mock_policy_check.assert_called_once_with( 

704 self.context, self.resource_name, 'update') 

705 

706 def test_share_group_update_invalid_body_invalid_field(self): 

707 body = {"share_group": {"unknown_field": ""}} 

708 

709 exc = self.assertRaises(webob.exc.HTTPBadRequest, 

710 self.controller.update, 

711 self.request, 'fake_id', body) 

712 

713 self.assertIn('unknown_field', str(exc)) 

714 self.mock_policy_check.assert_called_once_with( 

715 self.context, self.resource_name, 'update') 

716 

717 def test_share_group_update_invalid_body_readonly_field(self): 

718 body = {"share_group": {"share_types": []}} 

719 

720 exc = self.assertRaises(webob.exc.HTTPBadRequest, 

721 self.controller.update, 

722 self.request, 'fake_id', body) 

723 

724 self.assertIn('share_types', str(exc)) 

725 self.mock_policy_check.assert_called_once_with( 

726 self.context, self.resource_name, 'update') 

727 

728 @ddt.data({'microversion': '2.31', 'experimental': True}, 

729 {'microversion': SG_GRADUATION_VERSION, 'experimental': False}) 

730 @ddt.unpack 

731 def test_share_group_list_index(self, microversion, experimental): 

732 fake, expected = self._get_fake_simple_share_group() 

733 self.mock_object( 

734 share_group_api.API, 'get_all', mock.Mock(return_value=[fake])) 

735 req, req_context = self._get_fake_custom_request_and_context( 

736 microversion, experimental) 

737 

738 res_dict = self.controller.index(req) 

739 

740 self.assertEqual([expected], res_dict['share_groups']) 

741 self.mock_policy_check.assert_called_once_with( 

742 req_context, self.resource_name, 'get_all') 

743 

744 def test_share_group_list_index_no_groups(self): 

745 self.mock_object( 

746 share_group_api.API, 'get_all', mock.Mock(return_value=[])) 

747 

748 res_dict = self.controller.index(self.request) 

749 

750 self.assertEqual([], res_dict['share_groups']) 

751 self.mock_policy_check.assert_called_once_with( 

752 self.context, self.resource_name, 'get_all') 

753 

754 def test_share_group_list_index_with_limit(self): 

755 fake, expected = self._get_fake_simple_share_group() 

756 fake2, expected2 = self._get_fake_simple_share_group(id="fake_id2") 

757 self.mock_object( 

758 share_group_api.API, 'get_all', 

759 mock.Mock(return_value=[fake, fake2])) 

760 req = fakes.HTTPRequest.blank( 

761 '/share-groups?limit=1', version=self.api_version, 

762 experimental=True) 

763 req_context = req.environ['manila.context'] 

764 

765 res_dict = self.controller.index(req) 

766 

767 self.assertEqual(1, len(res_dict['share_groups'])) 

768 self.assertEqual([expected], res_dict['share_groups']) 

769 self.mock_policy_check.assert_called_once_with( 

770 req_context, self.resource_name, 'get_all') 

771 

772 def test_share_group_list_index_with_limit_and_offset(self): 

773 fake, expected = self._get_fake_simple_share_group() 

774 fake2, expected2 = self._get_fake_simple_share_group( 

775 id="fake_id2") 

776 self.mock_object(share_group_api.API, 'get_all', 

777 mock.Mock(return_value=[fake, fake2])) 

778 req = fakes.HTTPRequest.blank( 

779 '/share-groups?limit=1&offset=1', version=self.api_version, 

780 experimental=True) 

781 req_context = req.environ['manila.context'] 

782 

783 res_dict = self.controller.index(req) 

784 

785 self.assertEqual(1, len(res_dict['share_groups'])) 

786 self.assertEqual([expected2], res_dict['share_groups']) 

787 self.mock_policy_check.assert_called_once_with( 

788 req_context, self.resource_name, 'get_all') 

789 

790 def test_share_group_list_index_with_like_filter(self): 

791 fake, expected = self._get_fake_simple_share_group( 

792 name='fake_1', description='fake_ds_1') 

793 fake2, expected2 = self._get_fake_simple_share_group( 

794 name='fake_2', description='fake_ds_2') 

795 self.mock_object(share_group_api.API, 'get_all', 

796 mock.Mock(return_value=[fake, fake2])) 

797 req = fakes.HTTPRequest.blank( 

798 '/share-groups?name~=fake&description~=fake', 

799 version='2.36', experimental=True) 

800 req_context = req.environ['manila.context'] 

801 

802 res_dict = self.controller.index(req) 

803 

804 expected.pop('description') 

805 expected2.pop('description') 

806 self.assertEqual(2, len(res_dict['share_groups'])) 

807 self.assertEqual([expected, expected2], res_dict['share_groups']) 

808 self.mock_policy_check.assert_called_once_with( 

809 req_context, self.resource_name, 'get_all') 

810 

811 @ddt.data({'microversion': '2.34', 'experimental': True}, 

812 {'microversion': SG_GRADUATION_VERSION, 'experimental': False}) 

813 @ddt.unpack 

814 def test_share_group_list_detail(self, microversion, experimental): 

815 fake, expected = self._get_fake_share_group() 

816 self.mock_object( 

817 share_group_api.API, 'get_all', mock.Mock(return_value=[fake])) 

818 req, req_context = self._get_fake_custom_request_and_context( 

819 microversion, experimental) 

820 

821 res_dict = self.controller.detail(req) 

822 

823 self.assertEqual([expected], res_dict['share_groups']) 

824 self.mock_policy_check.assert_called_once_with( 

825 req_context, self.resource_name, 'get_all') 

826 

827 def test_share_group_list_detail_no_groups(self): 

828 self.mock_object( 

829 share_group_api.API, 'get_all', mock.Mock(return_value=[])) 

830 

831 res_dict = self.controller.detail(self.request) 

832 

833 self.assertEqual([], res_dict['share_groups']) 

834 self.mock_policy_check.assert_called_once_with( 

835 self.context, self.resource_name, 'get_all') 

836 

837 def test_share_group_list_detail_with_limit(self): 

838 req = fakes.HTTPRequest.blank('/share-groups?limit=1', 

839 version=self.api_version, 

840 experimental=True) 

841 req_context = req.environ['manila.context'] 

842 fake_group, expected_group = self._get_fake_share_group( 

843 ctxt=req_context) 

844 fake_group2, expected_group2 = self._get_fake_share_group( 

845 ctxt=req_context, id="fake_id2") 

846 self.mock_object(share_group_api.API, 'get_all', 

847 mock.Mock(return_value=[fake_group, fake_group2])) 

848 

849 res_dict = self.controller.detail(req) 

850 

851 self.assertEqual(1, len(res_dict['share_groups'])) 

852 self.assertEqual([expected_group], res_dict['share_groups']) 

853 self.mock_policy_check.assert_called_once_with( 

854 req_context, self.resource_name, 'get_all') 

855 

856 def test_share_group_list_detail_with_limit_and_offset(self): 

857 req = fakes.HTTPRequest.blank('/share-groups?limit=1&offset=1', 

858 version=self.api_version, 

859 experimental=True) 

860 req_context = req.environ['manila.context'] 

861 fake_group, expected_group = self._get_fake_share_group( 

862 ctxt=req_context) 

863 fake_group2, expected_group2 = self._get_fake_share_group( 

864 id="fake_id2", ctxt=req_context) 

865 self.mock_object(share_group_api.API, 'get_all', 

866 mock.Mock(return_value=[fake_group, fake_group2])) 

867 

868 res_dict = self.controller.detail(req) 

869 

870 self.assertEqual(1, len(res_dict['share_groups'])) 

871 self.assertEqual([expected_group2], res_dict['share_groups']) 

872 self.mock_policy_check.assert_called_once_with( 

873 req_context, self.resource_name, 'get_all') 

874 

875 @ddt.data({'microversion': '2.31', 'experimental': True}, 

876 {'microversion': SG_GRADUATION_VERSION, 'experimental': False}) 

877 @ddt.unpack 

878 def test_share_group_delete(self, microversion, experimental): 

879 fake_group, expected_group = self._get_fake_share_group() 

880 self.mock_object(share_group_api.API, 'get', 

881 mock.Mock(return_value=fake_group)) 

882 self.mock_object(share_group_api.API, 'delete') 

883 req, req_context = self._get_fake_custom_request_and_context( 

884 microversion, experimental) 

885 

886 res = self.controller.delete(req, fake_group['id']) 

887 

888 self.assertEqual(202, res.status_code) 

889 self.mock_policy_check.assert_called_once_with( 

890 req_context, self.resource_name, 'delete') 

891 

892 def test_share_group_delete_group_not_found(self): 

893 fake_group, expected_group = self._get_fake_share_group() 

894 self.mock_object(share_group_api.API, 'get', 

895 mock.Mock(side_effect=exception.NotFound)) 

896 

897 self.assertRaises(webob.exc.HTTPNotFound, self.controller.delete, 

898 self.request, fake_group['id']) 

899 self.mock_policy_check.assert_called_once_with( 

900 self.context, self.resource_name, 'delete') 

901 

902 def test_share_group_delete_in_conflicting_status(self): 

903 fake, expected = self._get_fake_share_group() 

904 self.mock_object( 

905 share_group_api.API, 'get', mock.Mock(return_value=fake)) 

906 self.mock_object(share_group_api.API, 'delete', mock.Mock( 

907 side_effect=exception.InvalidShareGroup(reason='blah'))) 

908 

909 self.assertRaises( 

910 webob.exc.HTTPConflict, 

911 self.controller.delete, self.request, fake['id']) 

912 

913 self.mock_policy_check.assert_called_once_with( 

914 self.context, self.resource_name, 'delete') 

915 

916 @ddt.data({'microversion': '2.34', 'experimental': True}, 

917 {'microversion': SG_GRADUATION_VERSION, 'experimental': False}) 

918 @ddt.unpack 

919 def test_share_group_show(self, microversion, experimental): 

920 fake, expected = self._get_fake_share_group() 

921 self.mock_object( 

922 share_group_api.API, 'get', mock.Mock(return_value=fake)) 

923 req = fakes.HTTPRequest.blank( 

924 '/share-groupss/%s' % fake['id'], version=microversion, 

925 experimental=experimental) 

926 req_context = req.environ['manila.context'] 

927 

928 res_dict = self.controller.show(req, fake['id']) 

929 

930 self.assertEqual(expected, res_dict['share_group']) 

931 self.mock_policy_check.assert_called_once_with( 

932 req_context, self.resource_name, 'get') 

933 

934 def test_share_group_show_as_admin(self): 

935 req = fakes.HTTPRequest.blank( 

936 '/share-groupss/my_group_id', version=self.api_version, 

937 experimental=True) 

938 admin_context = req.environ['manila.context'].elevated() 

939 req.environ['manila.context'] = admin_context 

940 fake_group, expected_group = self._get_fake_share_group( 

941 ctxt=admin_context, id='my_group_id') 

942 self.mock_object(share_group_api.API, 'get', 

943 mock.Mock(return_value=fake_group)) 

944 

945 res_dict = self.controller.show(req, fake_group['id']) 

946 

947 self.assertEqual(expected_group, res_dict['share_group']) 

948 self.assertIsNotNone(res_dict['share_group']['share_server_id']) 

949 self.mock_policy_check.assert_called_once_with( 

950 admin_context, self.resource_name, 'get') 

951 

952 def test_share_group_show_group_not_found(self): 

953 req = fakes.HTTPRequest.blank( 

954 '/share-groupss/myfakegroup', version=self.api_version, 

955 experimental=True) 

956 req_context = req.environ['manila.context'] 

957 fake, expected = self._get_fake_share_group( 

958 ctxt=req_context, id='myfakegroup') 

959 self.mock_object(share_group_api.API, 'get', 

960 mock.Mock(side_effect=exception.NotFound)) 

961 

962 self.assertRaises( 

963 webob.exc.HTTPNotFound, self.controller.show, req, fake['id']) 

964 

965 self.mock_policy_check.assert_called_once_with( 

966 req_context, self.resource_name, 'get') 

967 

968 @ddt.data({'microversion': '2.31', 'experimental': True}, 

969 {'microversion': SG_GRADUATION_VERSION, 'experimental': False}) 

970 @ddt.unpack 

971 def test__reset_status_call(self, microversion, experimental): 

972 self.mock_object(self.controller, '_reset_status') 

973 req, _junk = self._get_fake_custom_request_and_context( 

974 microversion, experimental) 

975 sg_id = 'fake' 

976 body = {'reset_status': {'status': constants.STATUS_ERROR}} 

977 

978 self.controller.share_group_reset_status(req, sg_id, body) 

979 self.controller._reset_status.assert_called_once_with(req, sg_id, body) 

980 

981 @ddt.data(*fakes.fixture_reset_status_with_different_roles) 

982 @ddt.unpack 

983 def test_share_groups_reset_status_with_different_roles( 

984 self, role, valid_code, valid_status, version): 

985 ctxt = self._get_context(role) 

986 share_group, req = self._setup_share_group_data() 

987 

988 action_name = 'reset_status' 

989 body = {action_name: {'status': constants.STATUS_ERROR}} 

990 req.method = 'POST' 

991 req.headers['content-type'] = 'application/json' 

992 req.body = jsonutils.dumps(body).encode("utf-8") 

993 req.headers['X-Openstack-Manila-Api-Version'] = self.api_version 

994 req.environ['manila.context'] = ctxt 

995 

996 with mock.patch.object( 

997 policy, 'check_policy', fakes.mock_fake_admin_check): 

998 resp = req.get_response(fakes.app()) 

999 

1000 # validate response code and model status 

1001 self.assertEqual(valid_code, resp.status_int) 

1002 

1003 actual_model = db.share_group_get(ctxt, share_group['id']) 

1004 self.assertEqual(valid_status, actual_model['status']) 

1005 

1006 @ddt.data(*fakes.fixture_force_delete_with_different_roles) 

1007 @ddt.unpack 

1008 def test_share_group_force_delete_with_different_roles(self, role, 

1009 resp_code, version): 

1010 ctxt = self._get_context(role) 

1011 share_group, req = self._setup_share_group_data() 

1012 req.method = 'POST' 

1013 req.headers['content-type'] = 'application/json' 

1014 action_name = 'force_delete' 

1015 body = {action_name: {}} 

1016 req.body = jsonutils.dumps(body).encode("utf-8") 

1017 req.headers['X-Openstack-Manila-Api-Version'] = self.api_version 

1018 req.environ['manila.context'] = ctxt 

1019 

1020 with mock.patch.object( 

1021 policy, 'check_policy', fakes.mock_fake_admin_check): 

1022 resp = req.get_response(fakes.app()) 

1023 

1024 # validate response 

1025 self.assertEqual(resp_code, resp.status_int) 

1026 

1027 @ddt.data({'microversion': '2.31', 'experimental': True}, 

1028 {'microversion': SG_GRADUATION_VERSION, 'experimental': False}) 

1029 @ddt.unpack 

1030 def test__force_delete_call(self, microversion, experimental): 

1031 self.mock_object(self.controller, '_force_delete') 

1032 req, _junk = self._get_fake_custom_request_and_context( 

1033 microversion, experimental) 

1034 sg_id = 'fake' 

1035 body = {'force_delete': {}} 

1036 

1037 self.controller.share_group_force_delete(req, sg_id, body) 

1038 self.controller._force_delete.assert_called_once_with(req, sg_id, body)