diff --git a/cinder/api/openstack/api_version_request.py b/cinder/api/openstack/api_version_request.py index e2e99fb8599..667a7d3dc48 100644 --- a/cinder/api/openstack/api_version_request.py +++ b/cinder/api/openstack/api_version_request.py @@ -74,6 +74,7 @@ REST_API_VERSION_HISTORY = """ * 3.22 - Add filtering based on metadata for snapshot listing. * 3.23 - Allow passing force parameter to volume delete. * 3.24 - Add workers/cleanup endpoint. + * 3.25 - Add ``volumes`` field to group list/detail and group show. """ # The minimum and maximum versions of the API supported @@ -81,7 +82,7 @@ REST_API_VERSION_HISTORY = """ # minimum version of the API supported. # Explicitly using /v1 or /v2 enpoints will still work _MIN_API_VERSION = "3.0" -_MAX_API_VERSION = "3.24" +_MAX_API_VERSION = "3.25" _LEGACY_API_VERSION1 = "1.0" _LEGACY_API_VERSION2 = "2.0" diff --git a/cinder/api/openstack/rest_api_version_history.rst b/cinder/api/openstack/rest_api_version_history.rst index 367415a3370..f0380aab9d1 100644 --- a/cinder/api/openstack/rest_api_version_history.rst +++ b/cinder/api/openstack/rest_api_version_history.rst @@ -264,3 +264,7 @@ user documentation. ``id``, ``host``, ``binary``, and ``cluster_name``. These are not the services that will be performing the cleanup, but the services that will be cleaned up or couldn't be cleaned up. + +3.25 +---- + Add ``volumes`` field to group list/detail and group show. diff --git a/cinder/api/v3/views/groups.py b/cinder/api/v3/views/groups.py index 1d012804b02..264c7794980 100644 --- a/cinder/api/v3/views/groups.py +++ b/cinder/api/v3/views/groups.py @@ -14,6 +14,7 @@ # under the License. from cinder.api import common +from cinder import utils class ViewBuilder(common.ViewBuilder): @@ -64,6 +65,12 @@ class ViewBuilder(common.ViewBuilder): group_ref['group']['group_snapshot_id'] = group.group_snapshot_id group_ref['group']['source_group_id'] = group.source_group_id + # Add volumes if min version is greater than or equal to 3.25. + if req_version.matches("3.25", None): + if utils.get_bool_param('list_volume', request.params): + group_ref['group']['volumes'] = [volume.id + for volume in group.volumes] + return group_ref def _list_view(self, func, request, groups): diff --git a/cinder/tests/unit/api/v3/test_groups.py b/cinder/tests/unit/api/v3/test_groups.py index d94df7798c9..cb4c7723d3b 100644 --- a/cinder/tests/unit/api/v3/test_groups.py +++ b/cinder/tests/unit/api/v3/test_groups.py @@ -144,6 +144,49 @@ class GroupsAPITestCase(test.TestCase): self.assertEqual([fake.VOLUME_TYPE_ID], res_dict['group']['volume_types']) + @mock.patch('cinder.objects.volume_type.VolumeTypeList.get_all_by_group') + @mock.patch('cinder.objects.volume.VolumeList.get_all_by_generic_group') + def test_show_group_with_list_volume(self, mock_vol_get_all_by_group, + mock_vol_type_get_all_by_group): + volume_objs = [objects.Volume(context=self.ctxt, id=i) + for i in [fake.VOLUME_ID]] + volumes = objects.VolumeList(context=self.ctxt, objects=volume_objs) + mock_vol_get_all_by_group.return_value = volumes + + vol_type_objs = [objects.VolumeType(context=self.ctxt, id=i) + for i in [fake.VOLUME_TYPE_ID]] + vol_types = objects.VolumeTypeList(context=self.ctxt, + objects=vol_type_objs) + mock_vol_type_get_all_by_group.return_value = vol_types + + # If the microversion >= 3.25 and "list_volume=True", "volumes" should + # be contained in the response body. + req = fakes.HTTPRequest.blank('/v3/%s/groups/%s?list_volume=True' % + (fake.PROJECT_ID, self.group1.id), + version='3.25') + res_dict = self.controller.show(req, self.group1.id) + self.assertEqual(1, len(res_dict)) + self.assertEqual([fake.VOLUME_ID], + res_dict['group']['volumes']) + + # If the microversion >= 3.25 but "list_volume" is missing, "volumes" + # should not be contained in the response body. + req = fakes.HTTPRequest.blank('/v3/%s/groups/%s' % + (fake.PROJECT_ID, self.group1.id), + version='3.25') + res_dict = self.controller.show(req, self.group1.id) + self.assertEqual(1, len(res_dict)) + self.assertIsNone(res_dict['group'].get('volumes', None)) + + # If the microversion < 3.25, "volumes" should not be contained in the + # response body. + req = fakes.HTTPRequest.blank('/v3/%s/groups/%s?list_volume=True' % + (fake.PROJECT_ID, self.group1.id), + version='3.24') + res_dict = self.controller.show(req, self.group1.id) + self.assertEqual(1, len(res_dict)) + self.assertIsNone(res_dict['group'].get('volumes', None)) + def test_show_group_with_group_NotFound(self): req = fakes.HTTPRequest.blank('/v3/%s/groups/%s' % (fake.PROJECT_ID, diff --git a/releasenotes/notes/improvement-to-get-group-detail-0e8b68114e79a8a2.yaml b/releasenotes/notes/improvement-to-get-group-detail-0e8b68114e79a8a2.yaml new file mode 100644 index 00000000000..b1d602863a2 --- /dev/null +++ b/releasenotes/notes/improvement-to-get-group-detail-0e8b68114e79a8a2.yaml @@ -0,0 +1,5 @@ +--- +features: + - Added support for querying group details with volume ids + which are in this group. + For example, "groups/{group_id}?list_volume=True".