Refactor authorize() method in wsgi.py

Almost every API method written in Manila performs
a policy check against relevant policies in etc/policy.json.
A method - authorize() was introduced in
manila/api/openstack/wsgi.py
in commit e4428f5e6c324a674c76f81340e1c94a956b4c6c
to perform these policy checks.

This patch refactors the authorize() method as a decorator
for consistency and easy usage in APIs that choose to
implement the policy check prior to any core logic.

Prior unit tests are modified for the APIs impacted through
this change.

The Cgsnapshots controller's policies are corrected for
name consistency without impacting behavior.

Change-Id: Ib34e166ab65513f8f02215c6569175fc9a913244
Closes-Bug: #1515397
This commit is contained in:
Goutham Pacha Ravi 2015-11-15 21:56:35 -05:00
parent fabadd9404
commit 379ee2f31c
33 changed files with 626 additions and 269 deletions

@ -97,13 +97,14 @@
"consistency_group:update": "rule:default",
"consistency_group:get": "rule:default",
"consistency_group:get_all": "rule:default",
"consistency_group:create_cgsnapshot" : "rule:default",
"consistency_group:delete_cgsnapshot": "rule:default",
"consistency_group:force_delete": "rule:admin_api",
"consistency_group:reset_status": "rule:admin_api",
"consistency_group:get_cgsnapshot": "rule:default",
"consistency_group:get_all_cgsnapshots": "rule:default",
"cgsnapshot:force_delete": "rule:admin_api",
"cgsnapshot:reset_status": "rule:admin_api"
"cgsnapshot:reset_status": "rule:admin_api",
"cgsnapshot:create" : "rule:default",
"cgsnapshot:update" : "rule:default",
"cgsnapshot:delete": "rule:default",
"cgsnapshot:get_cgsnapshot": "rule:default",
"cgsnapshot:get_all": "rule:default"
}

@ -1112,11 +1112,42 @@ class Controller(object):
return decorator
def authorize(self, context, action):
try:
policy.check_policy(context, self.resource_name, action)
except exception.PolicyNotAuthorized:
raise webob.exc.HTTPForbidden()
@staticmethod
def authorize(arg):
"""Decorator for checking the policy on API methods.
Add this decorator to any API method which takes a request object
as the first parameter and belongs to a class which inherits from
wsgi.Controller. The class must also have a class member called
'resource_name' which specifies the resource for the policy check.
Can be used in any of the following forms
@authorize
@authorize('my_action_name')
:param arg: Can either be the function being decorated or a str
containing the 'action' for the policy check. If no action name is
provided, the function name is assumed to be the action name.
"""
action_name = None
def decorator(f):
@functools.wraps(f)
def wrapper(self, req, *args, **kwargs):
action = action_name or f.__name__
context = req.environ['manila.context']
try:
policy.check_policy(context, self.resource_name, action)
except exception.PolicyNotAuthorized:
raise webob.exc.HTTPForbidden()
return f(self, req, *args, **kwargs)
return wrapper
if callable(arg):
return decorator(arg)
else:
action_name = arg
return decorator
@staticmethod
def is_valid_body(body, entity_name):
@ -1169,10 +1200,10 @@ class AdminActionsMixin(object):
return update
@action('os-reset_status')
@Controller.authorize('reset_status')
def _reset_status(self, req, id, body):
"""Reset status on the resource."""
context = req.environ['manila.context']
self.authorize(context, 'reset_status')
update = self.validate_update(body['os-reset_status'])
msg = "Updating %(resource)s '%(id)s' with '%(update)r'"
LOG.debug(msg, {'resource': self.resource_name, 'id': id,
@ -1184,10 +1215,10 @@ class AdminActionsMixin(object):
return webob.Response(status_int=202)
@action('os-force_delete')
@Controller.authorize('force_delete')
def _force_delete(self, req, id, body):
"""Delete a resource, bypassing the check for status."""
context = req.environ['manila.context']
self.authorize(context, 'force_delete')
try:
resource = self._get(context, id)
except exception.NotFound as e:

@ -24,8 +24,8 @@ class AvailabilityZoneController(wsgi.Controller):
resource_name = "availability_zone"
_view_builder_class = availability_zones_views.ViewBuilder
@wsgi.Controller.authorize
def index(self, req):
self.authorize(req.environ['manila.context'], 'index')
return self._index(req)
def _index(self, req):

@ -44,6 +44,7 @@ class CGSnapshotController(wsgi.Controller, wsgi.AdminActionsMixin):
self.cg_api = cg_api.API()
@wsgi.Controller.api_version('2.4', experimental=True)
@wsgi.Controller.authorize('get_cgsnapshot')
def show(self, req, id):
"""Return data about the given cgsnapshot."""
context = req.environ['manila.context']
@ -57,6 +58,7 @@ class CGSnapshotController(wsgi.Controller, wsgi.AdminActionsMixin):
return self._view_builder.detail(req, cg)
@wsgi.Controller.api_version('2.4', experimental=True)
@wsgi.Controller.authorize
def delete(self, req, id):
"""Delete a cgsnapshot."""
context = req.environ['manila.context']
@ -78,11 +80,13 @@ class CGSnapshotController(wsgi.Controller, wsgi.AdminActionsMixin):
return webob.Response(status_int=202)
@wsgi.Controller.api_version('2.4', experimental=True)
@wsgi.Controller.authorize('get_all')
def index(self, req):
"""Returns a summary list of cgsnapshots."""
return self._get_cgs(req, is_detail=False)
@wsgi.Controller.api_version('2.4', experimental=True)
@wsgi.Controller.authorize('get_all')
def detail(self, req):
"""Returns a detailed list of cgsnapshots."""
return self._get_cgs(req, is_detail=True)
@ -110,6 +114,7 @@ class CGSnapshotController(wsgi.Controller, wsgi.AdminActionsMixin):
return snaps
@wsgi.Controller.api_version('2.4', experimental=True)
@wsgi.Controller.authorize
def update(self, req, id, body):
"""Update a cgsnapshot."""
context = req.environ['manila.context']
@ -139,6 +144,7 @@ class CGSnapshotController(wsgi.Controller, wsgi.AdminActionsMixin):
@wsgi.Controller.api_version('2.4', experimental=True)
@wsgi.response(202)
@wsgi.Controller.authorize
def create(self, req, body):
"""Creates a new cgsnapshot."""
context = req.environ['manila.context']
@ -177,6 +183,7 @@ class CGSnapshotController(wsgi.Controller, wsgi.AdminActionsMixin):
new_snapshot)))
@wsgi.Controller.api_version('2.4', experimental=True)
@wsgi.Controller.authorize('get_cgsnapshot')
def members(self, req, id):
"""Returns a list of cgsnapshot members."""
context = req.environ['manila.context']

@ -39,12 +39,14 @@ class CGController(wsgi.Controller, wsgi.AdminActionsMixin):
resource_name = 'consistency_group'
_view_builder_class = cg_views.CGViewBuilder
resource_name = 'consistency_group'
def __init__(self):
super(CGController, self).__init__()
self.cg_api = cg_api.API()
@wsgi.Controller.api_version('2.4', experimental=True)
@wsgi.Controller.authorize('get')
def show(self, req, id):
"""Return data about the given CG."""
context = req.environ['manila.context']
@ -58,6 +60,7 @@ class CGController(wsgi.Controller, wsgi.AdminActionsMixin):
return self._view_builder.detail(req, cg)
@wsgi.Controller.api_version('2.4', experimental=True)
@wsgi.Controller.authorize
def delete(self, req, id):
"""Delete a CG."""
context = req.environ['manila.context']
@ -79,11 +82,13 @@ class CGController(wsgi.Controller, wsgi.AdminActionsMixin):
return webob.Response(status_int=202)
@wsgi.Controller.api_version('2.4', experimental=True)
@wsgi.Controller.authorize('get_all')
def index(self, req):
"""Returns a summary list of shares."""
return self._get_cgs(req, is_detail=False)
@wsgi.Controller.api_version('2.4', experimental=True)
@wsgi.Controller.authorize('get_all')
def detail(self, req):
"""Returns a detailed list of shares."""
return self._get_cgs(req, is_detail=True)
@ -111,6 +116,7 @@ class CGController(wsgi.Controller, wsgi.AdminActionsMixin):
return cgs
@wsgi.Controller.api_version('2.4', experimental=True)
@wsgi.Controller.authorize
def update(self, req, id, body):
"""Update a share."""
context = req.environ['manila.context']
@ -140,6 +146,7 @@ class CGController(wsgi.Controller, wsgi.AdminActionsMixin):
@wsgi.Controller.api_version('2.4', experimental=True)
@wsgi.response(202)
@wsgi.Controller.authorize
def create(self, req, body):
"""Creates a new share."""
context = req.environ['manila.context']

@ -30,9 +30,9 @@ class QuotaClassSetsController(wsgi.Controller):
resource_name = "quota_class_set"
_view_builder_class = quota_class_sets_views.ViewBuilder
@wsgi.Controller.authorize
def show(self, req, id):
context = req.environ['manila.context']
self.authorize(context, 'show')
try:
db.authorize_quota_class_context(context, id)
except exception.NotAuthorized:
@ -41,9 +41,9 @@ class QuotaClassSetsController(wsgi.Controller):
return self._view_builder.detail_list(
QUOTAS.get_class_quotas(context, id), id)
@wsgi.Controller.authorize
def update(self, req, id, body):
context = req.environ['manila.context']
self.authorize(context, 'update')
quota_class = id
for key in body.get(self.resource_name, {}).keys():
if key in QUOTAS:

@ -61,9 +61,9 @@ class QuotaSetsController(wsgi.Controller):
return values
return dict((k, v['limit']) for k, v in values.items())
@wsgi.Controller.authorize
def show(self, req, id):
context = req.environ['manila.context']
self.authorize(context, 'show')
params = parse.parse_qs(req.environ.get('QUERY_STRING', ''))
user_id = params.get('user_id', [None])[0]
try:
@ -73,14 +73,14 @@ class QuotaSetsController(wsgi.Controller):
except exception.NotAuthorized:
raise webob.exc.HTTPForbidden()
@wsgi.Controller.authorize('show')
def defaults(self, req, id):
context = req.environ['manila.context']
self.authorize(context, 'show')
return self._view_builder.detail_list(QUOTAS.get_defaults(context), id)
@wsgi.Controller.authorize
def update(self, req, id, body):
context = req.environ['manila.context']
self.authorize(context, 'update')
project_id = id
bad_keys = []
force_update = False
@ -166,9 +166,9 @@ class QuotaSetsController(wsgi.Controller):
return self._view_builder.detail_list(
self._get_quotas(context, id, user_id=user_id))
@wsgi.Controller.authorize
def delete(self, req, id):
context = req.environ['manila.context']
self.authorize(context, 'update')
params = parse.parse_qs(req.environ.get('QUERY_STRING', ''))
user_id = params.get('user_id', [None])[0]
try:

