Security service API

Added security service controller to
Manila v1 API.

Partially implements bp: join-tenant-network
Change-Id: Ic11feb44547bf438d925261b587edc828eac31c1
This commit is contained in:
Yulia Portnova 2014-01-10 15:11:47 +02:00 committed by Gerrit Code Review
parent 55f42ea27c
commit d68efa454c
13 changed files with 530 additions and 121 deletions

View File

@ -312,3 +312,18 @@ class MetadataTemplate(xmlutil.TemplateBuilder):
elem.set('key', 0)
elem.text = 1
return xmlutil.MasterTemplate(root, 1, nsmap=metadata_nsmap)
def remove_invalid_options(context, search_options, allowed_search_options):
"""Remove search options that are not valid for non-admin API/context."""
if context.is_admin:
# Allow all options
return
# Otherwise, strip out all unknown options
unknown_options = [opt for opt in search_options
if opt not in allowed_search_options]
bad_options = ", ".join(unknown_options)
log_msg = _("Removing options '%(bad_options)s' from query") % locals()
LOG.debug(log_msg)
for opt in unknown_options:
del search_options[opt]

View File

@ -26,6 +26,7 @@ import manila.api.openstack
from manila.api.v1 import limits
from manila.api import versions
from manila.api.v1 import security_service
from manila.api.v1 import share_metadata
from manila.api.v1 import share_snapshots
from manila.api.v1 import shares
@ -80,3 +81,8 @@ class APIRouter(manila.api.openstack.APIRouter):
self.resources['limits'] = limits.create_resource()
mapper.resource("limit", "limits",
controller=self.resources['limits'])
self.resources["security_services"] = \
security_service.create_resource()
mapper.resource("security-service", "security-services",
controller=self.resources['security_services'])

View File

