diff --git a/api-ref/source/parameters.yaml b/api-ref/source/parameters.yaml index 8284ac4f08..fcd3c99ab8 100644 --- a/api-ref/source/parameters.yaml +++ b/api-ref/source/parameters.yaml @@ -298,6 +298,19 @@ group_snapshot_status_query: in: query required: false type: string +group_specs_query: + description: | + The group specifications as a set of one or more + key-value pairs. In each pair, the key is the name of the group + specification and the value is the share group type that was used to + filter search share group type list. The query must be a “percent-encoded” string, + for example, the following query parameters: {'group-specs': + {'consistent_snapshot_support': 'true'}} is encoded as + 'group_specs=%7B%27consistent_snapshot_support%27%3A+%27True%27%7D' + in: query + required: false + type: string + min_version: 2.66 host_query: description: | The host name of the resource to query with. Querying by hostname is a diff --git a/api-ref/source/share-group-types.inc b/api-ref/source/share-group-types.inc index e83bb22dfd..1f38e4a3f3 100644 --- a/api-ref/source/share-group-types.inc +++ b/api-ref/source/share-group-types.inc @@ -58,6 +58,8 @@ Request .. rest_parameters:: parameters.yaml - project_id: project_id_path + - is_public: is_public_query + - group_specs: group_specs_query Response parameters ------------------- diff --git a/manila/api/common.py b/manila/api/common.py index 11962e6bf9..fb34729a57 100644 --- a/manila/api/common.py +++ b/manila/api/common.py @@ -266,6 +266,27 @@ def check_share_network_is_active(share_network): raise webob.exc.HTTPBadRequest(explanation=msg) +def parse_is_public(is_public): + """Parse is_public into something usable. + + :returns: + - True: API should list public share group types only + - False: API should list private share group types only + - None: API should list both public and private share group types + """ + if is_public is None: + # preserve default value of showing only public types + return True + elif six.text_type(is_public).lower() == "all": + return None + else: + try: + return strutils.bool_from_string(is_public, strict=True) + except ValueError: + msg = _('Invalid is_public filter [%s]') % is_public + raise webob.exc.HTTPBadRequest(explanation=msg) + + class ViewBuilder(object): """Model API responses as dictionaries.""" diff --git a/manila/api/openstack/api_version_request.py b/manila/api/openstack/api_version_request.py index 1d9cc5e911..723ee748c0 100644 --- a/manila/api/openstack/api_version_request.py +++ b/manila/api/openstack/api_version_request.py @@ -172,13 +172,14 @@ REST_API_VERSION_HISTORY = """ 'update_security_service', 'update_security_service_check' and 'add_security_service_check'. * 2.65 - Added ability to set scheduler hints via the share create API. + * 2.66 - Added filter search by group spec for share group type list. """ # The minimum and maximum versions of the API supported # The default api version request is defined to be the # minimum version of the API supported. _MIN_API_VERSION = "2.0" -_MAX_API_VERSION = "2.65" +_MAX_API_VERSION = "2.66" DEFAULT_API_VERSION = _MIN_API_VERSION diff --git a/manila/api/openstack/rest_api_version_history.rst b/manila/api/openstack/rest_api_version_history.rst index 70218c38d0..be56611565 100644 --- a/manila/api/openstack/rest_api_version_history.rst +++ b/manila/api/openstack/rest_api_version_history.rst @@ -363,3 +363,7 @@ user documentation. Added ability to specify "scheduler_hints" in the request body of the POST /shares request. These hints will invoke Affinity/Anti-Affinity scheduler filters during share creation and share migration. + +2.66 +---- + Added filter search by group spec for share group type list. diff --git a/manila/api/v2/share_group_types.py b/manila/api/v2/share_group_types.py index 1c66c46c0e..5f8a8acf44 100644 --- a/manila/api/v2/share_group_types.py +++ b/manila/api/v2/share_group_types.py @@ -11,14 +11,16 @@ # under the License. """The group type API controller module.""" +import ast -from oslo_utils import strutils from oslo_utils import uuidutils import six from six.moves import http_client import webob from webob import exc +from manila.api import common +from manila.api.openstack import api_version_request as api_version from manila.api.openstack import wsgi from manila.api.views import share_group_types as views from manila import exception @@ -104,35 +106,27 @@ class ShareGroupTypesController(wsgi.Controller): context = req.environ['manila.context'] if context.is_admin: # Only admin has query access to all group types - filters['is_public'] = self._parse_is_public( + filters['is_public'] = common.parse_is_public( req.params.get('is_public')) else: filters['is_public'] = True + + group_specs = req.params.get('group_specs', {}) + group_specs_disallowed = (req.api_version_request < + api_version.APIVersionRequest("2.66")) + + if group_specs and group_specs_disallowed: + msg = _("Filter by 'group_specs' is not supported by this " + "microversion. Use 2.66 or greater microversion to " + "be able to use filter search by 'group_specs.") + raise webob.exc.HTTPBadRequest(explanation=msg) + elif group_specs: + filters['group_specs'] = ast.literal_eval(group_specs) + limited_types = share_group_types.get_all( context, search_opts=filters).values() return list(limited_types) - @staticmethod - def _parse_is_public(is_public): - """Parse is_public into something usable. - - :returns: - - True: API should list public share group types only - - False: API should list private share group types only - - None: API should list both public and private share group types - """ - if is_public is None: - # preserve default value of showing only public types - return True - elif six.text_type(is_public).lower() == "all": - return None - else: - try: - return strutils.bool_from_string(is_public, strict=True) - except ValueError: - msg = _('Invalid is_public filter [%s]') % is_public - raise exc.HTTPBadRequest(explanation=msg) - @wsgi.Controller.authorize('create') def _create(self, req, body): """Creates a new share group type.""" diff --git a/manila/api/v2/share_types.py b/manila/api/v2/share_types.py index 902357eb3b..3ed218eb92 100644 --- a/manila/api/v2/share_types.py +++ b/manila/api/v2/share_types.py @@ -25,6 +25,7 @@ from six.moves import http_client import webob from webob import exc +from manila.api import common from manila.api.openstack import api_version_request as api_version from manila.api.openstack import wsgi from manila.api.views import types as views_types @@ -125,7 +126,7 @@ class ShareTypesController(wsgi.Controller): context = req.environ['manila.context'] if context.is_admin: # Only admin has query access to all share types - filters['is_public'] = self._parse_is_public( + filters['is_public'] = common.parse_is_public( req.params.get('is_public')) else: filters['is_public'] = True @@ -148,26 +149,6 @@ class ShareTypesController(wsgi.Controller): context, search_opts=filters).values() return list(limited_types) - @staticmethod - def _parse_is_public(is_public): - """Parse is_public into something usable. - - * True: API should list public share types only - * False: API should list private share types only - * None: API should list both public and private share types - """ - if is_public is None: - # preserve default value of showing only public types - return True - elif six.text_type(is_public).lower() == "all": - return None - else: - try: - return strutils.bool_from_string(is_public, strict=True) - except ValueError: - msg = _('Invalid is_public filter [%s]') % is_public - raise exc.HTTPBadRequest(explanation=msg) - @wsgi.Controller.api_version("1.0", "2.23") @wsgi.action("create") def create(self, req, body): diff --git a/manila/tests/api/test_common.py b/manila/tests/api/test_common.py index 7f7fd973a9..549ab57070 100644 --- a/manila/tests/api/test_common.py +++ b/manila/tests/api/test_common.py @@ -344,6 +344,16 @@ class MiscFunctionsTest(test.TestCase): result = common.check_net_id_and_subnet_id(body) self.assertIsNone(result) + @ddt.data(None, True, 'true', 'false', 'all') + def test_parse_is_public_valid(self, value): + result = common.parse_is_public(value) + self.assertIn(result, (True, False, None)) + + def test_parse_is_public_invalid(self): + self.assertRaises(webob.exc.HTTPBadRequest, + common.parse_is_public, + 'fakefakefake') + @ddt.ddt class ViewBuilderTest(test.TestCase): diff --git a/manila/tests/api/v2/test_share_types.py b/manila/tests/api/v2/test_share_types.py index 35add9d63a..d0a9c28927 100644 --- a/manila/tests/api/v2/test_share_types.py +++ b/manila/tests/api/v2/test_share_types.py @@ -430,16 +430,6 @@ class ShareTypesAPITest(test.TestCase): self.assertDictEqual(expected_share_type, output['share_types'][i]) - @ddt.data(None, True, 'true', 'false', 'all') - def test_parse_is_public_valid(self, value): - result = self.controller._parse_is_public(value) - self.assertIn(result, (True, False, None)) - - def test_parse_is_public_invalid(self): - self.assertRaises(webob.exc.HTTPBadRequest, - self.controller._parse_is_public, - 'fakefakefake') - @ddt.data( ("new_name", "new_description", "wrong_bool"), (" ", "new_description", "true"), diff --git a/manila/tests/share_group/test_share_group_types.py b/manila/tests/share_group/test_share_group_types.py index ebb3fea1cf..7b29126180 100644 --- a/manila/tests/share_group/test_share_group_types.py +++ b/manila/tests/share_group/test_share_group_types.py @@ -102,7 +102,7 @@ class ShareGroupTypesTestCase(test.TestCase): def test_get_all_types_search(self): share_group_type = self.fake_type_w_extra - search_filter = {"group_specs": {"gold": "True"}, 'is_public': True} + search_filter = {'group_specs': {'gold': 'True'}, 'is_public': True} self.mock_object( db, 'share_group_type_get_all', mock.Mock(return_value=share_group_type)) @@ -113,11 +113,17 @@ class ShareGroupTypesTestCase(test.TestCase): db.share_group_type_get_all.assert_called_once_with( mock.ANY, 0, filters={'is_public': True}) self.assertEqual(sorted(share_group_type), sorted(returned_type)) - search_filter = {"group_specs": {"gold": "False"}} + search_filter = {'group_specs': {'gold': 'False'}} returned_type = share_group_types.get_all( self.context, search_opts=search_filter) self.assertEqual({}, returned_type) + share_group_type = self.fake_type_w_extra + search_filter = {'group_specs': {'gold': 'True'}} + returned_type = share_group_types.get_all( + self.context, search_opts=search_filter) + self.assertItemsEqual(share_group_type, returned_type) + def test_add_access(self): project_id = '456' share_group_type = share_group_types.create(self.context, 'type2', []) diff --git a/releasenotes/notes/bp-support-group-spec-search-share-group-type-api-df55d056b622ced7.yaml b/releasenotes/notes/bp-support-group-spec-search-share-group-type-api-df55d056b622ced7.yaml new file mode 100644 index 0000000000..ff3537e7ac --- /dev/null +++ b/releasenotes/notes/bp-support-group-spec-search-share-group-type-api-df55d056b622ced7.yaml @@ -0,0 +1,3 @@ +--- +features: + - Share group types can now be filtered with its group_specs.