@ -164,7 +164,7 @@ class APIRouter(manila.api.openstack.APIRouter):
member={'action': 'POST'})
self.resources['share_servers'] = share_servers.create_resource()
mapper.resource(share_servers.RESOURCE_NAME,
mapper.resource('share_server',
'share-servers',
controller=self.resources['share_servers'])
mapper.connect('details',

@ -16,32 +16,33 @@ from oslo_log import log
from manila.api.openstack import wsgi
from manila.api.views import scheduler_stats as scheduler_stats_views
from manila import policy
from manila.scheduler import rpcapi
POOLS_RESOURCES_NAME = 'scheduler_stats:pools'
LOG = log.getLogger(__name__)
class SchedulerStatsController(wsgi.Controller):
"""The Scheduler Stats API controller for the OpenStack API."""
resource_name = 'scheduler_stats:pools'
def __init__(self):
self.scheduler_api = rpcapi.SchedulerAPI()
self._view_builder_class = scheduler_stats_views.ViewBuilder
super(SchedulerStatsController, self).__init__()
@wsgi.Controller.authorize('index')
def pools_index(self, req):
"""Returns a list of storage pools known to the scheduler."""
return self._pools(req, action='index')
@wsgi.Controller.authorize('detail')
def pools_detail(self, req):
"""Returns a detailed list of storage pools known to the scheduler."""
return self._pools(req, action='detail')
def _pools(self, req, action='index'):
context = req.environ['manila.context']
policy.check_policy(context, POOLS_RESOURCES_NAME, action)
search_opts = {}
search_opts.update(req.GET)
pools = self.scheduler_api.get_pools(context, filters=search_opts)

@ -31,11 +31,11 @@ class ServiceController(wsgi.Controller):
resource_name = "service"
_view_builder_class = services_views.ViewBuilder
@wsgi.Controller.authorize
def index(self, req):
"""Return a list of all running services."""
context = req.environ['manila.context']
self.authorize(context, 'index')
all_services = db.service_get_all(context)
services = []
@ -68,10 +68,10 @@ class ServiceController(wsgi.Controller):
return self._view_builder.detail_list(services)
@wsgi.Controller.authorize
def update(self, req, id, body):
"""Enable/Disable scheduling for a service."""
context = req.environ['manila.context']
self.authorize(context, 'update')
if id == "enable":
data = {'disabled': False}

@ -42,17 +42,17 @@ class ShareInstancesController(wsgi.Controller, wsgi.AdminActionsMixin):
return self.share_api.delete_instance(*args, **kwargs)
@wsgi.Controller.api_version("2.3")
@wsgi.Controller.authorize
def index(self, req):
context = req.environ['manila.context']
self.authorize(context, 'index')
instances = db.share_instances_get_all(context)
return self._view_builder.detail_list(req, instances)
@wsgi.Controller.api_version("2.3")
@wsgi.Controller.authorize
def show(self, req, id):
context = req.environ['manila.context']
self.authorize(context, 'show')
try:
instance = db.share_instance_get(context, id)
@ -62,9 +62,9 @@ class ShareInstancesController(wsgi.Controller, wsgi.AdminActionsMixin):
return self._view_builder.detail(req, instance)
@wsgi.Controller.api_version("2.3")
@wsgi.Controller.authorize('index')
def get_share_instances(self, req, share_id):
context = req.environ['manila.context']
self.authorize(context, 'index')
try:
share = self.share_api.get(context, share_id)

@ -35,11 +35,11 @@ class ShareManageController(wsgi.Controller):
super(self.__class__, self).__init__(*args, **kwargs)
self.share_api = share.API()
@wsgi.Controller.authorize('manage')
def create(self, req, body):
# TODO(vponomaryov): move it to shares controller.
context = req.environ['manila.context']
self.authorize(req.environ['manila.context'], 'manage')
share_data = self._validate_manage_parameters(context, body)
# NOTE(vponomaryov): compatibility actions are required between API and
@ -98,6 +98,8 @@ class ShareManageController(wsgi.Controller):
raise exc.HTTPNotFound(explanation=six.text_type(e))
except exception.PolicyNotAuthorized as e:
raise exc.HTTPForbidden(explanation=six.text_type(e))
except exception.AdminRequired as e:
raise exc.HTTPForbidden(explanation=six.text_type(e))
except exception.ServiceIsDown as e:
raise exc.HTTPBadRequest(explanation=six.text_type(e))

@ -24,11 +24,8 @@ from manila.common import constants
from manila.db import api as db_api
from manila import exception
from manila.i18n import _
from manila import policy
from manila import share
RESOURCE_NAME = 'share_server'
RESOURCES_NAME = 'share_servers'
LOG = log.getLogger(__name__)
@ -38,13 +35,14 @@ class ShareServerController(wsgi.Controller):
def __init__(self):
self.share_api = share.API()
self._view_builder_class = share_servers_views.ViewBuilder
self.resource_name = 'share_server'
super(ShareServerController, self).__init__()
@wsgi.Controller.authorize
def index(self, req):
"""Returns a list of share servers."""
context = req.environ['manila.context']
policy.check_policy(context, RESOURCE_NAME, 'index')
search_opts = {}
search_opts.update(req.GET)
@ -65,10 +63,10 @@ class ShareServerController(wsgi.Controller):
s.share_network['id']])]
return self._view_builder.build_share_servers(share_servers)
@wsgi.Controller.authorize
def show(self, req, id):
"""Return data about the requested share server."""
context = req.environ['manila.context']
policy.check_policy(context, RESOURCE_NAME, 'show')
try:
server = db_api.share_server_get(context, id)
server.project_id = server.share_network["project_id"]
@ -80,10 +78,10 @@ class ShareServerController(wsgi.Controller):
raise exc.HTTPNotFound(explanation=six.text_type(e))
return self._view_builder.build_share_server(server)
@wsgi.Controller.authorize
def details(self, req, id):
"""Return details for requested share server."""
context = req.environ['manila.context']
policy.check_policy(context, RESOURCE_NAME, 'details')
try:
share_server = db_api.share_server_get(context, id)
except exception.ShareServerNotFound as e:
@ -92,10 +90,10 @@ class ShareServerController(wsgi.Controller):
return self._view_builder.build_share_server_details(
share_server['backend_details'])
@wsgi.Controller.authorize
def delete(self, req, id):
"""Delete specified share server."""
context = req.environ['manila.context']
policy.check_policy(context, RESOURCE_NAME, 'delete')
try:
share_server = db_api.share_server_get(context, id)
except exception.ShareServerNotFound as e:

@ -25,7 +25,6 @@ from manila.api.openstack import wsgi
from manila.api.views import types as views_types
from manila import exception
from manila.i18n import _
from manila import policy
from manila import rpc
from manila.share import share_types
@ -54,20 +53,18 @@ class ShareTypesController(wsgi.Controller):
"project is not in proper format (%s)") % project
raise webob.exc.HTTPBadRequest(explanation=msg)
@wsgi.Controller.authorize
def index(self, req):
"""Returns the list of share types."""
context = req.environ['manila.context']
policy.check_policy(context, self.resource_name, 'index')
limited_types = self._get_share_types(req)
req.cache_db_share_types(limited_types)
return self._view_builder.index(req, limited_types)
@wsgi.Controller.authorize
def show(self, req, id):
"""Return a single share type item."""
context = req.environ['manila.context']
policy.check_policy(context, self.resource_name, 'show')
try:
share_type = share_types.get_share_type(context, id)
except exception.NotFound:
@ -78,10 +75,10 @@ class ShareTypesController(wsgi.Controller):
req.cache_db_share_type(share_type)
return self._view_builder.show(req, share_type)
@wsgi.Controller.authorize
def default(self, req):
"""Return default volume type."""
context = req.environ['manila.context']
policy.check_policy(context, self.resource_name, 'default')
try:
share_type = share_types.get_default_share_type(context)
@ -131,10 +128,10 @@ class ShareTypesController(wsgi.Controller):
raise exc.HTTPBadRequest(explanation=msg)
@wsgi.action("create")
@wsgi.Controller.authorize('create')
def _create(self, req, body):
"""Creates a new share type."""
context = req.environ['manila.context']
self.authorize(context, 'create')
if not self.is_valid_body(body, 'share_type') and \
not self.is_valid_body(body, 'volume_type'):
@ -185,10 +182,10 @@ class ShareTypesController(wsgi.Controller):
return self._view_builder.show(req, share_type)
@wsgi.action("delete")
@wsgi.Controller.authorize('delete')
def _delete(self, req, id):
"""Deletes an existing share type."""
context = req.environ['manila.context']
self.authorize(context, 'delete')
try:
share_type = share_types.get_share_type(context, id)
@ -211,9 +208,9 @@ class ShareTypesController(wsgi.Controller):
return webob.Response(status_int=202)
@wsgi.Controller.authorize('list_project_access')
def _list_project_access(self, req, id):
context = req.environ['manila.context']
self.authorize(context, 'list_project_access')
try:
share_type = share_types.get_share_type(
@ -235,9 +232,9 @@ class ShareTypesController(wsgi.Controller):
return {'share_type_access': rval}
@wsgi.action('addProjectAccess')
@wsgi.Controller.authorize('add_project_access')
def _add_project_access(self, req, id, body):
context = req.environ['manila.context']
self.authorize(context, 'add_project_access')
self._check_body(body, 'addProjectAccess')
project = body['addProjectAccess']['project']
@ -259,9 +256,9 @@ class ShareTypesController(wsgi.Controller):
return webob.Response(status_int=202)
@wsgi.action('removeProjectAccess')
@wsgi.Controller.authorize('remove_project_access')
def _remove_project_access(self, req, id, body):
context = req.environ['manila.context']
self.authorize(context, 'remove_project_access')
self._check_body(body, 'removeProjectAccess')
project = body['removeProjectAccess']['project']

@ -71,16 +71,16 @@ class ShareTypeExtraSpecsController(wsgi.Controller):
}
raise webob.exc.HTTPBadRequest(explanation=expl)
@wsgi.Controller.authorize
def index(self, req, type_id):
"""Returns the list of extra specs for a given share type."""
context = req.environ['manila.context']
self.authorize(context, 'index')
self._check_type(context, type_id)
return self._get_extra_specs(context, type_id)
@wsgi.Controller.authorize
def create(self, req, type_id, body=None):
context = req.environ['manila.context']
self.authorize(context, 'create')
if not self.is_valid_body(body, 'extra_specs'):
raise webob.exc.HTTPBadRequest()
@ -95,9 +95,9 @@ class ShareTypeExtraSpecsController(wsgi.Controller):
notifier.info(context, 'share_type_extra_specs.create', notifier_info)
return body
@wsgi.Controller.authorize
def update(self, req, type_id, id, body=None):
context = req.environ['manila.context']
self.authorize(context, 'update')
if not body:
expl = _('Request body empty')
raise webob.exc.HTTPBadRequest(explanation=expl)
@ -115,10 +115,10 @@ class ShareTypeExtraSpecsController(wsgi.Controller):
notifier.info(context, 'share_type_extra_specs.update', notifier_info)
return body
@wsgi.Controller.authorize
def show(self, req, type_id, id):
"""Return a single extra spec item."""
context = req.environ['manila.context']
self.authorize(context, 'show')
self._check_type(context, type_id)
specs = self._get_extra_specs(context, type_id)
if id in specs['extra_specs']:
@ -126,11 +126,11 @@ class ShareTypeExtraSpecsController(wsgi.Controller):
else:
raise webob.exc.HTTPNotFound()
@wsgi.Controller.authorize
def delete(self, req, type_id, id):
"""Deletes an existing extra spec."""
context = req.environ['manila.context']
self._check_type(context, type_id)
self.authorize(context, 'delete')
if id in share_types.get_undeletable_extra_specs():
msg = _("Extra spec '%s' can't be deleted.") % id

@ -36,11 +36,11 @@ class ShareUnmanageController(wsgi.Controller):
self.share_api = share.API()
@wsgi.action("unmanage")
@wsgi.Controller.authorize
def unmanage(self, req, id):
"""Unmanage a share."""
# TODO(vponomaryov): move it to shares controller as 'unmanage' action.
context = req.environ['manila.context']
self.authorize(req.environ['manila.context'], 'unmanage')
LOG.info(_LI("Unmanage share with id: %s"), id, context=context)

@ -27,7 +27,6 @@ from manila.common import constants
from manila.db import base
from manila import exception
from manila.i18n import _
from manila import policy
from manila.scheduler import rpcapi as scheduler_rpcapi
from manila import share
from manila.share import rpcapi as share_rpcapi
@ -52,7 +51,6 @@ class API(base.Base):
share_type_ids=None, source_cgsnapshot_id=None,
share_network_id=None):
"""Create new consistency group."""
policy.check_policy(context, 'consistency_group', 'create')
cgsnapshot = None
original_cg = None
@ -164,7 +162,6 @@ class API(base.Base):
return cg
@policy.wrap_check_policy('consistency_group')
def delete(self, context, cg):
"""Delete consistency group."""
@ -194,16 +191,13 @@ class API(base.Base):
self.share_rpcapi.delete_consistency_group(context, cg)
@policy.wrap_check_policy('consistency_group')
def update(self, context, cg, fields):
return self.db.consistency_group_update(context, cg['id'], fields)
def get(self, context, cg_id):
policy.check_policy(context, 'consistency_group', 'get')
return self.db.consistency_group_get(context, cg_id)
def get_all(self, context, detailed=True, search_opts=None):
policy.check_policy(context, 'consistency_group', 'get_all')
if search_opts is None:
search_opts = {}
@ -224,7 +218,6 @@ class API(base.Base):
def create_cgsnapshot(self, context, name=None, description=None,
consistency_group_id=None):
"""Create new cgsnapshot."""
policy.check_policy(context, 'consistency_group', 'create_cgsnapshot')
options = {
'consistency_group_id': consistency_group_id,
@ -285,7 +278,6 @@ class API(base.Base):
return snap
@policy.wrap_check_policy('consistency_group')
def delete_cgsnapshot(self, context, snap):
"""Delete consistency group snapshot."""
@ -307,17 +299,13 @@ class API(base.Base):
# Cast to share manager
self.share_rpcapi.delete_cgsnapshot(context, snap, cg['host'])
@policy.wrap_check_policy('consistency_group')
def update_cgsnapshot(self, context, cg, fields):
return self.db.cgsnapshot_update(context, cg['id'], fields)
def get_cgsnapshot(self, context, snapshot_id):
policy.check_policy(context, 'consistency_group', 'get_cgsnapshot')
return self.db.cgsnapshot_get(context, snapshot_id)
def get_all_cgsnapshots(self, context, detailed=True, search_opts=None):
policy.check_policy(context, 'consistency_group',
'get_all_cgsnapshots')
if search_opts is None:
search_opts = {}
@ -336,7 +324,6 @@ class API(base.Base):
return cgsnapshots
def get_all_cgsnapshot_members(self, context, cgsnapshot_id):
policy.check_policy(context, 'consistency_group', 'get_cgsnapshot')
members = self.db.cgsnapshot_members_get_all(context,
cgsnapshot_id)

@ -32,6 +32,7 @@ from manila.api.v1 import router
from manila.api import versions
from manila.common import constants
from manila import context
from manila import exception
from manila import wsgi
@ -202,3 +203,10 @@ fixture_invalid_reset_status_body = (
{'os-reset_status': {'x-status': 'bad'}},
{'os-reset_status': {'status': 'invalid'}}
)
def mock_fake_admin_check(context, resource_name, action, *args, **kwargs):
if context.is_admin:
return
else:
raise exception.PolicyNotAuthorized(action=action)

@ -1,10 +1,13 @@
import ddt
import inspect
import mock
import six
import webob
from manila.api.openstack import wsgi
from manila import context
from manila import exception
from manila import policy
from manila import test
from manila.tests.api import fakes
@ -865,3 +868,50 @@ class ValidBodyTest(test.TestCase):
def test_is_valid_body_malformed_entity(self):
body = {'foo': 'bar'}
self.assertFalse(self.controller.is_valid_body(body, 'foo'))
class AuthorizeDecoratorTest(test.TestCase):
class FakeController(wsgi.Controller):
resource_name = 'fake_resource_name'
@wsgi.Controller.authorize
def fake_action_1(self, req):
pass
@wsgi.Controller.authorize('fake_action')
def fake_action_2(self, req):
pass
def setUp(self):
super(AuthorizeDecoratorTest, self).setUp()
self.controller = self.FakeController()
self.admin_context = context.get_admin_context()
self.user_context = fakes.FakeRequestContext
self.mock_policy_check = self.mock_object(policy, 'check_policy')
def test_authorize_decorator_no_args(self):
req = fakes.HTTPRequest.blank('/v2/fake/fake_id')
req.environ['manila.context'] = self.user_context
self.controller.fake_action_1(req)
self.mock_policy_check.assert_called_once_with(
self.user_context, self.controller.resource_name, 'fake_action_1')
def test_authorize_decorator_action_name(self):
req = fakes.HTTPRequest.blank('/v2/fake/fake_id')
req.environ['manila.context'] = self.admin_context
self.controller.fake_action_2(req)
self.mock_policy_check.assert_called_once_with(
self.admin_context, self.controller.resource_name, 'fake_action')
def test_authorize_exception(self):
req = fakes.HTTPRequest.blank('/v2/fake/fake_id')
req.environ['manila.context'] = self.admin_context
exc = exception.PolicyNotAuthorized(action='fake_action')
with mock.patch.object(policy, 'check_policy',
mock.Mock(side_effect=exc)):
self.assertRaises(webob.exc.HTTPForbidden,
self.controller.fake_action_2, req)

@ -17,6 +17,7 @@ import mock
from manila.api.v1 import availability_zones
from manila import context
from manila import policy
from manila import test
from manila.tests.api import fakes
@ -50,6 +51,7 @@ class AvailabilityZonesAPITest(test.TestCase):
"redundant_key": "redundant_value",
},
]
mock_policy_check = self.mock_object(policy, 'check_policy')
self.mock_object(availability_zones.db, 'availability_zone_get_all',
mock.Mock(return_value=azs))
controller = availability_zones.AvailabilityZoneController()
@ -61,6 +63,8 @@ class AvailabilityZonesAPITest(test.TestCase):
availability_zones.db.availability_zone_get_all.\
assert_called_once_with(ctxt)
mock_policy_check.assert_called_once_with(
ctxt, controller.resource_name, 'index')
self.assertTrue(isinstance(result, dict))
self.assertEqual(["availability_zones"], list(result.keys()))
self.assertTrue(isinstance(result["availability_zones"], list))