@ -0,0 +1,205 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2014 Mirantis Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""The security service api."""
import webob
from webob import exc
from manila.api import common
from manila.api.openstack import wsgi
from manila.api.views import security_service as security_service_views
from manila.api import xmlutil
from manila.common import constants
from manila import db
from manila import exception
from manila.openstack.common import log as logging
from manila import policy
LOG = logging.getLogger(__name__)
def make_security_service(elem):
attrs = ['id', 'name', 'description', 'type', 'server', 'domain', 'sid',
'dns_ip', 'status', 'updated_at', 'created_at']
for attr in attrs:
elem.set(attr)
class SecurityServiceTemplate(xmlutil.TemplateBuilder):
def construct(self):
root = xmlutil.TemplateElement('security_service',
selector='security_service')
make_security_service(root)
return xmlutil.MasterTemplate(root, 1)
class SecurityServicesTemplate(xmlutil.TemplateBuilder):
def construct(self):
root = xmlutil.TemplateElement('security_services')
elem = xmlutil.SubTemplateElement(root, 'security_service',
selector='security_services')
make_security_service(elem)
return xmlutil.MasterTemplate(root, 1)
class SecurityServiceController(wsgi.Controller):
"""The Shares API controller for the OpenStack API."""
_view_builder_class = security_service_views.ViewBuilder
@wsgi.serializers(xml=SecurityServiceTemplate)
def show(self, req, id):
"""Return data about the given security service."""
context = req.environ['manila.context']
try:
security_service = db.security_service_get(context, id)
policy.check_policy(context, 'show', security_service)
except exception.NotFound:
raise exc.HTTPNotFound()
return self._view_builder.detail(req, security_service)
def delete(self, req, id):
"""Delete a security service."""
context = req.environ['manila.context']
LOG.audit(_("Delete security service with id: %s"),
id, context=context)
try:
security_service = db.security_service_get(context, id)
policy.check_policy(context, 'show', security_service)
db.security_service_delete(context, id)
except exception.NotFound:
raise exc.HTTPNotFound()
except exception.InvalidShare:
raise exc.HTTPForbidden()
return webob.Response(status_int=202)
@wsgi.serializers(xml=SecurityServicesTemplate)
def index(self, req):
"""Returns a summary list of security services."""
return self._get_security_services(req, is_detail=False)
@wsgi.serializers(xml=SecurityServicesTemplate)
def detail(self, req):
"""Returns a detailed list of security services."""
return self._get_security_services(req, is_detail=True)
def _get_security_services(self, req, is_detail):
"""Returns a list of security services, transformed through view
builder.
"""
context = req.environ['manila.context']
policy.check_policy(context, 'get_all_security_services')
search_opts = {}
search_opts.update(req.GET)
common.remove_invalid_options(
context, search_opts, self._get_security_services_search_options())
if 'all_tenants' in search_opts:
security_services = db.security_service_get_all(context)
del search_opts['all_tenants']
else:
security_services = db.security_service_get_all_by_project(
context, context.project_id)
if search_opts:
results = []
not_found = object()
for service in security_services:
for opt, value in search_opts.iteritems():
if service.get(opt, not_found) != value:
break
else:
results.append(service)
security_services = results
limited_list = common.limited(security_services, req)
if is_detail:
security_services = self._view_builder.detail_list(
req, limited_list)
else:
security_services = self._view_builder.summary_list(
req, limited_list)
return security_services
def _get_security_services_search_options(self):
return ('status', 'name', 'id')
@wsgi.serializers(xml=SecurityServicesTemplate)
def update(self, req, id, body):
"""Update a security service."""
context = req.environ['manila.context']
if not body or 'security_service' not in body:
raise exc.HTTPUnprocessableEntity()
security_service_data = body['security_service']
valid_update_keys = (
'description',
'name'
)
try:
security_service = db.security_service_get(context, id)
policy.check_policy(context, 'show', security_service)
except exception.NotFound:
raise exc.HTTPNotFound()
if security_service['status'].lower() in ['new', 'inactive']:
update_dict = security_service_data
else:
update_dict = dict([(key, security_service_data[key])
for key in valid_update_keys
if key in security_service_data])
security_service = db.security_service_update(context, id, update_dict)
return self._view_builder.detail(req, security_service)
@wsgi.serializers(xml=SecurityServicesTemplate)
def create(self, req, body):
"""Creates a new security service."""
context = req.environ['manila.context']
policy.check_policy(context, 'create')
if not self.is_valid_body(body, 'security_service'):
raise exc.HTTPUnprocessableEntity()
security_service_args = body['security_service']
security_srv_type = security_service_args.get('type')
allowed_types = constants.SECURITY_SERVICES_ALLOWED_TYPES
if security_srv_type not in allowed_types:
raise exception.InvalidInput(
reason=(_("Invalid type %(type)s specified for security "
"service. Valid types are %(types)s") %
{'type': security_srv_type,
'types': ','.join(allowed_types)}))
security_service_args['project_id'] = context.project_id
security_service = db.security_service_create(
context, security_service_args)
return self._view_builder.detail(req, security_service)
def create_resource():
return wsgi.Resource(SecurityServiceController())

View File

@ -19,9 +19,7 @@ import webob
from webob import exc
from manila.api import common
from manila.api import extensions
from manila.api.openstack import wsgi
from manila.api.v1 import shares
from manila.api.views import share_snapshots as snapshot_views
from manila.api import xmlutil
from manila import exception
@ -113,7 +111,7 @@ class ShareSnapshotsController(wsgi.Controller):
search_opts['display_name'] = search_opts['name']
del search_opts['name']
shares.remove_invalid_options(context, search_opts,
common.remove_invalid_options(context, search_opts,
self._get_snapshots_search_options())
snapshots = self.share_api.get_all_snapshots(context,

View File

@ -19,7 +19,6 @@ import webob
from webob import exc
from manila.api import common
from manila.api import extensions
from manila.api.openstack import wsgi
from manila.api.views import shares as share_views
from manila.api import xmlutil
@ -39,21 +38,6 @@ def make_share(elem):
elem.set(attr)
def remove_invalid_options(context, search_options, allowed_search_options):
"""Remove search options that are not valid for non-admin API/context."""
if context.is_admin:
# Allow all options
return
# Otherwise, strip out all unknown options
unknown_options = [opt for opt in search_options
if opt not in allowed_search_options]
bad_options = ", ".join(unknown_options)
log_msg = _("Removing options '%(bad_options)s' from query") % locals()
LOG.debug(log_msg)
for opt in unknown_options:
del search_options[opt]
class ShareTemplate(xmlutil.TemplateBuilder):
def construct(self):
root = xmlutil.TemplateElement('share', selector='share')
@ -130,8 +114,8 @@ class ShareController(wsgi.Controller):
search_opts['display_name'] = search_opts['name']
del search_opts['name']
remove_invalid_options(context, search_opts,
self._get_share_search_options())
common.remove_invalid_options(
context, search_opts, self._get_share_search_options())
shares = self.share_api.get_all(context, search_opts=search_opts)

View File

@ -0,0 +1,67 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 OpenStack LLC.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from manila.api import common
class ViewBuilder(common.ViewBuilder):
"""Model a server API response as a python dictionary."""
_collection_name = 'security_services'
def summary_list(self, request, security_services):
"""Show a list of security services without many details."""
return self._list_view(self.summary, request, security_services)
def detail_list(self, request, security_services):
"""Detailed view of a list of security services."""
return self._list_view(self.detail, request, security_services)
def summary(self, request, security_service):
"""Generic, non-detailed view of an security service."""
return {
'security_service': {
'id': security_service.get('id'),
'name': security_service.get('name'),
'status': security_service.get('status')
}
}
def detail(self, request, security_service):
"""Detailed view of a single security service."""
return {
'security_service': {
'id': security_service.get('id'),
'name': security_service.get('name'),
'created_at': security_service.get('created_at'),
'updated_at': security_service.get('updated_at'),
'status': security_service.get('status'),
'description': security_service.get('description'),
'dns_ip': security_service.get('dns_ip'),
'server': security_service.get('server'),
'domain': security_service.get('domain'),
'sid': security_service.get('sid'),
'type': security_service.get('type')
}
}
def _list_view(self, func, request, security_services):
"""Provide a view for a list of security services."""
security_services_list = [func(request, service)['security_service']
for service in security_services]
security_services_dict = dict(security_services=security_services_list)
return security_services_dict

View File

@ -20,3 +20,5 @@ STATUS_DELETED = 'DELETED'
STATUS_ERROR = 'ERROR'
STATUS_ACTIVE = 'ACTIVE'
STATUS_INACTIVE = 'INACTIVE'
SECURITY_SERVICES_ALLOWED_TYPES = ['active_directory', 'ldap', 'kerberos']

View File

@ -16,6 +16,7 @@
# under the License.
"""Policy Engine For Manila"""
import functools
from oslo.config import cfg
@ -103,3 +104,27 @@ def check_is_admin(roles):
credentials = {'roles': roles}
return policy.enforce(match_list, target, credentials)
def wrap_check_policy(func):
"""Check policy corresponding to the wrapped methods prior to execution.
This decorator requires the first 3 args of the wrapped function
to be (self, context, share).
"""
@functools.wraps(func)
def wrapped(self, context, target_obj, *args, **kwargs):
check_policy(context, func.__name__, target_obj)
return func(self, context, target_obj, *args, **kwargs)
return wrapped
def check_policy(context, action, target_obj=None):
target = {
'project_id': context.project_id,
'user_id': context.user_id,
}
target.update(target_obj or {})
_action = 'share:%s' % action
enforce(context, _action, target)

View File

@ -20,16 +20,12 @@
Handles all requests relating to shares.
"""
import functools
from manila.db import base
from manila import exception
from manila.image import glance
from manila.openstack.common import excutils
from manila.openstack.common import log as logging
from manila.openstack.common import rpc
from manila.openstack.common import timeutils
import manila.policy
from manila import policy
from manila import quota
from manila.scheduler import rpcapi as scheduler_rpcapi
from manila.share import rpcapi as share_rpcapi
@ -44,30 +40,6 @@ GB = 1048576 * 1024
QUOTAS = quota.QUOTAS
def wrap_check_policy(func):
"""Check policy corresponding to the wrapped methods prior to execution.
This decorator requires the first 3 args of the wrapped function
to be (self, context, share).
"""
@functools.wraps(func)
def wrapped(self, context, target_obj, *args, **kwargs):
check_policy(context, func.__name__, target_obj)
return func(self, context, target_obj, *args, **kwargs)
return wrapped
def check_policy(context, action, target_obj=None):
target = {
'project_id': context.project_id,
'user_id': context.user_id,
}
target.update(target_obj or {})
_action = 'share:%s' % action
manila.policy.enforce(context, _action, target)
class API(base.Base):
"""API for interacting with the share manager."""
@ -79,7 +51,7 @@ class API(base.Base):
def create(self, context, share_proto, size, name, description,
snapshot=None, availability_zone=None, metadata=None):
"""Create new share."""
check_policy(context, 'create')
policy.check_policy(context, 'create')
self._check_metadata_properties(context, metadata)
@ -190,7 +162,7 @@ class API(base.Base):
return share
@wrap_check_policy
@policy.wrap_check_policy
def delete(self, context, share):
"""Delete share."""
if context.is_admin and context.project_id != share['project_id']:
@ -231,7 +203,7 @@ class API(base.Base):
def create_snapshot(self, context, share, name, description,
force=False):
check_policy(context, 'create_snapshot', share)
policy.check_policy(context, 'create_snapshot', share)
if ((not force) and (share['status'] != "available")):
msg = _("must be available")
@ -291,7 +263,7 @@ class API(base.Base):
self.share_rpcapi.create_snapshot(context, share, snapshot)
return snapshot
@wrap_check_policy
@policy.wrap_check_policy
def delete_snapshot(self, context, snapshot, force=False):
if not force and snapshot['status'] not in ["available", "error"]:
msg = _("Share Snapshot status must be available or ")
@ -302,21 +274,21 @@ class API(base.Base):
share = self.db.share_get(context, snapshot['share_id'])
self.share_rpcapi.delete_snapshot(context, snapshot, share['host'])
@wrap_check_policy
@policy.wrap_check_policy
def update(self, context, share, fields):
return self.db.share_update(context, share['id'], fields)
@wrap_check_policy
@policy.wrap_check_policy
def snapshot_update(self, context, snapshot, fields):
return self.db.share_snapshot_update(context, snapshot['id'], fields)
def get(self, context, share_id):
rv = self.db.share_get(context, share_id)
check_policy(context, 'get', rv)
policy.check_policy(context, 'get', rv)
return rv
def get_all(self, context, search_opts={}):
check_policy(context, 'get_all')
policy.check_policy(context, 'get_all')
search_opts = search_opts or {}
@ -343,12 +315,12 @@ class API(base.Base):
return shares
def get_snapshot(self, context, snapshot_id):
check_policy(context, 'get_snapshot')
policy.check_policy(context, 'get_snapshot')
rv = self.db.share_snapshot_get(context, snapshot_id)
return dict(rv.iteritems())
def get_all_snapshots(self, context, search_opts=None):
check_policy(context, 'get_all_snapshots')
policy.check_policy(context, 'get_all_snapshots')
search_opts = search_opts or {}
@ -382,7 +354,7 @@ class API(base.Base):
if share['status'] not in ["available"]:
msg = _("Share status must be available")
raise exception.InvalidShare(reason=msg)
check_policy(ctx, 'allow_access')
policy.check_policy(ctx, 'allow_access')
values = {'share_id': share['id'],
'access_type': access_type,
'access_to': access_to}
@ -392,7 +364,7 @@ class API(base.Base):
def deny_access(self, ctx, share, access):
"""Deny access to share."""
check_policy(ctx, 'deny_access')
policy.check_policy(ctx, 'deny_access')
#First check state of the target share
if not share['host']:
msg = _("Share host is None")
@ -415,7 +387,7 @@ class API(base.Base):
def access_get_all(self, context, share):
"""Returns all access rules for share."""
check_policy(context, 'access_get_all')
policy.check_policy(context, 'access_get_all')
rules = self.db.share_access_get_all_for_share(context, share['id'])
return [{'id': rule.id,
'access_type': rule.access_type,
@ -424,17 +396,17 @@ class API(base.Base):
def access_get(self, context, access_id):
"""Returns access rule with the id."""
check_policy(context, 'access_get')
policy.check_policy(context, 'access_get')
rule = self.db.share_access_get(context, access_id)
return rule
@wrap_check_policy
@policy.wrap_check_policy
def get_share_metadata(self, context, share):
"""Get all metadata associated with a share."""
rv = self.db.share_metadata_get(context, share['id'])
return dict(rv.iteritems())
@wrap_check_policy
@policy.wrap_check_policy
def delete_share_metadata(self, context, share, key):
"""Delete the given metadata item from a share."""
self.db.share_metadata_delete(context, share['id'], key)
@ -458,7 +430,7 @@ class API(base.Base):
LOG.warn(msg)
raise exception.InvalidShareMetadataSize(message=msg)
@wrap_check_policy
@policy.wrap_check_policy
def update_share_metadata(self, context, share, metadata, delete=False):
"""Updates or creates share metadata.

View File

@ -0,0 +1,138 @@
# Copyright 2012 NetApp
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import mock
import webob
from manila.api.v1 import security_service
from manila.common import constants
from manila import db
from manila import exception
from manila import test
from manila.tests.api import fakes
class ShareApiTest(test.TestCase):
"""Share Api Test."""
def setUp(self):
super(ShareApiTest, self).setUp()
self.controller = security_service.SecurityServiceController()
self.maxDiff = None
self.security_service = {
"created_at": "fake-time",
"updated_at": "fake-time-2",
"id": 1,
"name": "fake-name",
"description": "Fake Security Service Desc",
"type": constants.SECURITY_SERVICES_ALLOWED_TYPES[0],
"dns_ip": "1.1.1.1",
"server": "fake-server",
"domain": "fake-domain",
"sid": "fake-sid",
"status": "new"
}
security_service.policy.check_policy = mock.Mock()
def test_security_service_show(self):
db.security_service_get = mock.Mock(return_value=self.security_service)
req = fakes.HTTPRequest.blank('/security-services/1')
res_dict = self.controller.show(req, '1')
expected = self.security_service.copy()
expected.update()
self.assertEqual(res_dict, {'security_service': self.security_service})
def test_security_service_show_not_found(self):
db.security_service_get = mock.Mock(side_effect=exception.NotFound)
req = fakes.HTTPRequest.blank('/shares/1')
self.assertRaises(webob.exc.HTTPNotFound,
self.controller.show,
req, '1')
def test_security_service_create(self):
sec_service = self.security_service.copy()
db.security_service_create = mock.Mock(
return_value=sec_service)
req = fakes.HTTPRequest.blank('/security-services')
res_dict = self.controller.create(
req, {"security_service": sec_service})
expected = self.security_service.copy()
self.assertEqual(res_dict, {'security_service': expected})
def test_security_service_create_invalid_types(self):
sec_service = self.security_service.copy()
sec_service['type'] = 'invalid'
req = fakes.HTTPRequest.blank('/security-services')
self.assertRaises(exception.InvalidInput, self.controller.create, req,
{"security_service": sec_service})
def test_create_security_service_no_body(self):
body = {}
req = fakes.HTTPRequest.blank('/security-services')
self.assertRaises(webob.exc.HTTPUnprocessableEntity,
self.controller.create,
req,
body)
def test_security_service_delete(self):
db.security_service_delete = mock.Mock()
db.security_service_get = mock.Mock()
req = fakes.HTTPRequest.blank('/shares/1')
resp = self.controller.delete(req, 1)
db.security_service_delete.assert_called_once_with(
req.environ['manila.context'], 1)
self.assertEqual(resp.status_int, 202)
def test_security_service_delete_not_found(self):
db.security_service_get = mock.Mock(side_effect=exception.NotFound)
req = fakes.HTTPRequest.blank('/security_services/1')
self.assertRaises(webob.exc.HTTPNotFound,
self.controller.delete,
req,
1)
def test_security_service_update_name(self):
new = self.security_service.copy()
updated = self.security_service.copy()
updated['name'] = 'new'
db.security_service_get = mock.Mock(return_value=new)
db.security_service_update = mock.Mock(return_value=updated)
body = {"security_service": {"name": "new"}}
req = fakes.HTTPRequest.blank('/security_service/1')
res_dict = self.controller.update(req, 1, body)['security_service']
self.assertEqual(res_dict['name'], updated['name'])
def test_security_service_update_description(self):
new = self.security_service.copy()
updated = self.security_service.copy()
updated['description'] = 'new'
db.security_service_get = mock.Mock(return_value=new)
db.security_service_update = mock.Mock(return_value=updated)
body = {"security_service": {"description": "new"}}
req = fakes.HTTPRequest.blank('/security_service/1')
res_dict = self.controller.update(req, 1, body)['security_service']
self.assertEqual(res_dict['description'], updated['description'])
def test_security_service_list(self):
db.security_service_get_all_by_project = mock.Mock(
return_value=[self.security_service.copy()])
req = fakes.HTTPRequest.blank('/security_services')
res_dict = self.controller.index(req)
expected = {'security_services': [
{'id': self.security_service['id'],
'name': self.security_service['name'],
'status': self.security_service['status']
}
]}
self.assertEqual(res_dict, expected)

View File

@ -17,6 +17,7 @@ import datetime
import webob
from manila.api import common
from manila.api.v1 import shares
from manila import context
from manila import exception
@ -268,7 +269,7 @@ class ShareApiTest(test.TestCase):
expected_opts = {'a': 'a', 'c': 'c'}
allowed_opts = ['a', 'c']
self.mox.ReplayAll()
shares.remove_invalid_options(ctx, search_opts, allowed_opts)
common.remove_invalid_options(ctx, search_opts, allowed_opts)
self.assertEqual(search_opts, expected_opts)
def test_remove_invalid_options_admin(self):
@ -277,5 +278,5 @@ class ShareApiTest(test.TestCase):
expected_opts = {'a': 'a', 'b': 'b', 'c': 'c', 'd': 'd'}
allowed_opts = ['a', 'c']
self.mox.ReplayAll()
shares.remove_invalid_options(ctx, search_opts, allowed_opts)
common.remove_invalid_options(ctx, search_opts, allowed_opts)
self.assertEqual(search_opts, expected_opts)

View File

@ -162,8 +162,8 @@ class ShareAPITestCase(test.TestCase):
'share_proto': share['share_proto'],
'export_location': share['export_location']}
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(self.context, 'create_snapshot', share)
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(self.context, 'create_snapshot', share)
self.mox.StubOutWithMock(quota.QUOTAS, 'reserve')
quota.QUOTAS.reserve(self.context, snapshots=1, gigabytes=1).\
AndReturn('reservation')
@ -182,8 +182,9 @@ class ShareAPITestCase(test.TestCase):
share = fake_share('fakeid')
snapshot = fake_snapshot('fakesnapshotid', share_id=share['id'],
status='available')
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(self.context, 'delete_snapshot', snapshot)
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(
self.context, 'delete_snapshot', snapshot)
self.mox.StubOutWithMock(db_driver, 'share_snapshot_update')
db_driver.share_snapshot_update(self.context, snapshot['id'],
{'status': 'deleting'})
@ -198,8 +199,9 @@ class ShareAPITestCase(test.TestCase):
def test_delete_snapshot_wrong_status(self):
snapshot = fake_snapshot('fakesnapshotid', share_id='fakeshareid',
status='creating')
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(self.context, 'delete_snapshot', snapshot)
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(
self.context, 'delete_snapshot', snapshot)
self.mox.ReplayAll()
self.assertRaises(exception.InvalidShareSnapshot,
self.api.delete_snapshot, self.context, snapshot)
@ -207,8 +209,8 @@ class ShareAPITestCase(test.TestCase):
def test_create_snapshot_if_share_not_available(self):
share = fake_share('fakeid',
status='error')
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(self.context, 'create_snapshot', share)
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(self.context, 'create_snapshot', share)
self.mox.ReplayAll()
self.assertRaises(exception.InvalidShare, self.api.create_snapshot,
self.context, share, 'fakename', 'fakedesc')
@ -246,8 +248,8 @@ class ShareAPITestCase(test.TestCase):
def test_get_snapshot(self):
fake_get_snap = {'fake_key': 'fake_val'}
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(self.context, 'get_snapshot')
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(self.context, 'get_snapshot')
self.mox.StubOutWithMock(db_driver, 'share_snapshot_get')
db_driver.share_snapshot_get(self.context,
'fakeid').AndReturn(fake_get_snap)
@ -338,24 +340,24 @@ class ShareAPITestCase(test.TestCase):
def test_get(self):
self.mox.StubOutWithMock(db_driver, 'share_get')
db_driver.share_get(self.context, 'fakeid').AndReturn('fakeshare')
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(self.context, 'get', 'fakeshare')
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(self.context, 'get', 'fakeshare')
self.mox.ReplayAll()
result = self.api.get(self.context, 'fakeid')
self.assertEqual(result, 'fakeshare')
def test_get_all_admin_not_all_tenants(self):
ctx = context.RequestContext('fakeuid', 'fakepid', id_admin=True)
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(ctx, 'get_all')
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(ctx, 'get_all')
self.mox.StubOutWithMock(db_driver, 'share_get_all_by_project')
db_driver.share_get_all_by_project(ctx, 'fakepid')
self.mox.ReplayAll()
self.api.get_all(ctx)
def test_get_all_admin_all_tenants(self):
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(self.context, 'get_all')
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(self.context, 'get_all')
self.mox.StubOutWithMock(db_driver, 'share_get_all')
db_driver.share_get_all(self.context)
self.mox.ReplayAll()
@ -363,8 +365,8 @@ class ShareAPITestCase(test.TestCase):
def test_get_all_not_admin(self):
ctx = context.RequestContext('fakeuid', 'fakepid', id_admin=False)
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(ctx, 'get_all')
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(ctx, 'get_all')
self.mox.StubOutWithMock(db_driver, 'share_get_all_by_project')
db_driver.share_get_all_by_project(ctx, 'fakepid')
self.mox.ReplayAll()
@ -374,8 +376,8 @@ class ShareAPITestCase(test.TestCase):
search_opts = {'size': 'fakesize'}
fake_objs = [{'name': 'fakename1'}, search_opts]
ctx = context.RequestContext('fakeuid', 'fakepid', id_admin=False)
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(ctx, 'get_all')
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(ctx, 'get_all')
self.mox.StubOutWithMock(db_driver, 'share_get_all_by_project')
db_driver.share_get_all_by_project(ctx,
'fakepid').AndReturn(fake_objs)
@ -385,8 +387,8 @@ class ShareAPITestCase(test.TestCase):
def test_get_all_snapshots_admin_not_all_tenants(self):
ctx = context.RequestContext('fakeuid', 'fakepid', id_admin=True)
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(ctx, 'get_all_snapshots')
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(ctx, 'get_all_snapshots')
self.mox.StubOutWithMock(db_driver,
'share_snapshot_get_all_by_project')
db_driver.share_snapshot_get_all_by_project(ctx, 'fakepid')
@ -394,8 +396,8 @@ class ShareAPITestCase(test.TestCase):
self.api.get_all_snapshots(ctx)
def test_get_all_snapshots_admin_all_tenants(self):
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(self.context, 'get_all_snapshots')
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(self.context, 'get_all_snapshots')
self.mox.StubOutWithMock(db_driver, 'share_snapshot_get_all')
db_driver.share_snapshot_get_all(self.context)
self.mox.ReplayAll()
@ -404,8 +406,8 @@ class ShareAPITestCase(test.TestCase):
def test_get_all_snapshots_not_admin(self):
ctx = context.RequestContext('fakeuid', 'fakepid', id_admin=False)
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(ctx, 'get_all_snapshots')
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(ctx, 'get_all_snapshots')
self.mox.StubOutWithMock(db_driver,
'share_snapshot_get_all_by_project')
db_driver.share_snapshot_get_all_by_project(ctx, 'fakepid')
@ -416,8 +418,8 @@ class ShareAPITestCase(test.TestCase):
search_opts = {'size': 'fakesize'}
fake_objs = [{'name': 'fakename1'}, search_opts]
ctx = context.RequestContext('fakeuid', 'fakepid', id_admin=False)
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(ctx, 'get_all_snapshots')
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(ctx, 'get_all_snapshots')
self.mox.StubOutWithMock(db_driver,
'share_snapshot_get_all_by_project')
db_driver.share_snapshot_get_all_by_project(ctx, 'fakepid').\
@ -431,8 +433,8 @@ class ShareAPITestCase(test.TestCase):
values = {'share_id': share['id'],
'access_type': 'fakeacctype',
'access_to': 'fakeaccto'}
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(self.context, 'allow_access')
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(self.context, 'allow_access')
self.mox.StubOutWithMock(db_driver, 'share_access_create')
db_driver.share_access_create(self.context, values).\
AndReturn('fakeacc')
@ -457,8 +459,8 @@ class ShareAPITestCase(test.TestCase):
def test_deny_access_error(self):
share = fake_share('fakeid', status='available')
access = fake_access('fakaccid', state='fakeerror')
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(self.context, 'deny_access')
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(self.context, 'deny_access')
self.mox.StubOutWithMock(db_driver, 'share_access_delete')
db_driver.share_access_delete(self.context, access['id'])
self.mox.ReplayAll()
@ -467,8 +469,8 @@ class ShareAPITestCase(test.TestCase):
def test_deny_access_active(self):
share = fake_share('fakeid', status='available')
access = fake_access('fakaccid', state='fakeactive')
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(self.context, 'deny_access')
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(self.context, 'deny_access')
self.mox.StubOutWithMock(db_driver, 'share_access_update')
db_driver.share_access_update(self.context, access['id'],
{'state': 'fakedeleting'})
@ -479,31 +481,31 @@ class ShareAPITestCase(test.TestCase):
def test_deny_access_not_active_not_error(self):
share = fake_share('fakeid', status='available')
access = fake_access('fakaccid', state='fakenew')
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(self.context, 'deny_access')
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(self.context, 'deny_access')
self.mox.ReplayAll()
self.assertRaises(exception.InvalidShareAccess, self.api.deny_access,
self.context, share, access)
def test_deny_access_status_not_available(self):
share = fake_share('fakeid', status='error')
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(self.context, 'deny_access')
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(self.context, 'deny_access')
self.mox.ReplayAll()
self.assertRaises(exception.InvalidShare, self.api.deny_access,
self.context, share, 'fakeacc')
def test_deny_access_no_host(self):
share = fake_share('fakeid', host=None)
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(self.context, 'deny_access')
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(self.context, 'deny_access')
self.mox.ReplayAll()
self.assertRaises(exception.InvalidShare, self.api.deny_access,
self.context, share, 'fakeacc')
def test_access_get(self):
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(self.context, 'access_get')
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(self.context, 'access_get')
self.mox.StubOutWithMock(db_driver, 'share_access_get')
db_driver.share_access_get(self.context, 'fakeid').AndReturn('fake')
self.mox.ReplayAll()
@ -512,8 +514,8 @@ class ShareAPITestCase(test.TestCase):
def test_access_get_all(self):
share = fake_share('fakeid')
self.mox.StubOutWithMock(share_api, 'check_policy')
share_api.check_policy(self.context, 'access_get_all')
self.mox.StubOutWithMock(share_api.policy, 'check_policy')
share_api.policy.check_policy(self.context, 'access_get_all')
self.mox.StubOutWithMock(db_driver, 'share_access_get_all_for_share')
db_driver.share_access_get_all_for_share(self.context, 'fakeid').\
AndReturn([fake_access('fakeacc0id', state='fakenew'),

View File

@ -25,7 +25,6 @@ import errno
import functools
import hashlib
import inspect
import itertools
import os
import paramiko
import pyclbr
@ -34,27 +33,22 @@ import re
import shlex
import shutil
import signal
import socket
import struct
import sys
import tempfile
import time
import types
import warnings
from xml.dom import minidom
from xml.parsers import expat
from xml import sax
from xml.sax import expatreader
from xml.sax import saxutils
from oslo.config import cfg
from eventlet import event
from eventlet.green import subprocess
from eventlet import greenthread
from eventlet import pools
from oslo.config import cfg
from manila import exception
from manila.openstack.common import excutils
from manila.openstack.common import importutils
from manila.openstack.common import lockutils