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
« 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.
16import copy
17import datetime
18from unittest import mock
20import ddt
21from oslo_config import cfg
22from oslo_serialization import jsonutils
23from oslo_utils import uuidutils
24import webob
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
41CONF = cfg.CONF
42SG_GRADUATION_VERSION = '2.55'
45@ddt.ddt
46class ShareGroupAPITest(test.TestCase):
47 """Consistency Groups API Test suite."""
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))
70 def _get_context(self, role):
71 return getattr(self, '%s_context' % role)
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'
82 return share_group, req
84 def _get_fake_share_group(self, ctxt=None, **values):
85 if ctxt is None:
86 ctxt = self.context
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 }
106 share_group_db_dict.update(**values)
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']
131 return share_group_db_dict, expected_share_group
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
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
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": {}}
159 res_dict = self.controller.create(req, body)
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')
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 }
181 self.assertRaises(webob.exc.HTTPConflict,
182 self.controller.create, self.request, body)
184 self.mock_policy_check.assert_called_once_with(
185 self.context, self.resource_name, 'create')
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": {}}
195 self.assertRaises(
196 webob.exc.HTTPBadRequest,
197 self.controller.create, self.request, body)
199 self.mock_policy_check.assert_called_once_with(
200 self.context, self.resource_name, 'create')
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": {}}
211 self.assertRaises(
212 webob.exc.HTTPBadRequest,
213 self.controller.create, self.request, body)
215 self.mock_policy_check.assert_called_once_with(
216 self.context, self.resource_name, 'create')
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 }
231 self.controller.create(self.request, body)
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')
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"}}
248 self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
249 self.request, body)
251 self.mock_policy_check.assert_called_once_with(
252 self.context, self.resource_name, 'create')
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 })))
270 body = {"share_group": {"availability_zone": fake_az_name}}
272 res_dict = self.controller.create(self.request, body)
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')
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 })))
301 body = {"share_group": {
302 "availability_zone": fake_az_name,
303 "source_share_group_snapshot_id": 'fake_sgs_id',
304 }}
306 self.assertRaises(
307 webob.exc.HTTPBadRequest,
308 self.controller.create,
309 self.request, body)
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')
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)))
329 body = {"share_group": {"availability_zone": fake_az_name}}
331 self.assertRaises(
332 webob.exc.HTTPNotFound,
333 self.controller.create, self.request, body)
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')
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}}
349 res_dict = self.controller.create(self.request, body)
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')
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}}
369 res_dict = self.controller.create(self.request, body)
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')
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 }
391 res_dict = self.controller.create(self.request, body)
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')
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 }
414 self.assertRaises(webob.exc.HTTPBadRequest,
415 self.controller.create,
416 self.request, body)
418 self.assertFalse(mock_api_call.called)
419 self.mock_policy_check.assert_called_once_with(
420 self.context, self.resource_name, 'create')
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))
431 body = {
432 "share_group": {
433 "source_share_group_snapshot_id": fake_snap_id,
434 }
435 }
437 res_dict = self.controller.create(self.request, body)
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')
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)
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 }
461 res_dict = self.controller.create(self.request, body)
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')
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 }
484 res_dict = self.controller.create(self.request, body)
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')
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 }
509 res_dict = self.controller.create(self.request, body)
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')
519 def test_share_group_create_invalid_body(self):
520 body = {"not_group": {}}
522 self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
523 self.request, body)
525 self.mock_policy_check.assert_called_once_with(
526 self.context, self.resource_name, 'create')
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')
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')))
551 self.assertRaises(
552 webob.exc.HTTPConflict, self.controller.create, self.request, body)
554 self.mock_policy_check.assert_called_once_with(
555 self.context, self.resource_name, 'create')
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)))
567 self.assertRaises(
568 webob.exc.HTTPBadRequest,
569 self.controller.create, self.request, body)
571 self.mock_policy_check.assert_called_once_with(
572 self.context, self.resource_name, 'create')
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')))
584 self.assertRaises(
585 webob.exc.HTTPBadRequest,
586 self.controller.create, self.request, body)
588 self.mock_policy_check.assert_called_once_with(
589 self.context, self.resource_name, 'create')
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 }
599 self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
600 self.request, body)
602 self.mock_policy_check.assert_called_once_with(
603 self.context, self.resource_name, 'create')
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}}
609 self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
610 self.request, body)
612 self.mock_policy_check.assert_called_once_with(
613 self.context, self.resource_name, 'create')
615 def test_share_group_create_invalid_body_share_types_not_a_list(self):
616 body = {"share_group": {"share_types": ""}}
618 self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
619 self.request, body)
621 self.mock_policy_check.assert_called_once_with(
622 self.context, self.resource_name, 'create')
624 def test_share_group_create_invalid_body_invalid_field(self):
625 body = {"share_group": {"unknown_field": ""}}
627 exc = self.assertRaises(webob.exc.HTTPBadRequest,
628 self.controller.create,
629 self.request, body)
631 self.assertIn('unknown_field', str(exc))
632 self.mock_policy_check.assert_called_once_with(
633 self.context, self.resource_name, 'create')
635 def test_share_group_create_with_invalid_share_types_field(self):
636 body = {"share_group": {"share_types": 'iamastring'}}
638 self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
639 self.request, body)
641 self.mock_policy_check.assert_called_once_with(
642 self.context, self.resource_name, 'create')
644 def test_share_group_create_with_invalid_share_types_field_not_uuids(self):
645 body = {"share_group": {"share_types": ['iamastring']}}
647 self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
648 self.request, body)
650 self.mock_policy_check.assert_called_once_with(
651 self.context, self.resource_name, 'create')
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 }
675 res_dict = self.controller.update(req, fake_group['id'], body)
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')
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))
689 self.assertRaises(webob.exc.HTTPNotFound,
690 self.controller.update,
691 self.request, 'fake_id', body)
693 self.mock_policy_check.assert_called_once_with(
694 self.context, self.resource_name, 'update')
696 def test_share_group_update_invalid_body(self):
697 body = {"not_group": {}}
699 self.assertRaises(webob.exc.HTTPBadRequest,
700 self.controller.update,
701 self.request, 'fake_id', body)
703 self.mock_policy_check.assert_called_once_with(
704 self.context, self.resource_name, 'update')
706 def test_share_group_update_invalid_body_invalid_field(self):
707 body = {"share_group": {"unknown_field": ""}}
709 exc = self.assertRaises(webob.exc.HTTPBadRequest,
710 self.controller.update,
711 self.request, 'fake_id', body)
713 self.assertIn('unknown_field', str(exc))
714 self.mock_policy_check.assert_called_once_with(
715 self.context, self.resource_name, 'update')
717 def test_share_group_update_invalid_body_readonly_field(self):
718 body = {"share_group": {"share_types": []}}
720 exc = self.assertRaises(webob.exc.HTTPBadRequest,
721 self.controller.update,
722 self.request, 'fake_id', body)
724 self.assertIn('share_types', str(exc))
725 self.mock_policy_check.assert_called_once_with(
726 self.context, self.resource_name, 'update')
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)
738 res_dict = self.controller.index(req)
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')
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=[]))
748 res_dict = self.controller.index(self.request)
750 self.assertEqual([], res_dict['share_groups'])
751 self.mock_policy_check.assert_called_once_with(
752 self.context, self.resource_name, 'get_all')
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']
765 res_dict = self.controller.index(req)
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')
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']
783 res_dict = self.controller.index(req)
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')
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']
802 res_dict = self.controller.index(req)
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')
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)
821 res_dict = self.controller.detail(req)
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')
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=[]))
831 res_dict = self.controller.detail(self.request)
833 self.assertEqual([], res_dict['share_groups'])
834 self.mock_policy_check.assert_called_once_with(
835 self.context, self.resource_name, 'get_all')
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]))
849 res_dict = self.controller.detail(req)
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')
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]))
868 res_dict = self.controller.detail(req)
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')
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)
886 res = self.controller.delete(req, fake_group['id'])
888 self.assertEqual(202, res.status_code)
889 self.mock_policy_check.assert_called_once_with(
890 req_context, self.resource_name, 'delete')
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))
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')
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')))
909 self.assertRaises(
910 webob.exc.HTTPConflict,
911 self.controller.delete, self.request, fake['id'])
913 self.mock_policy_check.assert_called_once_with(
914 self.context, self.resource_name, 'delete')
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']
928 res_dict = self.controller.show(req, fake['id'])
930 self.assertEqual(expected, res_dict['share_group'])
931 self.mock_policy_check.assert_called_once_with(
932 req_context, self.resource_name, 'get')
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))
945 res_dict = self.controller.show(req, fake_group['id'])
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')
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))
962 self.assertRaises(
963 webob.exc.HTTPNotFound, self.controller.show, req, fake['id'])
965 self.mock_policy_check.assert_called_once_with(
966 req_context, self.resource_name, 'get')
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}}
978 self.controller.share_group_reset_status(req, sg_id, body)
979 self.controller._reset_status.assert_called_once_with(req, sg_id, body)
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()
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
996 with mock.patch.object(
997 policy, 'check_policy', fakes.mock_fake_admin_check):
998 resp = req.get_response(fakes.app())
1000 # validate response code and model status
1001 self.assertEqual(valid_code, resp.status_int)
1003 actual_model = db.share_group_get(ctxt, share_group['id'])
1004 self.assertEqual(valid_status, actual_model['status'])
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
1020 with mock.patch.object(
1021 policy, 'check_policy', fakes.mock_fake_admin_check):
1022 resp = req.get_response(fakes.app())
1024 # validate response
1025 self.assertEqual(resp_code, resp.status_int)
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': {}}
1037 self.controller.share_group_force_delete(req, sg_id, body)
1038 self.controller._force_delete.assert_called_once_with(req, sg_id, body)