@ -30,6 +30,7 @@ from manila.common import constants
from manila import context
from manila import db
from manila import exception
from manila import policy
from manila import test
from manila.tests.api import fakes
from manila.tests import db_utils
@ -43,10 +44,14 @@ class CGSnapshotApiTest(test.TestCase):
def setUp(self):
super(self.__class__, self).setUp()
self.controller = cgs.CGSnapshotController()
self.resource_name = self.controller.resource_name
self.api_version = '2.4'
self.mock_policy_check = self.mock_object(
policy, 'check_policy', mock.Mock(return_value=True))
self.request = fakes.HTTPRequest.blank('/consistency-groups',
version=self.api_version,
experimental=True)
self.context = self.request.environ['manila.context']
self.admin_context = context.RequestContext('admin', 'fake', True)
self.member_context = context.RequestContext('fake', 'fake')
self.flags(rpc_backend='manila.openstack.common.rpc.impl_fake')
@ -108,11 +113,15 @@ class CGSnapshotApiTest(test.TestCase):
body = {"not_cg_snapshot": {}}
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
self.request, body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_create_no_consistency_group_id(self):
body = {"cgnapshot": {}}
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
self.request, body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_create(self):
fake_snap, expected_snap = self._get_fake_cgsnapshot()
@ -121,11 +130,13 @@ class CGSnapshotApiTest(test.TestCase):
mock.Mock(return_value=fake_snap))
body = {"cgsnapshot": {"consistency_group_id": fake_id}}
context = self.request.environ['manila.context']
res_dict = self.controller.create(self.request, body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
self.controller.cg_api.create_cgsnapshot.assert_called_once_with(
context, consistency_group_id=fake_id)
self.context, consistency_group_id=fake_id)
self.assertEqual(expected_snap, res_dict['cgsnapshot'])
def test_create_cg_does_not_exist(self):
@ -140,6 +151,8 @@ class CGSnapshotApiTest(test.TestCase):
body = {"cgsnapshot": {"consistency_group_id": fake_id}}
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
self.request, body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_create_cg_does_not_a_uuid(self):
self.mock_object(self.controller.cg_api, 'create_cgsnapshot',
@ -151,6 +164,8 @@ class CGSnapshotApiTest(test.TestCase):
body = {"cgsnapshot": {"consistency_group_id": "not_a_uuid"}}
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
self.request, body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_create_invalid_cg(self):
fake_id = six.text_type(uuid.uuid4())
@ -163,6 +178,8 @@ class CGSnapshotApiTest(test.TestCase):
body = {"cgsnapshot": {"consistency_group_id": fake_id}}
self.assertRaises(webob.exc.HTTPConflict, self.controller.create,
self.request, body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_create_with_name(self):
fake_name = 'fake_name'
@ -173,12 +190,13 @@ class CGSnapshotApiTest(test.TestCase):
body = {"cgsnapshot": {"consistency_group_id": fake_id,
"name": fake_name}}
context = self.request.environ['manila.context']
res_dict = self.controller.create(self.request, body)
self.controller.cg_api.create_cgsnapshot.assert_called_once_with(
context, consistency_group_id=fake_id, name=fake_name)
self.context, consistency_group_id=fake_id, name=fake_name)
self.assertEqual(expected_snap, res_dict['cgsnapshot'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_create_with_description(self):
fake_description = 'fake_description'
@ -190,13 +208,14 @@ class CGSnapshotApiTest(test.TestCase):
body = {"cgsnapshot": {"consistency_group_id": fake_id,
"description": fake_description}}
context = self.request.environ['manila.context']
res_dict = self.controller.create(self.request, body)
self.controller.cg_api.create_cgsnapshot.assert_called_once_with(
context, consistency_group_id=fake_id,
self.context, consistency_group_id=fake_id,
description=fake_description)
self.assertEqual(expected_snap, res_dict['cgsnapshot'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_create_with_name_and_description(self):
fake_name = 'fake_name'
@ -210,13 +229,14 @@ class CGSnapshotApiTest(test.TestCase):
body = {"cgsnapshot": {"consistency_group_id": fake_id,
"description": fake_description,
"name": fake_name}}
context = self.request.environ['manila.context']
res_dict = self.controller.create(self.request, body)
self.controller.cg_api.create_cgsnapshot.assert_called_once_with(
context, consistency_group_id=fake_id, name=fake_name,
self.context, consistency_group_id=fake_id, name=fake_name,
description=fake_description)
self.assertEqual(expected_snap, res_dict['cgsnapshot'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_update_with_name_and_description(self):
fake_name = 'fake_name'
@ -231,13 +251,14 @@ class CGSnapshotApiTest(test.TestCase):
body = {"cgsnapshot": {"description": fake_description,
"name": fake_name}}
context = self.request.environ['manila.context']
res_dict = self.controller.update(self.request, fake_id, body)
self.controller.cg_api.update_cgsnapshot.assert_called_once_with(
context, fake_snap,
self.context, fake_snap,
dict(name=fake_name, description=fake_description))
self.assertEqual(expected_snap, res_dict['cgsnapshot'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'update')
def test_update_snapshot_not_found(self):
body = {"cgsnapshot": {}}
@ -246,12 +267,16 @@ class CGSnapshotApiTest(test.TestCase):
self.assertRaises(webob.exc.HTTPNotFound,
self.controller.update,
self.request, 'fake_id', body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'update')
def test_update_invalid_body(self):
body = {"not_cgsnapshot": {}}
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.update,
self.request, 'fake_id', body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'update')
def test_update_invalid_body_invalid_field(self):
body = {"cgsnapshot": {"unknown_field": ""}}
@ -259,6 +284,8 @@ class CGSnapshotApiTest(test.TestCase):
self.controller.update,
self.request, 'fake_id', body)
self.assertTrue('unknown_field' in six.text_type(exc))
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'update')
def test_update_invalid_body_readonly_field(self):
body = {"cgsnapshot": {"created_at": []}}
@ -266,6 +293,8 @@ class CGSnapshotApiTest(test.TestCase):
self.controller.update,
self.request, 'fake_id', body)
self.assertTrue('created_at' in six.text_type(exc))
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'update')
def test_list_index(self):
fake_snap, expected_snap = self._get_fake_simple_cgsnapshot()
@ -273,12 +302,16 @@ class CGSnapshotApiTest(test.TestCase):
mock.Mock(return_value=[fake_snap]))
res_dict = self.controller.index(self.request)
self.assertEqual([expected_snap], res_dict['cgsnapshots'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'get_all')
def test_list_index_no_cgs(self):
self.mock_object(self.controller.cg_api, 'get_all_cgsnapshots',
mock.Mock(return_value=[]))
res_dict = self.controller.index(self.request)
self.assertEqual([], res_dict['cgsnapshots'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'get_all')
def test_list_index_with_limit(self):
fake_snap, expected_snap = self._get_fake_simple_cgsnapshot()
@ -289,9 +322,14 @@ class CGSnapshotApiTest(test.TestCase):
req = fakes.HTTPRequest.blank('/cgsnapshots?limit=1',
version=self.api_version,
experimental=True)
req_context = req.environ['manila.context']
res_dict = self.controller.index(req)
self.assertEqual(1, len(res_dict['cgsnapshots']))
self.assertEqual([expected_snap], res_dict['cgsnapshots'])
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'get_all')
def test_list_index_with_limit_and_offset(self):
fake_snap, expected_snap = self._get_fake_simple_cgsnapshot()
@ -302,11 +340,14 @@ class CGSnapshotApiTest(test.TestCase):
req = fakes.HTTPRequest.blank('/cgsnapshots?limit=1&offset=1',
version=self.api_version,
experimental=True)
req_context = req.environ['manila.context']
res_dict = self.controller.index(req)
self.assertEqual(1, len(res_dict['cgsnapshots']))
self.assertEqual([expected_snap2], res_dict['cgsnapshots'])
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'get_all')
def test_list_detail(self):
fake_snap, expected_snap = self._get_fake_cgsnapshot()
@ -314,12 +355,16 @@ class CGSnapshotApiTest(test.TestCase):
mock.Mock(return_value=[fake_snap]))
res_dict = self.controller.detail(self.request)
self.assertEqual([expected_snap], res_dict['cgsnapshots'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'get_all')
def test_list_detail_no_cgs(self):
self.mock_object(self.controller.cg_api, 'get_all_cgsnapshots',
mock.Mock(return_value=[]))
res_dict = self.controller.detail(self.request)
self.assertEqual([], res_dict['cgsnapshots'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'get_all')
def test_list_detail_with_limit(self):
fake_snap, expected_snap = self._get_fake_cgsnapshot()
@ -330,9 +375,14 @@ class CGSnapshotApiTest(test.TestCase):
req = fakes.HTTPRequest.blank('/cgsnapshots?limit=1',
version=self.api_version,
experimental=True)
req_context = req.environ['manila.context']
res_dict = self.controller.detail(req)
self.assertEqual(1, len(res_dict['cgsnapshots']))
self.assertEqual([expected_snap], res_dict['cgsnapshots'])
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'get_all')
def test_list_detail_with_limit_and_offset(self):
fake_snap, expected_snap = self._get_fake_cgsnapshot()
@ -343,11 +393,14 @@ class CGSnapshotApiTest(test.TestCase):
req = fakes.HTTPRequest.blank('/cgsnapshots?limit=1&offset=1',
version=self.api_version,
experimental=True)
req_context = req.environ['manila.context']
res_dict = self.controller.detail(req)
self.assertEqual(1, len(res_dict['cgsnapshots']))
self.assertEqual([expected_snap2], res_dict['cgsnapshots'])
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'get_all')
def test_delete(self):
fake_snap, expected_snap = self._get_fake_cgsnapshot()
@ -358,6 +411,8 @@ class CGSnapshotApiTest(test.TestCase):
res = self.controller.delete(self.request, fake_snap['id'])
self.assertEqual(202, res.status_code)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'delete')
def test_delete_not_found(self):
fake_snap, expected_snap = self._get_fake_cgsnapshot()
@ -366,6 +421,8 @@ class CGSnapshotApiTest(test.TestCase):
self.assertRaises(webob.exc.HTTPNotFound, self.controller.delete,
self.request, fake_snap['id'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'delete')
def test_delete_in_conflicting_status(self):
fake_snap, expected_snap = self._get_fake_cgsnapshot()
@ -378,6 +435,8 @@ class CGSnapshotApiTest(test.TestCase):
self.assertRaises(webob.exc.HTTPConflict, self.controller.delete,
self.request, fake_snap['id'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'delete')
def test_show(self):
fake_snap, expected_snap = self._get_fake_cgsnapshot()
@ -387,6 +446,8 @@ class CGSnapshotApiTest(test.TestCase):
res_dict = self.controller.show(self.request, fake_snap['id'])
self.assertEqual(expected_snap, res_dict['cgsnapshot'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'get_cgsnapshot')
def test_show_cg_not_found(self):
fake_snap, expected_snap = self._get_fake_cgsnapshot()
@ -395,19 +456,29 @@ class CGSnapshotApiTest(test.TestCase):
self.assertRaises(webob.exc.HTTPNotFound, self.controller.show,
self.request, fake_snap['id'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'get_cgsnapshot')
def test_members_empty(self):
self.mock_object(self.controller.cg_api, 'get_all_cgsnapshot_members',
mock.Mock(return_value=[]))
res_dict = self.controller.members(self.request, 'fake_cg_id')
self.assertEqual([], res_dict['cgsnapshot_members'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'get_cgsnapshot')
def test_members(self):
fake_member, expected_member = self._get_fake_cgsnapshot_member()
self.mock_object(self.controller.cg_api, 'get_all_cgsnapshot_members',
mock.Mock(return_value=[fake_member]))
res_dict = self.controller.members(self.request, 'fake_cg_id')
self.assertEqual([expected_member], res_dict['cgsnapshot_members'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'get_cgsnapshot')
def test_members_with_limit(self):
fake_member, expected_member = self._get_fake_cgsnapshot_member()
@ -418,8 +489,13 @@ class CGSnapshotApiTest(test.TestCase):
req = fakes.HTTPRequest.blank('/members?limit=1',
version=self.api_version,
experimental=True)
req_context = req.environ['manila.context']
res_dict = self.controller.members(req, 'fake_cg_id')
self.assertEqual(1, len(res_dict['cgsnapshot_members']))
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'get_cgsnapshot')
def test_members_with_limit_and_offset(self):
fake_member, expected_member = self._get_fake_cgsnapshot_member()
@ -430,11 +506,14 @@ class CGSnapshotApiTest(test.TestCase):
req = fakes.HTTPRequest.blank('/members?limit=1&offset=1',
version=self.api_version,
experimental=True)
req_context = req.environ['manila.context']
res_dict = self.controller.members(req, 'fake_cg_id')
self.assertEqual(1, len(res_dict['cgsnapshot_members']))
self.assertEqual([expected_member2], res_dict['cgsnapshot_members'])
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'get_cgsnapshot')
def _get_context(self, role):
return getattr(self, '%s_context' % role)
@ -460,7 +539,9 @@ class CGSnapshotApiTest(test.TestCase):
req.body = six.b(jsonutils.dumps({'os-force_delete': {}}))
req.environ['manila.context'] = ctxt
resp = req.get_response(fakes.app())
with mock.patch.object(
policy, 'check_policy', fakes.mock_fake_admin_check):
resp = req.get_response(fakes.app())
# Validate response
self.assertEqual(resp_code, resp.status_int)
@ -477,7 +558,9 @@ class CGSnapshotApiTest(test.TestCase):
req.body = six.b(jsonutils.dumps(body))
req.environ['manila.context'] = ctxt
resp = req.get_response(fakes.app())
with mock.patch.object(
policy, 'check_policy', fakes.mock_fake_admin_check):
resp = req.get_response(fakes.app())
# Validate response code and model status
self.assertEqual(valid_code, resp.status_int)

@ -31,6 +31,7 @@ import manila.consistency_group.api as cg_api
from manila import context
from manila import db
from manila import exception
from manila import policy
from manila.share import share_types
from manila import test
from manila.tests.api import fakes
@ -47,6 +48,7 @@ class CGApiTest(test.TestCase):
def setUp(self):
super(self.__class__, self).setUp()
self.controller = cgs.CGController()
self.resource_name = self.controller.resource_name
self.fake_share_type = {'id': six.text_type(uuid.uuid4())}
self.api_version = '2.4'
self.request = fakes.HTTPRequest.blank('/consistency-groups',
@ -55,6 +57,9 @@ class CGApiTest(test.TestCase):
self.flags(rpc_backend='manila.openstack.common.rpc.impl_fake')
self.admin_context = context.RequestContext('admin', 'fake', True)
self.member_context = context.RequestContext('fake', 'fake')
self.mock_policy_check = self.mock_object(
policy, 'check_policy', mock.Mock(return_value=True))
self.context = self.request.environ['manila.context']
def _get_context(self, role):
return getattr(self, '%s_context' % role)
@ -121,6 +126,8 @@ class CGApiTest(test.TestCase):
self.controller.cg_api.create.assert_called_once_with(
context, share_type_ids=[self.fake_share_type['id']])
self.assertEqual(expected_cg, res_dict['consistency_group'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_cg_create_invalid_cgsnapshot_state(self):
fake_snap_id = six.text_type(uuid.uuid4())
@ -132,6 +139,8 @@ class CGApiTest(test.TestCase):
body = {"consistency_group": {"source_cgsnapshot_id": fake_snap_id}}
self.assertRaises(webob.exc.HTTPConflict,
self.controller.create, self.request, body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_cg_create_no_default_share_type(self):
fake_cg, expected_cg = self._get_fake_cg()
@ -143,6 +152,8 @@ class CGApiTest(test.TestCase):
body = {"consistency_group": {}}
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
self.request, body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_cg_create_with_name(self):
fake_name = 'fake_name'
@ -153,13 +164,15 @@ class CGApiTest(test.TestCase):
mock.Mock(return_value=fake_cg))
body = {"consistency_group": {"name": fake_name}}
context = self.request.environ['manila.context']
res_dict = self.controller.create(self.request, body)
self.controller.cg_api.create.assert_called_once_with(
context, name=fake_name,
self.context, name=fake_name,
share_type_ids=[self.fake_share_type['id']])
self.assertEqual(expected_cg, res_dict['consistency_group'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_cg_create_with_description(self):
fake_description = 'fake_description'
@ -170,13 +183,15 @@ class CGApiTest(test.TestCase):
mock.Mock(return_value=fake_cg))
body = {"consistency_group": {"description": fake_description}}
context = self.request.environ['manila.context']
res_dict = self.controller.create(self.request, body)
self.controller.cg_api.create.assert_called_once_with(
context, description=fake_description,
self.context, description=fake_description,
share_type_ids=[self.fake_share_type['id']])
self.assertEqual(expected_cg, res_dict['consistency_group'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_cg_create_with_share_types(self):
fake_share_types = [{"share_type_id": self.fake_share_type['id']}]
@ -186,12 +201,13 @@ class CGApiTest(test.TestCase):
body = {"consistency_group": {
"share_types": [self.fake_share_type['id']]}}
context = self.request.environ['manila.context']
res_dict = self.controller.create(self.request, body)
self.controller.cg_api.create.assert_called_once_with(
context, share_type_ids=[self.fake_share_type['id']])
self.context, share_type_ids=[self.fake_share_type['id']])
self.assertEqual(expected_cg, res_dict['consistency_group'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_cg_create_with_source_cgsnapshot_id(self):
fake_snap_id = six.text_type(uuid.uuid4())
@ -205,12 +221,14 @@ class CGApiTest(test.TestCase):
body = {"consistency_group": {
"source_cgsnapshot_id": fake_snap_id}}
context = self.request.environ['manila.context']
res_dict = self.controller.create(self.request, body)
self.controller.cg_api.create.assert_called_once_with(
context, source_cgsnapshot_id=fake_snap_id)
self.context, source_cgsnapshot_id=fake_snap_id)
self.assertEqual(expected_cg, res_dict['consistency_group'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_cg_create_with_share_network_id(self):
fake_net_id = six.text_type(uuid.uuid4())
@ -224,12 +242,15 @@ class CGApiTest(test.TestCase):
body = {"consistency_group": {
"share_network_id": fake_net_id}}
context = self.request.environ['manila.context']
res_dict = self.controller.create(self.request, body)
self.controller.cg_api.create.assert_called_once_with(
context, share_network_id=fake_net_id, share_type_ids=mock.ANY)
self.context, share_network_id=fake_net_id,
share_type_ids=mock.ANY)
self.assertEqual(expected_cg, res_dict['consistency_group'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_cg_create_no_default_share_type_with_cgsnapshot(self):
fake_snap_id = six.text_type(uuid.uuid4())
@ -241,12 +262,14 @@ class CGApiTest(test.TestCase):
body = {"consistency_group": {
"source_cgsnapshot_id": fake_snap_id}}
context = self.request.environ['manila.context']
res_dict = self.controller.create(self.request, body)
self.controller.cg_api.create.assert_called_once_with(
context, source_cgsnapshot_id=fake_snap_id)
self.context, source_cgsnapshot_id=fake_snap_id)
self.assertEqual(expected_cg, res_dict['consistency_group'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_cg_create_with_name_and_description(self):
fake_name = 'fake_name'
@ -260,32 +283,41 @@ class CGApiTest(test.TestCase):
body = {"consistency_group": {"name": fake_name,
"description": fake_description}}
context = self.request.environ['manila.context']
res_dict = self.controller.create(self.request, body)
self.controller.cg_api.create.assert_called_once_with(
context, name=fake_name, description=fake_description,
self.context, name=fake_name, description=fake_description,
share_type_ids=[self.fake_share_type['id']])
self.assertEqual(expected_cg, res_dict['consistency_group'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_cg_create_invalid_body(self):
body = {"not_consistency_group": {}}
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
self.request, body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_cg_create_invalid_body_share_types_and_source_cgsnapshot(self):
body = {"consistency_group": {"share_types": [],
"source_cgsnapshot_id": ""}}
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
self.request, body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_cg_create_source_cgsnapshot_not_in_available(self):
fake_snap_id = six.text_type(uuid.uuid4())
body = {"consistency_group": {"source_cgsnapshot_id": fake_snap_id}}
self.mock_object(self.controller.cg_api, 'create', mock.Mock(
side_effect=exception.InvalidCGSnapshot(reason='blah')))
self.assertRaises(webob.exc.HTTPConflict, self.controller.create,
self.request, body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_cg_create_source_cgsnapshot_does_not_exist(self):
fake_snap_id = six.text_type(uuid.uuid4())
@ -293,42 +325,61 @@ class CGApiTest(test.TestCase):
self.mock_object(self.controller.cg_api, 'create', mock.Mock(
side_effect=exception.CGSnapshotNotFound(
cgsnapshot_id=fake_snap_id)))
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
self.request, body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_cg_create_source_cgsnapshot_not_a_uuid(self):
fake_snap_id = "Not a uuid"
body = {"consistency_group": {"source_cgsnapshot_id": fake_snap_id}}
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
self.request, body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_cg_create_share_network_id_not_a_uuid(self):
fake_net_id = "Not a uuid"
body = {"consistency_group": {"share_network_id": fake_net_id}}
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
self.request, body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_cg_create_invalid_body_share_types_not_a_list(self):
body = {"consistency_group": {"share_types": ""}}
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
self.request, body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_cg_create_invalid_body_invalid_field(self):
body = {"consistency_group": {"unknown_field": ""}}
exc = self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.create,
self.request, body)
self.assertTrue('unknown_field' in six.text_type(exc))
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_cg_create_with_invalid_share_types_field(self):
body = {"consistency_group": {"share_types": 'iamastring'}}
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
self.request, body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_cg_create_with_invalid_share_types_field_not_uuids(self):
body = {"consistency_group": {"share_types": ['iamastring']}}
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
self.request, body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'create')
def test_cg_update_with_name_and_description(self):
fake_name = 'fake_name'
@ -349,6 +400,8 @@ class CGApiTest(test.TestCase):
context, fake_cg,
{"name": fake_name, "description": fake_description})
self.assertEqual(expected_cg, res_dict['consistency_group'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'update')
def test_cg_update_cg_not_found(self):
body = {"consistency_group": {}}
@ -358,12 +411,16 @@ class CGApiTest(test.TestCase):
self.assertRaises(webob.exc.HTTPNotFound,
self.controller.update,
self.request, 'fake_id', body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'update')
def test_cg_update_invalid_body(self):
body = {"not_consistency_group": {}}
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.update,
self.request, 'fake_id', body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'update')
def test_cg_update_invalid_body_invalid_field(self):
body = {"consistency_group": {"unknown_field": ""}}
@ -371,6 +428,8 @@ class CGApiTest(test.TestCase):
self.controller.update,
self.request, 'fake_id', body)
self.assertTrue('unknown_field' in six.text_type(exc))
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'update')
def test_cg_update_invalid_body_readonly_field(self):
body = {"consistency_group": {"share_types": []}}
@ -378,6 +437,8 @@ class CGApiTest(test.TestCase):
self.controller.update,
self.request, 'fake_id', body)
self.assertTrue('share_types' in six.text_type(exc))
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'update')
def test_cg_list_index(self):
fake_cg, expected_cg = self._get_fake_simple_cg()
@ -385,12 +446,16 @@ class CGApiTest(test.TestCase):
mock.Mock(return_value=[fake_cg]))
res_dict = self.controller.index(self.request)
self.assertEqual([expected_cg], res_dict['consistency_groups'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'get_all')
def test_cg_list_index_no_cgs(self):
self.mock_object(cg_api.API, 'get_all',
mock.Mock(return_value=[]))
res_dict = self.controller.index(self.request)
self.assertEqual([], res_dict['consistency_groups'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'get_all')
def test_cg_list_index_with_limit(self):
fake_cg, expected_cg = self._get_fake_simple_cg()
@ -400,9 +465,14 @@ class CGApiTest(test.TestCase):
req = fakes.HTTPRequest.blank('/consistency_groups?limit=1',
version=self.api_version,
experimental=True)
req_context = req.environ['manila.context']
res_dict = self.controller.index(req)
self.assertEqual(1, len(res_dict['consistency_groups']))
self.assertEqual([expected_cg], res_dict['consistency_groups'])
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'get_all')
def test_cg_list_index_with_limit_and_offset(self):
fake_cg, expected_cg = self._get_fake_simple_cg()
@ -412,11 +482,14 @@ class CGApiTest(test.TestCase):
req = fakes.HTTPRequest.blank('/consistency_groups?limit=1&offset=1',
version=self.api_version,
experimental=True)
req_context = req.environ['manila.context']
res_dict = self.controller.index(req)
self.assertEqual(1, len(res_dict['consistency_groups']))
self.assertEqual([expected_cg2], res_dict['consistency_groups'])
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'get_all')
def test_cg_list_detail(self):
fake_cg, expected_cg = self._get_fake_cg()
@ -426,6 +499,8 @@ class CGApiTest(test.TestCase):
res_dict = self.controller.detail(self.request)
self.assertEqual([expected_cg], res_dict['consistency_groups'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'get_all')
def test_cg_list_detail_no_cgs(self):
self.mock_object(cg_api.API, 'get_all',
@ -434,6 +509,8 @@ class CGApiTest(test.TestCase):
res_dict = self.controller.detail(self.request)
self.assertEqual([], res_dict['consistency_groups'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'get_all')
def test_cg_list_detail_with_limit(self):
fake_cg, expected_cg = self._get_fake_cg()
@ -443,11 +520,14 @@ class CGApiTest(test.TestCase):
req = fakes.HTTPRequest.blank('/consistency_groups?limit=1',
version=self.api_version,
experimental=True)
req_context = req.environ['manila.context']
res_dict = self.controller.detail(req)
self.assertEqual(1, len(res_dict['consistency_groups']))
self.assertEqual([expected_cg], res_dict['consistency_groups'])
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'get_all')
def test_cg_list_detail_with_limit_and_offset(self):
fake_cg, expected_cg = self._get_fake_cg()
@ -457,11 +537,14 @@ class CGApiTest(test.TestCase):
req = fakes.HTTPRequest.blank('/consistency_groups?limit=1&offset=1',
version=self.api_version,
experimental=True)
req_context = req.environ['manila.context']
res_dict = self.controller.detail(req)
self.assertEqual(1, len(res_dict['consistency_groups']))
self.assertEqual([expected_cg2], res_dict['consistency_groups'])
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'get_all')
def test_cg_delete(self):
fake_cg, expected_cg = self._get_fake_cg()
@ -472,6 +555,8 @@ class CGApiTest(test.TestCase):
res = self.controller.delete(self.request, fake_cg['id'])
self.assertEqual(202, res.status_code)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'delete')
def test_cg_delete_cg_not_found(self):
fake_cg, expected_cg = self._get_fake_cg()
@ -480,6 +565,8 @@ class CGApiTest(test.TestCase):
self.assertRaises(webob.exc.HTTPNotFound, self.controller.delete,
self.request, fake_cg['id'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'delete')
def test_cg_delete_in_conflicting_status(self):
fake_cg, expected_cg = self._get_fake_cg()
@ -490,6 +577,8 @@ class CGApiTest(test.TestCase):
self.assertRaises(webob.exc.HTTPConflict, self.controller.delete,
self.request, fake_cg['id'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'delete')
def test_cg_show(self):
fake_cg, expected_cg = self._get_fake_cg()
@ -498,10 +587,13 @@ class CGApiTest(test.TestCase):
req = fakes.HTTPRequest.blank(
'/consistency_groups/%s' % fake_cg['id'],
version=self.api_version, experimental=True)
req_context = req.environ['manila.context']
res_dict = self.controller.show(req, fake_cg['id'])
self.assertEqual(expected_cg, res_dict['consistency_group'])
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'get')
def test_cg_show_as_admin(self):
fake_cg, expected_cg = self._get_fake_cg()
@ -517,6 +609,8 @@ class CGApiTest(test.TestCase):
res_dict = self.controller.show(req, fake_cg['id'])
self.assertEqual(expected_cg, res_dict['consistency_group'])
self.mock_policy_check.assert_called_once_with(
admin_context, self.resource_name, 'get')
def test_cg_show_cg_not_found(self):
fake_cg, expected_cg = self._get_fake_cg()
@ -525,9 +619,12 @@ class CGApiTest(test.TestCase):
req = fakes.HTTPRequest.blank(
'/consistency_groups/%s' % fake_cg['id'],
version=self.api_version, experimental=True)
req_context = req.environ['manila.context']
self.assertRaises(webob.exc.HTTPNotFound, self.controller.show,
req, fake_cg['id'])
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'get')
@ddt.data(*fakes.fixture_reset_status_with_different_roles)
@ddt.unpack
@ -542,7 +639,9 @@ class CGApiTest(test.TestCase):
req.body = six.b(jsonutils.dumps(body))
req.environ['manila.context'] = ctxt
resp = req.get_response(fakes.app())
with mock.patch.object(
policy, 'check_policy', fakes.mock_fake_admin_check):
resp = req.get_response(fakes.app())
# validate response code and model status
self.assertEqual(valid_code, resp.status_int)
@ -567,7 +666,9 @@ class CGApiTest(test.TestCase):
req.body = six.b(jsonutils.dumps({'os-force_delete': {}}))
req.environ['manila.context'] = ctxt
resp = req.get_response(fakes.app())
with mock.patch.object(
policy, 'check_policy', fakes.mock_fake_admin_check):
resp = req.get_response(fakes.app())
# validate response
self.assertEqual(resp_code, resp.status_int)

@ -29,6 +29,7 @@ import webob.response
from manila.api.v1 import quota_class_sets
from manila import context
from manila import exception
from manila import policy
from manila import test
CONF = cfg.CONF
@ -49,7 +50,10 @@ class QuotaSetsControllerTest(test.TestCase):
def setUp(self):
super(self.__class__, self).setUp()
self.controller = quota_class_sets.QuotaClassSetsController()
self.resource_name = self.controller.resource_name
self.class_name = 'foo_class_name'
self.mock_policy_check = self.mock_object(
policy, 'check_policy', mock.Mock(return_value=True))
def test_show_quota(self):
quotas = {
@ -75,6 +79,8 @@ class QuotaSetsControllerTest(test.TestCase):
result = self.controller.show(REQ, self.class_name)
self.assertEqual(expected, result)
self.mock_policy_check.assert_called_once_with(
REQ.environ['manila.context'], self.resource_name, 'show')
def test_show_quota_not_authorized(self):
self.mock_object(
@ -86,6 +92,8 @@ class QuotaSetsControllerTest(test.TestCase):
webob.exc.HTTPForbidden,
self.controller.show,
REQ, self.class_name)
self.mock_policy_check.assert_called_once_with(
REQ.environ['manila.context'], self.resource_name, 'show')
def test_update_quota(self):
CONF.set_default('quota_shares', 789)
@ -114,6 +122,9 @@ class QuotaSetsControllerTest(test.TestCase):
expected['quota_class_set']['id'] = self.class_name
self.assertEqual(expected, show_result)
self.mock_policy_check.assert_has_calls([mock.call(
REQ.environ['manila.context'], self.resource_name, action_name)
for action_name in ('update', 'show')])
def test_update_quota_not_authorized(self):
body = {
@ -127,3 +138,5 @@ class QuotaSetsControllerTest(test.TestCase):
webob.exc.HTTPForbidden,
self.controller.update,
REQ_MEMBER, self.class_name, body=body)
self.mock_policy_check.assert_called_once_with(
REQ_MEMBER.environ['manila.context'], self.resource_name, 'update')

@ -29,6 +29,7 @@ import webob.response
from manila.api.v1 import quota_sets
from manila import context
from manila import exception
from manila import policy
from manila import test
from manila import utils
@ -54,7 +55,10 @@ class QuotaSetsControllerTest(test.TestCase):
def setUp(self):
super(self.__class__, self).setUp()
self.controller = quota_sets.QuotaSetsController()
self.resource_name = self.controller.resource_name
self.project_id = 'foo_project_id'
self.mock_policy_check = self.mock_object(
policy, 'check_policy', mock.Mock(return_value=True))
@ddt.data(
{"shares": 3, "snapshots": 4, "gigabytes": 5,
@ -84,6 +88,8 @@ class QuotaSetsControllerTest(test.TestCase):
result = self.controller.defaults(REQ, self.project_id)
self.assertEqual(expected, result)
self.mock_policy_check.assert_called_once_with(
REQ.environ['manila.context'], self.resource_name, 'show')
@ddt.data(REQ, REQ_WITH_USER)
def test_show_quota(self, request):
@ -110,6 +116,8 @@ class QuotaSetsControllerTest(test.TestCase):
result = self.controller.show(request, self.project_id)
self.assertEqual(expected, result)
self.mock_policy_check.assert_called_once_with(
request.environ['manila.context'], self.resource_name, 'show')
def test_show_quota_not_authorized(self):
self.mock_object(
@ -121,6 +129,8 @@ class QuotaSetsControllerTest(test.TestCase):
webob.exc.HTTPForbidden,
self.controller.show,
REQ, self.project_id)
self.mock_policy_check.assert_called_once_with(
REQ.environ['manila.context'], self.resource_name, 'show')
@ddt.data(REQ, REQ_WITH_USER)
def test_update_quota(self, request):
@ -135,6 +145,10 @@ class QuotaSetsControllerTest(test.TestCase):
'share_networks': 10,
}
}
mock_policy_update_check_call = mock.call(
request.environ['manila.context'], self.resource_name, 'update')
mock_policy_show_check_call = mock.call(
request.environ['manila.context'], self.resource_name, 'show')
update_result = self.controller.update(
request, self.project_id, body=body)
@ -145,6 +159,8 @@ class QuotaSetsControllerTest(test.TestCase):
expected['quota_set']['id'] = self.project_id
self.assertEqual(expected, show_result)
self.mock_policy_check.assert_has_calls([
mock_policy_update_check_call, mock_policy_show_check_call])
@ddt.data(-2, 'foo', {1: 2}, [1])
def test_update_quota_with_invalid_value(self, value):
@ -154,6 +170,8 @@ class QuotaSetsControllerTest(test.TestCase):
webob.exc.HTTPBadRequest,
self.controller.update,
REQ, self.project_id, body=body)
self.mock_policy_check.assert_called_once_with(
REQ.environ['manila.context'], self.resource_name, 'update')
def test_user_quota_can_not_be_bigger_than_tenant_quota(self):
value = 777
@ -169,6 +187,9 @@ class QuotaSetsControllerTest(test.TestCase):
webob.exc.HTTPBadRequest,
self.controller.update,
REQ_WITH_USER, self.project_id, body=body)
self.mock_policy_check.assert_called_once_with(
REQ_WITH_USER.environ['manila.context'], self.resource_name,
'update')
def test_update_inexistent_quota(self):
body = {
@ -182,6 +203,8 @@ class QuotaSetsControllerTest(test.TestCase):
webob.exc.HTTPBadRequest,
self.controller.update,
REQ, self.project_id, body=body)
self.mock_policy_check.assert_called_once_with(
REQ.environ['manila.context'], self.resource_name, 'update')
def test_update_quota_not_authorized(self):
body = {'quota_set': {'tenant_id': self.project_id, 'shares': 13}}
@ -190,6 +213,8 @@ class QuotaSetsControllerTest(test.TestCase):
webob.exc.HTTPForbidden,
self.controller.update,
REQ_MEMBER, self.project_id, body=body)
self.mock_policy_check.assert_called_once_with(
REQ_MEMBER.environ['manila.context'], self.resource_name, 'update')
def test_update_all_quotas_with_force(self):
quotas = (
@ -212,6 +237,10 @@ class QuotaSetsControllerTest(test.TestCase):
'force': True,
}
}
mock_policy_update_check_call = mock.call(
REQ.environ['manila.context'], self.resource_name, 'update')
mock_policy_show_check_call = mock.call(
REQ.environ['manila.context'], self.resource_name, 'show')
update_result = self.controller.update(
REQ, self.project_id, body=expected)
@ -224,6 +253,8 @@ class QuotaSetsControllerTest(test.TestCase):
expected['quota_set']['id'] = self.project_id
self.assertEqual(expected, show_result)
self.mock_policy_check.assert_has_calls([
mock_policy_update_check_call, mock_policy_show_check_call])
def test_delete_tenant_quota(self):
self.mock_object(quota_sets.QUOTAS, 'destroy_all_by_project_and_user')
@ -240,6 +271,8 @@ class QuotaSetsControllerTest(test.TestCase):
quota_sets.QUOTAS.destroy_all_by_project_and_user.called)
quota_sets.QUOTAS.destroy_all_by_project.assert_called_once_with(
REQ.environ['manila.context'], self.project_id)
self.mock_policy_check.assert_called_once_with(
REQ.environ['manila.context'], self.resource_name, 'delete')
def test_delete_user_quota(self):
project_id = 'foo_project_id'
@ -259,9 +292,14 @@ class QuotaSetsControllerTest(test.TestCase):
project_id,
REQ_WITH_USER.environ['manila.context'].user_id)
self.assertFalse(quota_sets.QUOTAS.destroy_all_by_project.called)
self.mock_policy_check.assert_called_once_with(
REQ_WITH_USER.environ['manila.context'], self.resource_name,
'delete')
def test_delete_not_authorized(self):
self.assertRaises(
webob.exc.HTTPForbidden,
self.controller.delete,
REQ_MEMBER, self.project_id)
self.mock_policy_check.assert_called_once_with(
REQ_MEMBER.environ['manila.context'], self.resource_name, 'delete')

@ -16,6 +16,7 @@ import mock
from manila.api.v1 import scheduler_stats
from manila import context
from manila import policy
from manila.scheduler import rpcapi
from manila import test
from manila.tests.api import fakes
@ -62,7 +63,10 @@ class SchedulerStatsControllerTestCase(test.TestCase):
super(SchedulerStatsControllerTestCase, self).setUp()
self.flags(host='fake')
self.controller = scheduler_stats.SchedulerStatsController()
self.resource_name = self.controller.resource_name
self.ctxt = context.RequestContext('admin', 'fake', True)
self.mock_policy_check = self.mock_object(
policy, 'check_policy', mock.Mock(return_value=True))
def test_pools_index(self):
mock_get_pools = self.mock_object(rpcapi.SchedulerAPI,
@ -92,6 +96,8 @@ class SchedulerStatsControllerTestCase(test.TestCase):
self.assertDictMatch(result, expected)
mock_get_pools.assert_called_once_with(self.ctxt, filters={})
self.mock_policy_check.assert_called_once_with(
self.ctxt, self.resource_name, 'index')
def test_pools_index_with_filters(self):
mock_get_pools = self.mock_object(rpcapi.SchedulerAPI,
@ -127,6 +133,8 @@ class SchedulerStatsControllerTestCase(test.TestCase):
self.assertDictMatch(result, expected)
mock_get_pools.assert_called_once_with(self.ctxt,
filters=expected_filters)
self.mock_policy_check.assert_called_once_with(
self.ctxt, self.resource_name, 'index')
def test_get_pools_detail(self):
mock_get_pools = self.mock_object(rpcapi.SchedulerAPI,
@ -177,6 +185,8 @@ class SchedulerStatsControllerTestCase(test.TestCase):
self.assertDictMatch(expected, result)
mock_get_pools.assert_called_once_with(self.ctxt, filters={})
self.mock_policy_check.assert_called_once_with(
self.ctxt, self.resource_name, 'detail')
class SchedulerStatsTestCase(test.TestCase):

@ -17,6 +17,7 @@
import datetime
import mock
from oslo_utils import timeutils
from manila.api.v1 import services
@ -167,10 +168,6 @@ def fake_service_update(context, service_id, values):
'disabled': values['disabled']}
def fake_policy_enforce(context, action, target):
pass
def fake_utcnow():
return datetime.datetime(2012, 10, 29, 13, 42, 11)
@ -185,10 +182,11 @@ class ServicesTest(test.TestCase):
self.mock_object(db, "service_get_by_args",
fake_service_get_by_host_binary)
self.mock_object(db, "service_update", fake_service_update)
self.mock_object(policy, "enforce", fake_policy_enforce)
self.context = context.get_admin_context()
self.controller = services.ServiceController()
self.resource_name = self.controller.resource_name
self.mock_policy_check = self.mock_object(
policy, 'check_policy', mock.Mock(return_value=True))
def tearDown(self):
super(ServicesTest, self).tearDown()
@ -197,6 +195,8 @@ class ServicesTest(test.TestCase):
req = FakeRequest()
res_dict = self.controller.index(req)
self.assertEqual(fake_response_service_list, res_dict)
self.mock_policy_check.assert_called_once_with(
req.environ['manila.context'], self.resource_name, 'index')
def test_services_list_with_host(self):
req = FakeRequestWithHost()
@ -207,6 +207,8 @@ class ServicesTest(test.TestCase):
fake_response_service_list['services'][1],
]}
self.assertEqual(response, res_dict)
self.mock_policy_check.assert_called_once_with(
req.environ['manila.context'], self.resource_name, 'index')
def test_services_list_with_binary(self):
req = FakeRequestWithBinary()
@ -217,6 +219,8 @@ class ServicesTest(test.TestCase):
]}
self.assertEqual(response, res_dict)
self.mock_policy_check.assert_called_once_with(
req.environ['manila.context'], self.resource_name, 'index')
def test_services_list_with_zone(self):
req = FakeRequestWithZone()
@ -226,6 +230,8 @@ class ServicesTest(test.TestCase):
fake_response_service_list['services'][1],
]}
self.assertEqual(response, res_dict)
self.mock_policy_check.assert_called_once_with(
req.environ['manila.context'], self.resource_name, 'index')
def test_services_list_with_status(self):
req = FakeRequestWithStatus()
@ -234,6 +240,8 @@ class ServicesTest(test.TestCase):
fake_response_service_list['services'][2],
]}
self.assertEqual(response, res_dict)
self.mock_policy_check.assert_called_once_with(
req.environ['manila.context'], self.resource_name, 'index')
def test_services_list_with_state(self):
req = FakeRequestWithState()
@ -243,21 +251,29 @@ class ServicesTest(test.TestCase):
fake_response_service_list['services'][1],
]}
self.assertEqual(response, res_dict)
self.mock_policy_check.assert_called_once_with(
req.environ['manila.context'], self.resource_name, 'index')
def test_services_list_with_host_binary(self):
req = FakeRequestWithHostBinary()
res_dict = self.controller.index(req)
response = {'services': [fake_response_service_list['services'][1], ]}
self.assertEqual(response, res_dict)
self.mock_policy_check.assert_called_once_with(
req.environ['manila.context'], self.resource_name, 'index')
def test_services_enable(self):
body = {'host': 'host1', 'binary': 'manila-share'}
req = fakes.HTTPRequest.blank('/v1/fake/os-services/enable')
res_dict = self.controller.update(req, "enable", body)
self.assertFalse(res_dict['disabled'])
self.mock_policy_check.assert_called_once_with(
req.environ['manila.context'], self.resource_name, 'update')
def test_services_disable(self):
req = fakes.HTTPRequest.blank('/v1/fake/os-services/disable')
body = {'host': 'host1', 'binary': 'manila-share'}
res_dict = self.controller.update(req, "disable", body)
self.assertTrue(res_dict['disabled'])
self.mock_policy_check.assert_called_once_with(
req.environ['manila.context'], self.resource_name, 'update')

