diff --git a/cinder/api/v2/types.py b/cinder/api/v2/types.py index 4109ec54135..c6816447aa0 100644 --- a/cinder/api/v2/types.py +++ b/cinder/api/v2/types.py @@ -21,11 +21,14 @@ from webob import exc from cinder.api.openstack import wsgi from cinder.api.v2.views import types as views_types from cinder.api import xmlutil +from cinder import context as ctx from cinder import exception from cinder.i18n import _ from cinder import utils from cinder.volume import volume_types +import cinder.policy + def make_voltype(elem): elem.set('id') @@ -57,6 +60,18 @@ class VolumeTypesController(wsgi.Controller): _view_builder_class = views_types.ViewBuilder + def _validate_policy(self, context): + target = { + 'project_id': context.project_id, + 'user_id': context.user_id, + } + try: + action = 'volume_extension:access_types_extra_specs' + cinder.policy.enforce(context, action, target) + return True + except Exception: + return False + @wsgi.serializers(xml=VolumeTypesTemplate) def index(self, req): """Returns the list of volume types.""" @@ -69,6 +84,9 @@ class VolumeTypesController(wsgi.Controller): """Return a single volume type item.""" context = req.environ['cinder.context'] + if not context.is_admin and self._validate_policy(context): + context = ctx.get_admin_context() + # get default volume type if id is not None and id == 'default': vol_type = volume_types.get_default_volume_type() @@ -109,6 +127,8 @@ class VolumeTypesController(wsgi.Controller): """Helper function that returns a list of type dicts.""" filters = {} context = req.environ['cinder.context'] + if not context.is_admin and self._validate_policy(context): + context = ctx.get_admin_context() if context.is_admin: # Only admin has query access to all volume types filters['is_public'] = self._parse_is_public( diff --git a/cinder/api/v2/views/types.py b/cinder/api/v2/views/types.py index af8a0495427..6c93f01b912 100644 --- a/cinder/api/v2/views/types.py +++ b/cinder/api/v2/views/types.py @@ -25,10 +25,10 @@ class ViewBuilder(common.ViewBuilder): trimmed = dict(id=volume_type.get('id'), name=volume_type.get('name'), is_public=volume_type.get('is_public'), - extra_specs=volume_type.get('extra_specs'), description=volume_type.get('description')) if context.is_admin: trimmed['qos_specs_id'] = volume_type.get('qos_specs_id') + trimmed['extra_specs'] = volume_type.get('extra_specs') return trimmed if brief else dict(volume_type=trimmed) def index(self, request, volume_types): diff --git a/cinder/tests/unit/api/v2/test_types.py b/cinder/tests/unit/api/v2/test_types.py index e9287d5baa8..d05e28d99e6 100644 --- a/cinder/tests/unit/api/v2/test_types.py +++ b/cinder/tests/unit/api/v2/test_types.py @@ -85,7 +85,7 @@ class VolumeTypesApiTest(test.TestCase): self.stubs.Set(volume_types, 'get_all_types', return_volume_types_get_all_types) - req = fakes.HTTPRequest.blank('/v2/fake/types') + req = fakes.HTTPRequest.blank('/v2/fake/types', use_admin_context=True) res_dict = self.controller.index(req) self.assertEqual(3, len(res_dict['volume_types'])) @@ -171,7 +171,6 @@ class VolumeTypesApiTest(test.TestCase): name='new_type', description='new_type_desc', is_public=True, - extra_specs={}, id=42, ) self.assertDictMatch(output['volume_type'], expected_volume_type) @@ -237,7 +236,6 @@ class VolumeTypesApiTest(test.TestCase): name='new_type', description='new_type_desc', is_public=True, - extra_specs={}, id=42 + i ) self.assertDictMatch(output['volume_types'][i], diff --git a/etc/cinder/policy.json b/etc/cinder/policy.json index 4c8a8aa5079..1b07629a9a8 100644 --- a/etc/cinder/policy.json +++ b/etc/cinder/policy.json @@ -25,6 +25,7 @@ "volume_extension:types_manage": "rule:admin_api", "volume_extension:types_extra_specs": "rule:admin_api", + "volume_extension:access_types_extra_specs": "rule:admin_api", "volume_extension:volume_type_access": "rule:admin_or_owner", "volume_extension:volume_type_access:addProjectAccess": "rule:admin_api", "volume_extension:volume_type_access:removeProjectAccess": "rule:admin_api",