Return volume_type extra specs based on policy

Currently extra specs are only shown to the admin user
when showing volume types. This patch grants the flexibility
to grant other users privelages to see them based on policy.

It also hides the extra_specs entry in the dictionary from
users who can't see it rather than just showing "None" as
the value.

Closes-Bug: #1504577
APIImpact

Change-Id: Ia8f71180f048ba9b253e35ee136915812ef8df0c
This commit is contained in:
Nate Potter 2015-10-19 16:24:29 +00:00
parent b2e92b85b5
commit 94714e761a
4 changed files with 23 additions and 4 deletions

View File

@ -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(

View File

@ -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):

View File

@ -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],

View File

@ -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",