@ -11,6 +11,7 @@
# under the License.
import ddt
import mock
from oslo_config import cfg
from oslo_serialization import jsonutils
import six
@ -22,6 +23,7 @@ from manila.common import constants
from manila import context
from manila import db
from manila import exception
from manila import policy
from manila import test
from manila.tests.api import fakes
from manila.tests import db_utils
@ -36,6 +38,10 @@ class ShareInstancesAPITest(test.TestCase):
def setUp(self):
super(self.__class__, self).setUp()
self.controller = share_instances.ShareInstancesController()
self.resource_name = self.controller.resource_name
self.context = context.RequestContext('admin', 'fake', True)
self.mock_policy_check = self.mock_object(
policy, 'check_policy', mock.Mock(return_value=True))
self.admin_context = context.RequestContext('admin', 'fake', True)
self.member_context = context.RequestContext('fake', 'fake')
@ -64,6 +70,7 @@ class ShareInstancesAPITest(test.TestCase):
def test_index(self):
req = self._get_request('/share_instances')
req_context = req.environ['manila.context']
share_instances_count = 3
test_instances = [
db_utils.create_share(size=s + 1).instance
@ -74,6 +81,8 @@ class ShareInstancesAPITest(test.TestCase):
self._validate_ids_in_share_instances_list(
test_instances, actual_result['share_instances'])
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'index')
def test_show(self):
test_instance = db_utils.create_share(size=1).instance
@ -82,11 +91,18 @@ class ShareInstancesAPITest(test.TestCase):
actual_result = self.controller.show(self._get_request('fake'), id)
self.assertEqual(id, actual_result['share_instance']['id'])
self.mock_policy_check.assert_called_once_with(
self.admin_context, self.resource_name, 'show')
def test_get_share_instances(self):
test_share = db_utils.create_share(size=1)
id = test_share['id']
req = self._get_request('fake')
req_context = req.environ['manila.context']
share_policy_check_call = mock.call(
req_context, 'share', 'get', mock.ANY)
get_instances_policy_check_call = mock.call(
req_context, 'share_instance', 'index')
actual_result = self.controller.get_share_instances(req, id)
@ -94,22 +110,33 @@ class ShareInstancesAPITest(test.TestCase):
[test_share.instance],
actual_result['share_instances']
)
self.mock_policy_check.assert_has_calls([
get_instances_policy_check_call, share_policy_check_call])
@ddt.data('show', 'get_share_instances')
def test_not_found(self, target_method_name):
method = getattr(self.controller, target_method_name)
action = (target_method_name if target_method_name == 'show' else
'index')
self.assertRaises(webob_exc.HTTPNotFound, method,
self._get_request('fake'), 'fake')
self.mock_policy_check.assert_called_once_with(
self.admin_context, self.resource_name, action)
@ddt.data(('show', 2), ('get_share_instances', 2), ('index', 1))
@ddt.unpack
def test_access(self, target_method_name, args_count):
user_context = context.RequestContext('fake', 'fake')
req = self._get_request('fake', user_context)
policy_exception = exception.PolicyNotAuthorized(
action=target_method_name)
target_method = getattr(self.controller, target_method_name)
args = [i for i in range(1, args_count)]
self.assertRaises(webob_exc.HTTPForbidden, target_method, req, *args)
with mock.patch.object(policy, 'check_policy', mock.Mock(
side_effect=policy_exception)):
self.assertRaises(
webob_exc.HTTPForbidden, target_method, req, *args)
def _reset_status(self, ctxt, model, req, db_access_method,
valid_code, valid_status=None, body=None):
@ -120,7 +147,9 @@ class ShareInstancesAPITest(test.TestCase):
req.body = six.b(jsonutils.dumps(body))
req.environ['manila.context'] = ctxt
resp = req.get_response(fakes.app())
with mock.patch.object(
policy, 'check_policy', fakes.mock_fake_admin_check):
resp = req.get_response(fakes.app())
# validate response code and model status
self.assertEqual(valid_code, resp.status_int)
@ -163,7 +192,9 @@ class ShareInstancesAPITest(test.TestCase):
req.body = six.b(jsonutils.dumps({'os-force_delete': {}}))
req.environ['manila.context'] = ctxt
resp = req.get_response(fakes.app())
with mock.patch.object(
policy, 'check_policy', fakes.mock_fake_admin_check):
resp = req.get_response(fakes.app())
# validate response
self.assertEqual(valid_code, resp.status_int)

