from cinder.api.openstack import wsgi
from cinder.api import xmlutil
+from cinder import exception
from cinder.i18n import _
+import cinder.policy
from cinder import utils
return True
+def validate_policy(context, action):
+ try:
+ cinder.policy.enforce_action(context, action)
+ return True
+ except exception.PolicyNotAuthorized:
+ return False
+
+
def get_pagination_params(params, max_limit=None):
"""Return marker, limit, offset tuple from request.
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')
_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."""
"""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()
# to filters.
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(
name=volume_type.get('name'),
is_public=volume_type.get('is_public'),
description=volume_type.get('description'))
- if context.is_admin:
- trimmed['qos_specs_id'] = volume_type.get('qos_specs_id')
+ if common.validate_policy(
+ context,
+ 'volume_extension:access_types_extra_specs'):
trimmed['extra_specs'] = volume_type.get('extra_specs')
+ if common.validate_policy(
+ context,
+ 'volume_extension:access_types_qos_specs_id'):
+ trimmed['qos_specs_id'] = volume_type.get('qos_specs_id')
return trimmed if brief else dict(volume_type=trimmed)
def index(self, request, volume_types):
import uuid
from lxml import etree
+import mock
from oslo_utils import timeutils
import six
import webob
+import cinder.api.common as common
from cinder.api.v2 import types
from cinder.api.v2.views import types as views_types
from cinder import context
)
self.assertDictMatch(expected_volume_type, output['volume_type'])
+ def test_view_builder_show_qos_specs_id_policy(self):
+ with mock.patch.object(common,
+ 'validate_policy',
+ side_effect=[False, True]):
+ view_builder = views_types.ViewBuilder()
+ now = timeutils.utcnow().isoformat()
+ raw_volume_type = dict(
+ name='new_type',
+ description='new_type_desc',
+ qos_specs_id='new_id',
+ is_public=True,
+ deleted=False,
+ created_at=now,
+ updated_at=now,
+ extra_specs={},
+ deleted_at=None,
+ id=42,
+ )
+
+ request = fakes.HTTPRequest.blank("/v2")
+ output = view_builder.show(request, raw_volume_type)
+
+ self.assertIn('volume_type', output)
+ expected_volume_type = dict(
+ name='new_type',
+ description='new_type_desc',
+ qos_specs_id='new_id',
+ is_public=True,
+ id=42,
+ )
+ self.assertDictMatch(expected_volume_type, output['volume_type'])
+
+ def test_view_builder_show_extra_specs_policy(self):
+ with mock.patch.object(common,
+ 'validate_policy',
+ side_effect=[True, False]):
+ view_builder = views_types.ViewBuilder()
+ now = timeutils.utcnow().isoformat()
+ raw_volume_type = dict(
+ name='new_type',
+ description='new_type_desc',
+ qos_specs_id='new_id',
+ is_public=True,
+ deleted=False,
+ created_at=now,
+ updated_at=now,
+ extra_specs={},
+ deleted_at=None,
+ id=42,
+ )
+
+ request = fakes.HTTPRequest.blank("/v2")
+ output = view_builder.show(request, raw_volume_type)
+
+ self.assertIn('volume_type', output)
+ expected_volume_type = dict(
+ name='new_type',
+ description='new_type_desc',
+ extra_specs={},
+ is_public=True,
+ id=42,
+ )
+ self.assertDictMatch(expected_volume_type, output['volume_type'])
+
+ def test_view_builder_show_pass_all_policy(self):
+ with mock.patch.object(common,
+ 'validate_policy',
+ side_effect=[True, True]):
+ view_builder = views_types.ViewBuilder()
+ now = timeutils.utcnow().isoformat()
+ raw_volume_type = dict(
+ name='new_type',
+ description='new_type_desc',
+ qos_specs_id='new_id',
+ is_public=True,
+ deleted=False,
+ created_at=now,
+ updated_at=now,
+ extra_specs={},
+ deleted_at=None,
+ id=42,
+ )
+
+ request = fakes.HTTPRequest.blank("/v2")
+ output = view_builder.show(request, raw_volume_type)
+
+ self.assertIn('volume_type', output)
+ expected_volume_type = dict(
+ name='new_type',
+ description='new_type_desc',
+ qos_specs_id='new_id',
+ extra_specs={},
+ is_public=True,
+ id=42,
+ )
+ self.assertDictMatch(expected_volume_type, output['volume_type'])
+
def test_view_builder_list(self):
view_builder = views_types.ViewBuilder()
"volume_extension:volume_actions:upload_image": "",
"volume_extension:types_manage": "",
"volume_extension:types_extra_specs": "",
+ "volume_extension:access_types_qos_specs_id": "rule:admin_api",
+ "volume_extension:access_types_extra_specs": "rule:admin_api",
"volume_extension:volume_type_access": "",
"volume_extension:volume_type_access:addProjectAccess": "rule:admin_api",
"volume_extension:volume_type_access:removeProjectAccess": "rule:admin_api",
"volume_extension:types_manage": "rule:admin_api",
"volume_extension:types_extra_specs": "rule:admin_api",
+ "volume_extension:access_types_qos_specs_id": "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",