@ -20,6 +20,7 @@ import webob
from manila.api.v1 import share_manage
from manila.db import api as db_api
from manila import exception
from manila import policy
from manila.share import api as share_api
from manila.share import share_types
from manila import test
@ -45,8 +46,12 @@ class ShareManageTest(test.TestCase):
def setUp(self):
super(ShareManageTest, self).setUp()
self.controller = share_manage.ShareManageController()
self.resource_name = self.controller.resource_name
self.request = fakes.HTTPRequest.blank('/share/manage',
use_admin_context=True)
self.context = self.request.environ['manila.context']
self.mock_policy_check = self.mock_object(
policy, 'check_policy', mock.Mock(return_value=True))
@ddt.data({},
{'share': None},
@ -57,6 +62,8 @@ class ShareManageTest(test.TestCase):
self.controller.create,
self.request,
body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'manage')
def test_share_manage_service_not_found(self):
body = get_fake_manage_body()
@ -67,6 +74,8 @@ class ShareManageTest(test.TestCase):
self.controller.create,
self.request,
body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'manage')
def test_share_manage_share_type_not_found(self):
body = get_fake_manage_body()
@ -80,6 +89,8 @@ class ShareManageTest(test.TestCase):
self.controller.create,
self.request,
body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'manage')
def _setup_manage_mocks(self, service_is_up=True):
self.mock_object(db_api, 'service_get_by_host_and_topic', mock.Mock(
@ -99,6 +110,8 @@ class ShareManageTest(test.TestCase):
self.controller.create,
self.request,
body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'manage')
def test_share_manage_duplicate_share(self):
body = get_fake_manage_body()
@ -110,6 +123,8 @@ class ShareManageTest(test.TestCase):
self.controller.create,
self.request,
body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'manage')
def test_share_manage_forbidden_manage(self):
body = get_fake_manage_body()
@ -121,6 +136,8 @@ class ShareManageTest(test.TestCase):
self.controller.create,
self.request,
body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'manage')
def test_share_manage_forbidden_validate_service_host(self):
body = get_fake_manage_body()
@ -132,6 +149,8 @@ class ShareManageTest(test.TestCase):
self.controller.create,
self.request,
body)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'manage')
@ddt.data(
get_fake_manage_body(name='foo', description='bar'),
@ -161,12 +180,16 @@ class ShareManageTest(test.TestCase):
share_api.API.manage.assert_called_once_with(
mock.ANY, share, driver_options)
self.assertIsNotNone(actual_result)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'manage')
def test_wrong_permissions(self):
body = get_fake_manage_body()
fake_req = fakes.HTTPRequest.blank(
'/share/manage', use_admin_context=False)
self.assertRaises(webob.exc.HTTPForbidden,
self.controller.create,
fakes.HTTPRequest.blank('/share/manage',
use_admin_context=False),
body)
fake_req, body)
self.mock_policy_check.assert_called_once_with(
fake_req.environ['manila.context'], self.resource_name, 'manage')

@ -157,6 +157,7 @@ class ShareServerAPITest(test.TestCase):
def setUp(self):
super(ShareServerAPITest, self).setUp()
self.controller = share_servers.ShareServerController()
self.resource_name = self.controller.resource_name
self.mock_object(policy, 'check_policy',
mock.Mock(return_value=True))
self.mock_object(db_api, 'share_server_get_all',
@ -165,14 +166,14 @@ class ShareServerAPITest(test.TestCase):
def test_index_no_filters(self):
result = self.controller.index(FakeRequestAdmin)
policy.check_policy.assert_called_once_with(
CONTEXT, share_servers.RESOURCE_NAME, 'index')
CONTEXT, self.resource_name, 'index')
db_api.share_server_get_all.assert_called_once_with(CONTEXT)
self.assertEqual(fake_share_server_list, result)
def test_index_host_filter(self):
result = self.controller.index(FakeRequestWithHost)
policy.check_policy.assert_called_once_with(
CONTEXT, share_servers.RESOURCE_NAME, 'index')
CONTEXT, self.resource_name, 'index')
db_api.share_server_get_all.assert_called_once_with(CONTEXT)
self.assertEqual([fake_share_server_list['share_servers'][0]],
result['share_servers'])
@ -180,7 +181,7 @@ class ShareServerAPITest(test.TestCase):
def test_index_status_filter(self):
result = self.controller.index(FakeRequestWithStatus)
policy.check_policy.assert_called_once_with(
CONTEXT, share_servers.RESOURCE_NAME, 'index')
CONTEXT, self.resource_name, 'index')
db_api.share_server_get_all.assert_called_once_with(CONTEXT)
self.assertEqual([fake_share_server_list['share_servers'][1]],
result['share_servers'])
@ -188,7 +189,7 @@ class ShareServerAPITest(test.TestCase):
def test_index_project_id_filter(self):
result = self.controller.index(FakeRequestWithProjectId)
policy.check_policy.assert_called_once_with(
CONTEXT, share_servers.RESOURCE_NAME, 'index')
CONTEXT, self.resource_name, 'index')
db_api.share_server_get_all.assert_called_once_with(CONTEXT)
self.assertEqual([fake_share_server_list['share_servers'][0]],
result['share_servers'])
@ -196,7 +197,7 @@ class ShareServerAPITest(test.TestCase):
def test_index_share_network_filter_by_name(self):
result = self.controller.index(FakeRequestWithShareNetworkName)
policy.check_policy.assert_called_once_with(
CONTEXT, share_servers.RESOURCE_NAME, 'index')
CONTEXT, self.resource_name, 'index')
db_api.share_server_get_all.assert_called_once_with(CONTEXT)
self.assertEqual([fake_share_server_list['share_servers'][0]],
result['share_servers'])
@ -204,7 +205,7 @@ class ShareServerAPITest(test.TestCase):
def test_index_share_network_filter_by_id(self):
result = self.controller.index(FakeRequestWithShareNetworkId)
policy.check_policy.assert_called_once_with(
CONTEXT, share_servers.RESOURCE_NAME, 'index')
CONTEXT, self.resource_name, 'index')
db_api.share_server_get_all.assert_called_once_with(CONTEXT)
self.assertEqual([fake_share_server_list['share_servers'][0]],
result['share_servers'])
@ -212,7 +213,7 @@ class ShareServerAPITest(test.TestCase):
def test_index_fake_filter(self):
result = self.controller.index(FakeRequestWithFakeFilter)
policy.check_policy.assert_called_once_with(
CONTEXT, share_servers.RESOURCE_NAME, 'index')
CONTEXT, self.resource_name, 'index')
db_api.share_server_get_all.assert_called_once_with(CONTEXT)
self.assertEqual(0, len(result['share_servers']))
@ -223,7 +224,7 @@ class ShareServerAPITest(test.TestCase):
FakeRequestAdmin,
fake_share_server_get_result['share_server']['id'])
policy.check_policy.assert_called_once_with(
CONTEXT, share_servers.RESOURCE_NAME, 'show')
CONTEXT, self.resource_name, 'show')
db_api.share_server_get.assert_called_once_with(
CONTEXT, fake_share_server_get_result['share_server']['id'])
self.assertEqual(fake_share_server_get_result['share_server'],
@ -236,7 +237,7 @@ class ShareServerAPITest(test.TestCase):
FakeRequestAdmin,
fake_share_server_get_result['share_server']['id'])
policy.check_policy.assert_called_once_with(
CONTEXT, share_servers.RESOURCE_NAME, 'details')
CONTEXT, self.resource_name, 'details')
db_api.share_server_get.assert_called_once_with(
CONTEXT, fake_share_server_get_result['share_server']['id'])
self.assertEqual(fake_share_server_backend_details_get_result,
@ -251,7 +252,7 @@ class ShareServerAPITest(test.TestCase):
FakeRequestAdmin,
fake_share_server_get_result['share_server']['id'])
policy.check_policy.assert_called_once_with(
CONTEXT, share_servers.RESOURCE_NAME, 'delete')
CONTEXT, self.resource_name, 'delete')
db_api.share_server_get.assert_called_once_with(
CONTEXT, fake_share_server_get_result['share_server']['id'])
self.controller.share_api.delete_share_server.assert_called_once_with(
@ -266,7 +267,7 @@ class ShareServerAPITest(test.TestCase):
FakeRequestAdmin,
fake_share_server_get_result['share_server']['id'])
policy.check_policy.assert_called_once_with(
CONTEXT, share_servers.RESOURCE_NAME, 'delete')
CONTEXT, self.resource_name, 'delete')
db_api.share_server_get.assert_called_once_with(
CONTEXT, fake_share_server_get_result['share_server']['id'])
self.controller.share_api.delete_share_server.assert_called_once_with(
@ -308,7 +309,7 @@ class ShareServerAPITest(test.TestCase):
db_api.share_server_get.assert_called_once_with(
CONTEXT, share_server_id)
policy.check_policy.assert_called_once_with(
CONTEXT, share_servers.RESOURCE_NAME, 'delete')
CONTEXT, self.resource_name, 'delete')
def test_delete_creating_server(self):
share_server = FakeShareServer(status=constants.STATUS_CREATING)
@ -320,7 +321,7 @@ class ShareServerAPITest(test.TestCase):
share_server['id'])
policy.check_policy.assert_called_once_with(
CONTEXT,
share_servers.RESOURCE_NAME, 'delete')
self.resource_name, 'delete')
def test_delete_deleting_server(self):
share_server = FakeShareServer(status=constants.STATUS_DELETING)
@ -331,4 +332,4 @@ class ShareServerAPITest(test.TestCase):
FakeRequestAdmin,
share_server['id'])
policy.check_policy.assert_called_once_with(
CONTEXT, share_servers.RESOURCE_NAME, 'delete')
CONTEXT, self.resource_name, 'delete')

@ -119,6 +119,7 @@ class ShareTypesAPITest(test.TestCase):
super(self.__class__, self).setUp()
self.flags(host='fake')
self.controller = types.ShareTypesController()
self.resource_name = self.controller.resource_name
self.mock_object(policy, 'check_policy',
mock.Mock(return_value=True))
fake_notifier.reset()
@ -157,8 +158,7 @@ class ShareTypesAPITest(test.TestCase):
constants.ExtraSpecs.DRIVER_HANDLES_SHARE_SERVERS, '')
self.assertEqual('true', required_extra_spec)
policy.check_policy.assert_called_once_with(
req.environ['manila.context'], self.controller.resource_name,
'index')
req.environ['manila.context'], self.resource_name, 'index')
def test_share_types_index_no_data(self):
self.mock_object(share_types, 'get_all_types',
@ -169,8 +169,7 @@ class ShareTypesAPITest(test.TestCase):
self.assertEqual(0, len(res_dict['share_types']))
policy.check_policy.assert_called_once_with(
req.environ['manila.context'], self.controller.resource_name,
'index')
req.environ['manila.context'], self.resource_name, 'index')
def test_share_types_show(self):
self.mock_object(share_types, 'get_share_type',
@ -183,8 +182,7 @@ class ShareTypesAPITest(test.TestCase):
self.assertEqual('1', res_dict['share_type']['id'])
self.assertEqual('share_type_1', res_dict['share_type']['name'])
policy.check_policy.assert_called_once_with(
req.environ['manila.context'], self.controller.resource_name,
'show')
req.environ['manila.context'], self.resource_name, 'show')
def test_share_types_show_not_found(self):
self.mock_object(share_types, 'get_share_type',
@ -194,8 +192,7 @@ class ShareTypesAPITest(test.TestCase):
self.assertRaises(webob.exc.HTTPNotFound, self.controller.show,
req, '777')
policy.check_policy.assert_called_once_with(
req.environ['manila.context'], self.controller.resource_name,
'show')
req.environ['manila.context'], self.resource_name, 'show')
def test_share_types_default(self):
self.mock_object(share_types, 'get_default_share_type',
@ -208,8 +205,7 @@ class ShareTypesAPITest(test.TestCase):
self.assertEqual('1', res_dict['share_type']['id'])
self.assertEqual('share_type_1', res_dict['share_type']['name'])
policy.check_policy.assert_called_once_with(
req.environ['manila.context'], self.controller.resource_name,
'default')
req.environ['manila.context'], self.resource_name, 'default')
def test_share_types_default_not_found(self):
self.mock_object(share_types, 'get_default_share_type',
@ -219,8 +215,7 @@ class ShareTypesAPITest(test.TestCase):
self.assertRaises(webob.exc.HTTPNotFound, self.controller.default, req)
policy.check_policy.assert_called_once_with(
req.environ['manila.context'], self.controller.resource_name,
'default')
req.environ['manila.context'], self.resource_name, 'default')
def test_view_builder_show(self):
view_builder = views_types.ViewBuilder()

@ -23,6 +23,7 @@ import webob
from manila.api.v1 import share_types_extra_specs
from manila.common import constants
from manila import exception
from manila import policy
from manila import test
from manila.tests.api import fakes
from manila.tests import fake_notifier
@ -91,6 +92,8 @@ class ShareTypesExtraSpecsTest(test.TestCase):
self.api_path = '/v2/fake/os-share-types/1/extra_specs'
self.controller = (
share_types_extra_specs.ShareTypeExtraSpecsController())
self.resource_name = self.controller.resource_name
self.mock_policy_check = self.mock_object(policy, 'check_policy')
"""to reset notifier drivers left over from other api/contrib tests"""
self.addCleanup(fake_notifier.reset)
@ -100,35 +103,51 @@ class ShareTypesExtraSpecsTest(test.TestCase):
return_share_type_extra_specs)
req = fakes.HTTPRequest.blank(self.api_path)
req_context = req.environ['manila.context']
res_dict = self.controller.index(req, 1)
self.assertEqual('value1', res_dict['extra_specs']['key1'])
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'index')
def test_index_no_data(self):
self.mock_object(manila.db, 'share_type_extra_specs_get',
return_empty_share_type_extra_specs)
req = fakes.HTTPRequest.blank(self.api_path)
req_context = req.environ['manila.context']
res_dict = self.controller.index(req, 1)
self.assertEqual(0, len(res_dict['extra_specs']))
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'index')
def test_show(self):
self.mock_object(manila.db, 'share_type_extra_specs_get',
return_share_type_extra_specs)
req = fakes.HTTPRequest.blank(self.api_path + '/key5')
req_context = req.environ['manila.context']
res_dict = self.controller.show(req, 1, 'key5')
self.assertEqual('value5', res_dict['key5'])
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'show')
def test_show_spec_not_found(self):
self.mock_object(manila.db, 'share_type_extra_specs_get',
return_empty_share_type_extra_specs)
req = fakes.HTTPRequest.blank(self.api_path + '/key6')
req_context = req.environ['manila.context']
self.assertRaises(webob.exc.HTTPNotFound, self.controller.show,
req, 1, 'key6')
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'show')
def test_delete(self):
self.mock_object(manila.db, 'share_type_extra_specs_delete',
@ -136,23 +155,34 @@ class ShareTypesExtraSpecsTest(test.TestCase):
self.assertEqual(0, len(fake_notifier.NOTIFICATIONS))
req = fakes.HTTPRequest.blank(self.api_path + '/key5')
req_context = req.environ['manila.context']
self.controller.delete(req, 1, 'key5')
self.assertEqual(1, len(fake_notifier.NOTIFICATIONS))
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'delete')
def test_delete_not_found(self):
self.mock_object(manila.db, 'share_type_extra_specs_delete',
delete_share_type_extra_specs_not_found)
req = fakes.HTTPRequest.blank(self.api_path + '/key6')
req_context = req.environ['manila.context']
self.assertRaises(webob.exc.HTTPNotFound, self.controller.delete,
req, 1, 'key6')
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'delete')
def test_delete_forbidden(self):
req = fakes.HTTPRequest.blank(
self.api_path + '/' + DRIVER_HANDLES_SHARE_SERVERS)
req_context = req.environ['manila.context']
self.assertRaises(webob.exc.HTTPForbidden, self.controller.delete,
req, 1, DRIVER_HANDLES_SHARE_SERVERS)
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'delete')
@ddt.data(
get_extra_specs_dict({}),
@ -169,6 +199,7 @@ class ShareTypesExtraSpecsTest(test.TestCase):
mock.Mock(return_value=return_create_share_type_extra_specs))
self.assertEqual(0, len(fake_notifier.NOTIFICATIONS))
req = fakes.HTTPRequest.blank(self.api_path)
req_context = req.environ['manila.context']
res_dict = self.controller.create(req, 1, body)
@ -179,6 +210,8 @@ class ShareTypesExtraSpecsTest(test.TestCase):
manila.db.share_type_extra_specs_update_or_create.\
assert_called_once_with(
req.environ['manila.context'], 1, body['extra_specs'])
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'create')
def test_create_with_too_small_key(self):
self.mock_object(
@ -188,12 +221,15 @@ class ShareTypesExtraSpecsTest(test.TestCase):
body = {"extra_specs": {too_small_key: "value"}}
self.assertEqual(0, len(fake_notifier.NOTIFICATIONS))
req = fakes.HTTPRequest.blank(self.api_path)
req_context = req.environ['manila.context']
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.create, req, 1, body)
self.assertFalse(
manila.db.share_type_extra_specs_update_or_create.called)
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'create')
def test_create_with_too_big_key(self):
self.mock_object(
@ -203,12 +239,15 @@ class ShareTypesExtraSpecsTest(test.TestCase):
body = {"extra_specs": {too_big_key: "value"}}
self.assertEqual(0, len(fake_notifier.NOTIFICATIONS))
req = fakes.HTTPRequest.blank(self.api_path)
req_context = req.environ['manila.context']
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.create, req, 1, body)
self.assertFalse(
manila.db.share_type_extra_specs_update_or_create.called)
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'create')
def test_create_with_too_small_value(self):
self.mock_object(
@ -218,10 +257,12 @@ class ShareTypesExtraSpecsTest(test.TestCase):
body = {"extra_specs": {"key": too_small_value}}
self.assertEqual(0, len(fake_notifier.NOTIFICATIONS))
req = fakes.HTTPRequest.blank(self.api_path)
req_context = req.environ['manila.context']
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.create, req, 1, body)
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'create')
self.assertFalse(
manila.db.share_type_extra_specs_update_or_create.called)
@ -233,10 +274,12 @@ class ShareTypesExtraSpecsTest(test.TestCase):
body = {"extra_specs": {"key": too_big_value}}
self.assertEqual(0, len(fake_notifier.NOTIFICATIONS))
req = fakes.HTTPRequest.blank(self.api_path)
req_context = req.environ['manila.context']
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.create, req, 1, body)
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'create')
self.assertFalse(
manila.db.share_type_extra_specs_update_or_create.called)
@ -255,13 +298,18 @@ class ShareTypesExtraSpecsTest(test.TestCase):
self.assertEqual(0, len(fake_notifier.NOTIFICATIONS))
req = fakes.HTTPRequest.blank(self.api_path)
req_context = req.environ['manila.context']
res_dict = self.controller.create(req, 1, body)
self.assertEqual(1, len(fake_notifier.NOTIFICATIONS))
self.assertEqual(mock_return_value['key1'],
res_dict['extra_specs']['other_alphanum.-_:'])
manila.db.share_type_extra_specs_update_or_create.\
assert_called_once_with(
req.environ['manila.context'], 1, body['extra_specs'])
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'create')
def test_create_too_many_keys_allowed_chars(self):
mock_return_value = {"key1": "value1",
@ -281,6 +329,7 @@ class ShareTypesExtraSpecsTest(test.TestCase):
self.assertEqual(0, len(fake_notifier.NOTIFICATIONS))
req = fakes.HTTPRequest.blank(self.api_path)
req_context = req.environ['manila.context']
res_dict = self.controller.create(req, 1, body)
@ -292,8 +341,9 @@ class ShareTypesExtraSpecsTest(test.TestCase):
self.assertEqual(mock_return_value['key3'],
res_dict['extra_specs']['other3_alphanum.-_:'])
manila.db.share_type_extra_specs_update_or_create.\
assert_called_once_with(
req.environ['manila.context'], 1, body['extra_specs'])
assert_called_once_with(req_context, 1, body['extra_specs'])
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'create')
def test_update_item(self):
self.mock_object(
@ -303,6 +353,7 @@ class ShareTypesExtraSpecsTest(test.TestCase):
self.assertEqual(0, len(fake_notifier.NOTIFICATIONS))
req = fakes.HTTPRequest.blank(
self.api_path + '/' + DRIVER_HANDLES_SHARE_SERVERS)
req_context = req.environ['manila.context']
res_dict = self.controller.update(
req, 1, DRIVER_HANDLES_SHARE_SERVERS, body)
@ -310,38 +361,48 @@ class ShareTypesExtraSpecsTest(test.TestCase):
self.assertEqual(1, len(fake_notifier.NOTIFICATIONS))
self.assertTrue(res_dict[DRIVER_HANDLES_SHARE_SERVERS])
manila.db.share_type_extra_specs_update_or_create.\
assert_called_once_with(
req.environ['manila.context'], 1, body)
assert_called_once_with(req_context, 1, body)
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'update')
def test_update_item_too_many_keys(self):
self.mock_object(manila.db, 'share_type_extra_specs_update_or_create')
body = {"key1": "value1", "key2": "value2"}
req = fakes.HTTPRequest.blank(self.api_path + '/key1')
req_context = req.environ['manila.context']
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
req, 1, 'key1', body)
self.assertFalse(
manila.db.share_type_extra_specs_update_or_create.called)
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'update')
def test_update_item_body_uri_mismatch(self):
self.mock_object(manila.db, 'share_type_extra_specs_update_or_create')
body = {"key1": "value1"}
req = fakes.HTTPRequest.blank(self.api_path + '/bad')
req_context = req.environ['manila.context']
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
req, 1, 'bad', body)
self.assertFalse(
manila.db.share_type_extra_specs_update_or_create.called)
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'update')
@ddt.data(None, {}, {"extra_specs": {DRIVER_HANDLES_SHARE_SERVERS: ""}})
def test_update_invalid_body(self, body):
req = fakes.HTTPRequest.blank('/v2/fake/types/1/extra_specs')
req_context = req.environ['manila.context']
req.method = 'POST'
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.update, req, '1', body)
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'update')
@ddt.data(
None, {}, {'foo': {'a': 'b'}}, {'extra_specs': 'string'},
@ -356,7 +417,10 @@ class ShareTypesExtraSpecsTest(test.TestCase):
{"extra_specs": {"k": ""}})
def test_create_invalid_body(self, body):
req = fakes.HTTPRequest.blank('/v2/fake/types/1/extra_specs')
req_context = req.environ['manila.context']
req.method = 'POST'
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.create, req, '1', body)
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'create')

@ -20,6 +20,7 @@ import webob
from manila.api.v1 import share_unmanage
from manila.common import constants
from manila import exception
from manila import policy
from manila.share import api as share_api
from manila import test
from manila.tests.api.contrib import stubs
@ -32,6 +33,7 @@ class ShareUnmanageTest(test.TestCase):
def setUp(self):
super(ShareUnmanageTest, self).setUp()
self.controller = share_unmanage.ShareUnmanageController()
self.resource_name = self.controller.resource_name
self.mock_object(share_api.API, 'get_all',
stubs.stub_get_all_shares)
self.mock_object(share_api.API, 'get',
@ -45,6 +47,9 @@ class ShareUnmanageTest(test.TestCase):
'/share/%s/unmanage' % self.share_id,
use_admin_context=True
)
self.context = self.request.environ['manila.context']
self.mock_policy_check = self.mock_object(
policy, 'check_policy', mock.Mock(return_value=True))
def test_unmanage_share(self):
share = dict(status=constants.STATUS_AVAILABLE, id='foo_id')
@ -64,6 +69,8 @@ class ShareUnmanageTest(test.TestCase):
self.request.environ['manila.context'], share['id'])
share_api.API.unmanage.assert_called_once_with(
self.request.environ['manila.context'], share)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'unmanage')
def test_unmanage_share_that_has_snapshots(self):
share = dict(status=constants.STATUS_AVAILABLE, id='foo_id')
@ -86,6 +93,8 @@ class ShareUnmanageTest(test.TestCase):
self.request.environ['manila.context'], share['id'])
self.controller.share_api.get.assert_called_once_with(
self.request.environ['manila.context'], share['id'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'unmanage')
def test_unmanage_share_based_on_share_server(self):
share = dict(share_server_id='foo_id', id='bar_id')
@ -99,6 +108,8 @@ class ShareUnmanageTest(test.TestCase):
self.controller.share_api.get.assert_called_once_with(
self.request.environ['manila.context'], share['id'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'unmanage')
@ddt.data(*constants.TRANSITIONAL_STATUSES)
def test_unmanage_share_with_transitional_state(self, share_status):
@ -113,6 +124,8 @@ class ShareUnmanageTest(test.TestCase):
self.controller.share_api.get.assert_called_once_with(
self.request.environ['manila.context'], share['id'])
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'unmanage')
def test_unmanage_share_not_found(self):
self.mock_object(share_api.API, 'get', mock.Mock(
@ -122,6 +135,8 @@ class ShareUnmanageTest(test.TestCase):
self.assertRaises(webob.exc.HTTPNotFound,
self.controller.unmanage,
self.request, self.share_id)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'unmanage')
@ddt.data(exception.InvalidShare(reason="fake"),
exception.PolicyNotAuthorized(action="fake"),)
@ -134,13 +149,18 @@ class ShareUnmanageTest(test.TestCase):
self.assertRaises(webob.exc.HTTPForbidden,
self.controller.unmanage,
self.request, self.share_id)
self.mock_policy_check.assert_called_once_with(
self.context, self.resource_name, 'unmanage')
def test_wrong_permissions(self):
share_id = 'fake'
req = fakes.HTTPRequest.blank('/share/%s/unmanage' % share_id,
use_admin_context=False)
req_context = req.environ['manila.context']
self.assertRaises(webob.exc.HTTPForbidden,
self.controller.unmanage,
req,
share_id)
self.mock_policy_check.assert_called_once_with(
req_context, self.resource_name, 'unmanage')

@ -83,7 +83,6 @@ class CGAPITestCase(test.TestCase):
dt_utc = datetime.datetime.utcnow()
self.mock_object(timeutils, 'utcnow', mock.Mock(return_value=dt_utc))
self.mock_object(cg_api.policy, 'check_policy')
def test_create_empty_request(self):
cg = fake_cg('fakeid',
@ -101,19 +100,6 @@ class CGAPITestCase(test.TestCase):
db_driver.consistency_group_create.assert_called_once_with(
self.context, expected_values)
def test_create_policy_check(self):
cg = fake_cg('fakeid',
user_id=self.context.user_id,
project_id=self.context.project_id,
status=constants.STATUS_CREATING)
self.mock_object(db_driver, 'consistency_group_create',
mock.Mock(return_value=cg))
self.api.create(self.context)
cg_api.policy.check_policy.assert_called_once_with(
self.context, 'consistency_group', 'create')
def test_create_request_spec(self):
"""Ensure the correct values are sent to the scheduler."""
cg = fake_cg('fakeid',
@ -498,18 +484,6 @@ class CGAPITestCase(test.TestCase):
db_driver.consistency_group_destroy.assert_called_once_with(
mock.ANY, cg['id'])
def test_delete_policy_check(self):
cg = fake_cg('fakeid',
user_id=self.context.user_id,
project_id=self.context.project_id,
status=constants.STATUS_CREATING)
self.mock_object(db_driver, 'consistency_group_destroy')
self.api.delete(self.context, cg)
cg_api.policy.check_policy.assert_called_once_with(
self.context, 'consistency_group', 'delete', cg)
def test_delete_creating_with_host(self):
cg = fake_cg('fakeid',
user_id=self.context.user_id,
@ -599,21 +573,6 @@ class CGAPITestCase(test.TestCase):
self.assertRaises(exception.InvalidConsistencyGroup, self.api.delete,
self.context, cg)
def test_update_policy_check(self):
cg = fake_cg('fakeid',
user_id=self.context.user_id,
project_id=self.context.project_id,
status=constants.STATUS_CREATING)
expected_values = {}
self.mock_object(db_driver, 'consistency_group_update',
mock.Mock(return_value=cg))
self.api.update(self.context, cg, expected_values)
cg_api.policy.check_policy.assert_called_once_with(
self.context, 'consistency_group', 'update', cg)
def test_update_no_values(self):
cg = fake_cg('fakeid',
user_id=self.context.user_id,
@ -660,19 +619,6 @@ class CGAPITestCase(test.TestCase):
db_driver.consistency_group_update.assert_called_once_with(
self.context, cg['id'], expected_values)
def test_get_policy_check(self):
cg = fake_cg('fakeid',
user_id=self.context.user_id,
project_id=self.context.project_id,
status=constants.STATUS_CREATING)
self.mock_object(db_driver, 'consistency_group_get',
mock.Mock(return_value=cg))
self.api.get(self.context, cg['id'])
cg_api.policy.check_policy.assert_called_once_with(
self.context, 'consistency_group', 'get')
def test_get(self):
expected_cg = fake_cg('fakeid',
user_id=self.context.user_id,
@ -684,15 +630,6 @@ class CGAPITestCase(test.TestCase):
actual_cg = self.api.get(self.context, expected_cg['id'])
self.assertEqual(expected_cg, actual_cg)
def test_get_all_policy_check(self):
self.mock_object(db_driver, 'consistency_group_get_all',
mock.Mock(return_value=[]))
self.api.get_all(self.context)
cg_api.policy.check_policy.assert_called_once_with(
self.context, 'consistency_group', 'get_all')
def test_get_all_no_cgs(self):
self.mock_object(db_driver, 'consistency_group_get_all',
@ -741,26 +678,6 @@ class CGAPITestCase(test.TestCase):
db_driver.consistency_group_get_all.assert_called_once_with(
self.context, detailed=True)
def test_create_cgsnapshot_policy_check(self):
cg = fake_cg('fake_cg_id',
user_id=self.context.user_id,
project_id=self.context.project_id,
status=constants.STATUS_AVAILABLE)
snap = fake_cgsnapshot('fakeid',
user_id=self.context.user_id,
project_id=self.context.project_id,
status=constants.STATUS_CREATING)
self.mock_object(db_driver, 'cgsnapshot_create',
mock.Mock(return_value=snap))
self.mock_object(db_driver, 'consistency_group_get',
mock.Mock(return_value=cg))
self.api.create_cgsnapshot(self.context)
cg_api.policy.check_policy.assert_called_once_with(
self.context, 'consistency_group', 'create_cgsnapshot')
def test_create_cgsnapshot_minimal_request_no_members(self):
cg = fake_cg('fake_cg_id',
user_id=self.context.user_id,
@ -1103,8 +1020,6 @@ class CGAPITestCase(test.TestCase):
self.api.delete_cgsnapshot(self.context, snap)
cg_api.policy.check_policy.assert_called_once_with(
self.context, 'consistency_group', 'delete_cgsnapshot', snap)
db_driver.consistency_group_get.assert_called_once_with(
self.context, "fake_id"
)
@ -1147,21 +1062,6 @@ class CGAPITestCase(test.TestCase):
self.context, "fake_id"
)
def test_update_cgsnapshot_policy_check(self):
snap = fake_cgsnapshot('fakeid',
user_id=self.context.user_id,
project_id=self.context.project_id,
status=constants.STATUS_CREATING)
expected_values = {}
self.mock_object(db_driver, 'cgsnapshot_update',
mock.Mock(return_value=snap))
self.api.update_cgsnapshot(self.context, snap, expected_values)
cg_api.policy.check_policy.assert_called_once_with(
self.context, 'consistency_group', 'update_cgsnapshot', snap)
def test_update_cgsnapshot_no_values(self):
snap = fake_cgsnapshot('fakeid',
user_id=self.context.user_id,
@ -1192,19 +1092,6 @@ class CGAPITestCase(test.TestCase):
db_driver.cgsnapshot_update.assert_called_once_with(
self.context, snap['id'], expected_values)
def test_cgsnapshot_get_policy_check(self):
snap = fake_cgsnapshot('fakeid',
user_id=self.context.user_id,
project_id=self.context.project_id,
status=constants.STATUS_CREATING)
self.mock_object(db_driver, 'cgsnapshot_get',
mock.Mock(return_value=snap))
self.api.get_cgsnapshot(self.context, snap['id'])
cg_api.policy.check_policy.assert_called_once_with(
self.context, 'consistency_group', 'get_cgsnapshot')
def test_cgsnapshot_get(self):
expected_snap = fake_cgsnapshot('fakeid',
user_id=self.context.user_id,
@ -1216,15 +1103,6 @@ class CGAPITestCase(test.TestCase):
actual_cg = self.api.get_cgsnapshot(self.context, expected_snap['id'])
self.assertEqual(expected_snap, actual_cg)
def test_cgsnapshot_get_all_policy_check(self):
self.mock_object(db_driver, 'cgsnapshot_get_all',
mock.Mock(return_value=[]))
self.api.get_all_cgsnapshots(self.context)
cg_api.policy.check_policy.assert_called_once_with(
self.context, 'consistency_group', 'get_all_cgsnapshots')
def test_cgsnapshot_get_all_no_cgs(self):
self.mock_object(db_driver, 'cgsnapshot_get_all',
@ -1273,15 +1151,6 @@ class CGAPITestCase(test.TestCase):
db_driver.cgsnapshot_get_all.assert_called_once_with(
self.context, detailed=True)
def test_get_all_cgsnapshot_members_policy_check(self):
self.mock_object(db_driver, 'cgsnapshot_members_get_all',
mock.Mock(return_value=[]))
self.api.get_all_cgsnapshot_members(self.context, 'fake_id')
cg_api.policy.check_policy.assert_called_once_with(
self.context, 'consistency_group', 'get_cgsnapshot')
def test_get_all_cgsnapshot_members(self):
self.mock_object(db_driver, 'cgsnapshot_members_get_all',
mock.Mock(return_value=[]))