Merge "Port admin actions extension to core API"
This commit is contained in:
commit
01ef190d9b
@ -23,11 +23,6 @@
|
||||
"share:get_all": "rule:default",
|
||||
"share:list_by_share_server_id": "rule:admin_api",
|
||||
"share:update": "rule:default",
|
||||
"share:snapshot_update": "rule:default",
|
||||
"share:create_snapshot": "rule:default",
|
||||
"share:delete_snapshot": "rule:default",
|
||||
"share:get_snapshot": "rule:default",
|
||||
"share:get_all_snapshots": "rule:default",
|
||||
"share:access_get": "rule:default",
|
||||
"share:access_get_all": "rule:default",
|
||||
"share:allow_access": "rule:default",
|
||||
@ -40,30 +35,28 @@
|
||||
"share:migrate": "rule:admin_api",
|
||||
"share:manage": "rule:admin_api",
|
||||
"share:unmanage": "rule:admin_api",
|
||||
"share:force_delete": "rule:admin_api",
|
||||
"share:reset_status": "rule:admin_api",
|
||||
|
||||
"share_instance:index": "rule:admin_api",
|
||||
"share_instance:show": "rule:admin_api",
|
||||
"share_instance:force_delete": "rule:admin_api",
|
||||
"share_instance:reset_status": "rule:admin_api",
|
||||
|
||||
"share_snapshot:create_snapshot": "rule:default",
|
||||
"share_snapshot:delete_snapshot": "rule:default",
|
||||
"share_snapshot:get_snapshot": "rule:default",
|
||||
"share_snapshot:get_all_snapshots": "rule:default",
|
||||
"share_snapshot:snapshot_update": "rule:default",
|
||||
"share_snapshot:force_delete": "rule:admin_api",
|
||||
"share_snapshot:reset_status": "rule:admin_api",
|
||||
|
||||
"share_type:index": "rule:default",
|
||||
"share_type:show": "rule:default",
|
||||
"share_type:default": "rule:default",
|
||||
|
||||
"share_instance:index": "rule:admin_api",
|
||||
"share_instance:show": "rule:admin_api",
|
||||
|
||||
"share_extension:share_admin_actions:force_delete": "rule:admin_api",
|
||||
"share_extension:share_admin_actions:reset_status": "rule:admin_api",
|
||||
"share_extension:snapshot_admin_actions:force_delete": "rule:admin_api",
|
||||
"share_extension:snapshot_admin_actions:reset_status": "rule:admin_api",
|
||||
"share_extension:share_instance_admin_actions:force_delete": "rule:admin_api",
|
||||
"share_extension:share_instance_admin_actions:reset_status": "rule:admin_api",
|
||||
"share_extension:consistency_group_admin_actions:force_delete": "rule:admin_api",
|
||||
"share_extension:consistency_group_admin_actions:reset_status": "rule:admin_api",
|
||||
"share_extension:cgsnapshot_admin_actions:force_delete": "rule:admin_api",
|
||||
"share_extension:cgsnapshot_admin_actions:reset_status": "rule:admin_api",
|
||||
|
||||
"share_extension:availability_zones": "",
|
||||
|
||||
"share_extension:types_manage": "rule:admin_api",
|
||||
"share_extension:types_extra_specs": "rule:admin_api",
|
||||
|
||||
"share_extension:share_type_access": "",
|
||||
"share_extension:share_type_access:addProjectAccess": "rule:admin_api",
|
||||
"share_extension:share_type_access:removeProjectAccess": "rule:admin_api",
|
||||
@ -99,9 +92,13 @@
|
||||
"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"
|
||||
"consistency_group:get_all_cgsnapshots": "rule:default",
|
||||
|
||||
"cgsnapshot:force_delete": "rule:admin_api",
|
||||
"cgsnapshot:reset_status": "rule:admin_api"
|
||||
}
|
||||
|
@ -1,230 +0,0 @@
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
#
|
||||
# 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 oslo_log import log
|
||||
import six
|
||||
import webob
|
||||
from webob import exc
|
||||
|
||||
from manila.api import extensions
|
||||
from manila.api.openstack import wsgi
|
||||
from manila.common import constants
|
||||
import manila.consistency_group.api as cg_api
|
||||
from manila import db
|
||||
from manila import exception
|
||||
from manila import share
|
||||
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class AdminController(wsgi.Controller):
|
||||
"""Abstract base class for AdminControllers."""
|
||||
|
||||
collection = None
|
||||
|
||||
valid_status = set([
|
||||
constants.STATUS_CREATING,
|
||||
constants.STATUS_AVAILABLE,
|
||||
constants.STATUS_DELETING,
|
||||
constants.STATUS_ERROR,
|
||||
constants.STATUS_ERROR_DELETING,
|
||||
])
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(AdminController, self).__init__(*args, **kwargs)
|
||||
self.resource_name = self.collection.rstrip('s').replace('-', '_')
|
||||
self.share_api = share.API()
|
||||
self.cg_api = cg_api.API()
|
||||
|
||||
def _update(self, *args, **kwargs):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _get(self, *args, **kwargs):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _delete(self, *args, **kwargs):
|
||||
raise NotImplementedError()
|
||||
|
||||
def validate_update(self, body):
|
||||
update = {}
|
||||
try:
|
||||
update['status'] = body['status']
|
||||
except (TypeError, KeyError):
|
||||
raise exc.HTTPBadRequest(explanation="Must specify 'status'")
|
||||
if update['status'] not in self.valid_status:
|
||||
expl = "Invalid state. Valid states: " +\
|
||||
', '.join(self.valid_status) + '.'
|
||||
raise exc.HTTPBadRequest(explanation=expl)
|
||||
return update
|
||||
|
||||
def authorize(self, context, action_name):
|
||||
action = '%s_admin_actions:%s' % (self.resource_name, action_name)
|
||||
extensions.extension_authorizer('share', action)(context)
|
||||
|
||||
@wsgi.action('os-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,
|
||||
'update': update})
|
||||
try:
|
||||
self._update(context, id, update)
|
||||
except exception.NotFound as e:
|
||||
raise exc.HTTPNotFound(six.text_type(e))
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
@wsgi.action('os-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:
|
||||
raise exc.HTTPNotFound(six.text_type(e))
|
||||
self._delete(context, resource, force=True)
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
|
||||
class ShareAdminController(AdminController):
|
||||
"""AdminController for Shares."""
|
||||
|
||||
collection = 'shares'
|
||||
|
||||
def _update(self, *args, **kwargs):
|
||||
db.share_update(*args, **kwargs)
|
||||
|
||||
def _get(self, *args, **kwargs):
|
||||
return self.share_api.get(*args, **kwargs)
|
||||
|
||||
def _delete(self, *args, **kwargs):
|
||||
return self.share_api.delete(*args, **kwargs)
|
||||
|
||||
def _migrate(self, *args, **kwargs):
|
||||
return self.share_api.migrate_share(*args, **kwargs)
|
||||
|
||||
|
||||
class ShareInstancesAdminController(AdminController):
|
||||
"""AdminController for Share instances."""
|
||||
|
||||
collection = 'share_instances'
|
||||
|
||||
def _get(self, *args, **kwargs):
|
||||
return db.share_instance_get(*args, **kwargs)
|
||||
|
||||
def _update(self, *args, **kwargs):
|
||||
db.share_instance_update(*args, **kwargs)
|
||||
|
||||
def _delete(self, *args, **kwargs):
|
||||
return self.share_api.delete_instance(*args, **kwargs)
|
||||
|
||||
|
||||
class SnapshotAdminController(AdminController):
|
||||
"""AdminController for Snapshots."""
|
||||
|
||||
collection = 'snapshots'
|
||||
|
||||
def _update(self, *args, **kwargs):
|
||||
db.share_snapshot_update(*args, **kwargs)
|
||||
|
||||
def _get(self, *args, **kwargs):
|
||||
return self.share_api.get_snapshot(*args, **kwargs)
|
||||
|
||||
def _delete(self, *args, **kwargs):
|
||||
return self.share_api.delete_snapshot(*args, **kwargs)
|
||||
|
||||
|
||||
class CGAdminController(AdminController):
|
||||
"""AdminController for Consistency Groups."""
|
||||
|
||||
collection = 'consistency-groups'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(CGAdminController, self).__init__(*args, **kwargs)
|
||||
self.cg_api = cg_api.API()
|
||||
|
||||
def _update(self, *args, **kwargs):
|
||||
db.consistency_group_update(*args, **kwargs)
|
||||
|
||||
def _get(self, *args, **kwargs):
|
||||
return self.cg_api.get(*args, **kwargs)
|
||||
|
||||
def _delete(self, context, resource, force=True):
|
||||
db.consistency_group_destroy(context.elevated(), resource['id'])
|
||||
|
||||
@wsgi.Controller.api_version('2.4', experimental=True)
|
||||
@wsgi.action('os-reset_status')
|
||||
@wsgi.response(202)
|
||||
def cg_reset_status(self, req, id, body):
|
||||
super(CGAdminController, self)._reset_status(req, id, body)
|
||||
|
||||
@wsgi.Controller.api_version('2.4', experimental=True)
|
||||
@wsgi.action('os-force_delete')
|
||||
@wsgi.response(202)
|
||||
def cg_force_delete(self, req, id, body):
|
||||
super(CGAdminController, self)._force_delete(req, id, body)
|
||||
|
||||
|
||||
class CGSnapshotAdminController(AdminController):
|
||||
"""AdminController for CGSnapshots."""
|
||||
|
||||
collection = 'cgsnapshots'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(CGSnapshotAdminController, self).__init__(*args, **kwargs)
|
||||
self.cg_api = cg_api.API()
|
||||
|
||||
def _update(self, *args, **kwargs):
|
||||
db.cgsnapshot_update(*args, **kwargs)
|
||||
|
||||
def _get(self, *args, **kwargs):
|
||||
return self.cg_api.get_cgsnapshot(*args, **kwargs)
|
||||
|
||||
def _delete(self, context, resource, force=True):
|
||||
db.cgsnapshot_destroy(context.elevated(), resource['id'])
|
||||
|
||||
@wsgi.Controller.api_version('2.4', experimental=True)
|
||||
@wsgi.action('os-reset_status')
|
||||
@wsgi.response(202)
|
||||
def cgsnapshot_reset_status(self, req, id, body):
|
||||
super(CGSnapshotAdminController, self)._reset_status(req, id, body)
|
||||
|
||||
@wsgi.Controller.api_version('2.4', experimental=True)
|
||||
@wsgi.action('os-force_delete')
|
||||
@wsgi.response(202)
|
||||
def cgsnapshot_force_delete(self, req, id, body):
|
||||
super(CGSnapshotAdminController, self)._force_delete(req, id, body)
|
||||
|
||||
|
||||
class Admin_actions(extensions.ExtensionDescriptor):
|
||||
"""Enable admin actions."""
|
||||
|
||||
name = "AdminActions"
|
||||
alias = "os-admin-actions"
|
||||
updated = "2015-09-01T00:00:00+00:00"
|
||||
|
||||
def get_controller_extensions(self):
|
||||
exts = []
|
||||
for class_ in (ShareAdminController, SnapshotAdminController,
|
||||
ShareInstancesAdminController,
|
||||
CGAdminController, CGSnapshotAdminController):
|
||||
controller = class_()
|
||||
extension = extensions.ControllerExtension(
|
||||
self, class_.collection, controller)
|
||||
exts.append(extension)
|
||||
return exts
|
@ -27,6 +27,7 @@ import webob.exc
|
||||
|
||||
from manila.api.openstack import api_version_request as api_version
|
||||
from manila.api.openstack import versioned_method
|
||||
from manila.common import constants
|
||||
from manila import exception
|
||||
from manila.i18n import _
|
||||
from manila.i18n import _LE
|
||||
@ -1135,6 +1136,66 @@ class Controller(object):
|
||||
return True
|
||||
|
||||
|
||||
class AdminActionsMixin(object):
|
||||
"""Mixin class for API controllers with admin actions."""
|
||||
|
||||
valid_statuses = set([
|
||||
constants.STATUS_CREATING,
|
||||
constants.STATUS_AVAILABLE,
|
||||
constants.STATUS_DELETING,
|
||||
constants.STATUS_ERROR,
|
||||
constants.STATUS_ERROR_DELETING,
|
||||
])
|
||||
|
||||
def _update(self, *args, **kwargs):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _get(self, *args, **kwargs):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _delete(self, *args, **kwargs):
|
||||
raise NotImplementedError()
|
||||
|
||||
def validate_update(self, body):
|
||||
update = {}
|
||||
try:
|
||||
update['status'] = body['status']
|
||||
except (TypeError, KeyError):
|
||||
raise webob.exc.HTTPBadRequest(explanation="Must specify 'status'")
|
||||
if update['status'] not in self.valid_statuses:
|
||||
expl = _("Invalid state. Valid states: " +
|
||||
", ".join(self.valid_statuses) + ".")
|
||||
raise webob.exc.HTTPBadRequest(explanation=expl)
|
||||
return update
|
||||
|
||||
@action('os-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,
|
||||
'update': update})
|
||||
try:
|
||||
self._update(context, id, update)
|
||||
except exception.NotFound as e:
|
||||
raise webob.exc.HTTPNotFound(six.text_type(e))
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
@action('os-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:
|
||||
raise webob.exc.HTTPNotFound(six.text_type(e))
|
||||
self._delete(context, resource, force=True)
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
|
||||
class Fault(webob.exc.HTTPException):
|
||||
"""Wrap webob.exc.HTTPException to provide API friendly response."""
|
||||
|
||||
|
@ -25,6 +25,7 @@ from manila.api import common
|
||||
from manila.api.openstack import wsgi
|
||||
import manila.api.views.cgsnapshots as cg_views
|
||||
import manila.consistency_group.api as cg_api
|
||||
from manila import db
|
||||
from manila import exception
|
||||
from manila.i18n import _
|
||||
from manila.i18n import _LI
|
||||
@ -32,9 +33,10 @@ from manila.i18n import _LI
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class CGSnapshotController(wsgi.Controller):
|
||||
class CGSnapshotController(wsgi.Controller, wsgi.AdminActionsMixin):
|
||||
"""The Consistency Group Snapshots API controller for the OpenStack API."""
|
||||
|
||||
resource_name = 'cgsnapshot'
|
||||
_view_builder_class = cg_views.CGSnapshotViewBuilder
|
||||
|
||||
def __init__(self):
|
||||
@ -193,6 +195,27 @@ class CGSnapshotController(wsgi.Controller):
|
||||
snaps = self._view_builder.member_list(req, limited_list)
|
||||
return snaps
|
||||
|
||||
def _update(self, *args, **kwargs):
|
||||
db.cgsnapshot_update(*args, **kwargs)
|
||||
|
||||
def _get(self, *args, **kwargs):
|
||||
return self.cg_api.get_cgsnapshot(*args, **kwargs)
|
||||
|
||||
def _delete(self, context, resource, force=True):
|
||||
db.cgsnapshot_destroy(context.elevated(), resource['id'])
|
||||
|
||||
@wsgi.Controller.api_version('2.4', experimental=True)
|
||||
@wsgi.action('os-reset_status')
|
||||
@wsgi.response(202)
|
||||
def cgsnapshot_reset_status(self, req, id, body):
|
||||
super(self.__class__, self)._reset_status(req, id, body)
|
||||
|
||||
@wsgi.Controller.api_version('2.4', experimental=True)
|
||||
@wsgi.action('os-force_delete')
|
||||
@wsgi.response(202)
|
||||
def cgsnapshot_force_delete(self, req, id, body):
|
||||
super(self.__class__, self)._force_delete(req, id, body)
|
||||
|
||||
|
||||
def create_resource():
|
||||
return wsgi.Resource(CGSnapshotController())
|
||||
|
@ -25,6 +25,7 @@ from manila.api import common
|
||||
from manila.api.openstack import wsgi
|
||||
import manila.api.views.consistency_groups as cg_views
|
||||
import manila.consistency_group.api as cg_api
|
||||
from manila import db
|
||||
from manila import exception
|
||||
from manila.i18n import _
|
||||
from manila.i18n import _LI
|
||||
@ -33,9 +34,10 @@ from manila.share import share_types
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class CGController(wsgi.Controller):
|
||||
class CGController(wsgi.Controller, wsgi.AdminActionsMixin):
|
||||
"""The Consistency Groups API controller for the OpenStack API."""
|
||||
|
||||
resource_name = 'consistency_group'
|
||||
_view_builder_class = cg_views.CGViewBuilder
|
||||
|
||||
def __init__(self):
|
||||
@ -206,6 +208,27 @@ class CGController(wsgi.Controller):
|
||||
|
||||
return self._view_builder.detail(req, dict(six.iteritems(new_cg)))
|
||||
|
||||
def _update(self, *args, **kwargs):
|
||||
db.consistency_group_update(*args, **kwargs)
|
||||
|
||||
def _get(self, *args, **kwargs):
|
||||
return self.cg_api.get(*args, **kwargs)
|
||||
|
||||
def _delete(self, context, resource, force=True):
|
||||
db.consistency_group_destroy(context.elevated(), resource['id'])
|
||||
|
||||
@wsgi.Controller.api_version('2.4', experimental=True)
|
||||
@wsgi.action('os-reset_status')
|
||||
@wsgi.response(202)
|
||||
def cg_reset_status(self, req, id, body):
|
||||
super(self.__class__, self)._reset_status(req, id, body)
|
||||
|
||||
@wsgi.Controller.api_version('2.4', experimental=True)
|
||||
@wsgi.action('os-force_delete')
|
||||
@wsgi.response(202)
|
||||
def cg_force_delete(self, req, id, body):
|
||||
super(self.__class__, self)._force_delete(req, id, body)
|
||||
|
||||
|
||||
def create_resource():
|
||||
return wsgi.Resource(CGController())
|
||||
|
@ -22,7 +22,7 @@ from manila import exception
|
||||
from manila import share
|
||||
|
||||
|
||||
class ShareInstancesController(wsgi.Controller):
|
||||
class ShareInstancesController(wsgi.Controller, wsgi.AdminActionsMixin):
|
||||
"""The share instances API controller for the OpenStack API."""
|
||||
|
||||
resource_name = 'share_instance'
|
||||
@ -30,7 +30,16 @@ class ShareInstancesController(wsgi.Controller):
|
||||
|
||||
def __init__(self):
|
||||
self.share_api = share.API()
|
||||
super(ShareInstancesController, self).__init__()
|
||||
super(self.__class__, self).__init__()
|
||||
|
||||
def _get(self, *args, **kwargs):
|
||||
return db.share_instance_get(*args, **kwargs)
|
||||
|
||||
def _update(self, *args, **kwargs):
|
||||
db.share_instance_update(*args, **kwargs)
|
||||
|
||||
def _delete(self, *args, **kwargs):
|
||||
return self.share_api.delete_instance(*args, **kwargs)
|
||||
|
||||
@wsgi.Controller.api_version("2.3")
|
||||
def index(self, req):
|
||||
@ -65,6 +74,18 @@ class ShareInstancesController(wsgi.Controller):
|
||||
view = instance_view.ViewBuilder()
|
||||
return view.detail_list(req, share.instances)
|
||||
|
||||
@wsgi.Controller.api_version('2.3')
|
||||
@wsgi.action('os-reset_status')
|
||||
@wsgi.response(202)
|
||||
def share_instance_reset_status(self, req, id, body):
|
||||
super(self.__class__, self)._reset_status(req, id, body)
|
||||
|
||||
@wsgi.Controller.api_version('2.3')
|
||||
@wsgi.action('os-force_delete')
|
||||
@wsgi.response(202)
|
||||
def share_instance_force_delete(self, req, id, body):
|
||||
super(self.__class__, self)._force_delete(req, id, body)
|
||||
|
||||
|
||||
def create_resource():
|
||||
return wsgi.Resource(ShareInstancesController())
|
||||
|
@ -23,6 +23,7 @@ from webob import exc
|
||||
from manila.api import common
|
||||
from manila.api.openstack import wsgi
|
||||
from manila.api.views import share_snapshots as snapshot_views
|
||||
from manila import db
|
||||
from manila import exception
|
||||
from manila.i18n import _, _LI
|
||||
from manila import share
|
||||
@ -30,15 +31,35 @@ from manila import share
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class ShareSnapshotsController(wsgi.Controller):
|
||||
class ShareSnapshotsController(wsgi.Controller, wsgi.AdminActionsMixin):
|
||||
"""The Share Snapshots API controller for the OpenStack API."""
|
||||
|
||||
resource_name = 'share_snapshot'
|
||||
_view_builder_class = snapshot_views.ViewBuilder
|
||||
|
||||
def __init__(self):
|
||||
super(ShareSnapshotsController, self).__init__()
|
||||
self.share_api = share.API()
|
||||
|
||||
def _update(self, *args, **kwargs):
|
||||
db.share_snapshot_update(*args, **kwargs)
|
||||
|
||||
def _get(self, *args, **kwargs):
|
||||
return self.share_api.get_snapshot(*args, **kwargs)
|
||||
|
||||
def _delete(self, *args, **kwargs):
|
||||
return self.share_api.delete_snapshot(*args, **kwargs)
|
||||
|
||||
@wsgi.action('os-reset_status')
|
||||
@wsgi.response(202)
|
||||
def share_snapshot_reset_status(self, req, id, body):
|
||||
super(self.__class__, self)._reset_status(req, id, body)
|
||||
|
||||
@wsgi.action('os-force_delete')
|
||||
@wsgi.response(202)
|
||||
def share_snapshot_force_delete(self, req, id, body):
|
||||
super(self.__class__, self)._force_delete(req, id, body)
|
||||
|
||||
def show(self, req, id):
|
||||
"""Return data about the given snapshot."""
|
||||
context = req.environ['manila.context']
|
||||
|
@ -38,15 +38,38 @@ from manila.share import share_types
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class ShareController(wsgi.Controller):
|
||||
class ShareController(wsgi.Controller, wsgi.AdminActionsMixin):
|
||||
"""The Shares API controller for the OpenStack API."""
|
||||
|
||||
resource_name = 'share'
|
||||
_view_builder_class = share_views.ViewBuilder
|
||||
|
||||
def __init__(self):
|
||||
super(ShareController, self).__init__()
|
||||
self.share_api = share.API()
|
||||
|
||||
def _update(self, *args, **kwargs):
|
||||
db.share_update(*args, **kwargs)
|
||||
|
||||
def _get(self, *args, **kwargs):
|
||||
return self.share_api.get(*args, **kwargs)
|
||||
|
||||
def _delete(self, *args, **kwargs):
|
||||
return self.share_api.delete(*args, **kwargs)
|
||||
|
||||
def _migrate(self, *args, **kwargs):
|
||||
return self.share_api.migrate_share(*args, **kwargs)
|
||||
|
||||
@wsgi.action('os-reset_status')
|
||||
@wsgi.response(202)
|
||||
def share_reset_status(self, req, id, body):
|
||||
super(self.__class__, self)._reset_status(req, id, body)
|
||||
|
||||
@wsgi.action('os-force_delete')
|
||||
@wsgi.response(202)
|
||||
def share_force_delete(self, req, id, body):
|
||||
super(self.__class__, self)._force_delete(req, id, body)
|
||||
|
||||
def show(self, req, id):
|
||||
"""Return data about the given share."""
|
||||
context = req.environ['manila.context']
|
||||
|
@ -702,13 +702,13 @@ class API(base.Base):
|
||||
return shares
|
||||
|
||||
def get_snapshot(self, context, snapshot_id):
|
||||
policy.check_policy(context, 'share', 'get_snapshot')
|
||||
policy.check_policy(context, 'share_snapshot', 'get_snapshot')
|
||||
rv = self.db.share_snapshot_get(context, snapshot_id)
|
||||
return dict(six.iteritems(rv))
|
||||
|
||||
def get_all_snapshots(self, context, search_opts=None,
|
||||
sort_key='share_id', sort_dir='desc'):
|
||||
policy.check_policy(context, 'share', 'get_all_snapshots')
|
||||
policy.check_policy(context, 'share_snapshot', 'get_all_snapshots')
|
||||
|
||||
search_opts = search_opts or {}
|
||||
LOG.debug("Searching for snapshots by: %s", six.text_type(search_opts))
|
||||
|
@ -1,308 +0,0 @@
|
||||
# Copyright 2013 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.
|
||||
|
||||
import ddt
|
||||
from oslo_config import cfg
|
||||
from oslo_serialization import jsonutils
|
||||
import six
|
||||
import webob
|
||||
|
||||
from manila.api.openstack import wsgi
|
||||
from manila.common import constants
|
||||
from manila import context
|
||||
from manila import db
|
||||
from manila import exception
|
||||
from manila.share import api as share_api
|
||||
from manila import test
|
||||
from manila.tests.api import fakes
|
||||
from manila.tests import db_utils
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
def app():
|
||||
# no auth, just let environ['manila.context'] pass through
|
||||
api = fakes.router.APIRouter()
|
||||
mapper = fakes.urlmap.URLMap()
|
||||
mapper['/v2'] = api
|
||||
return mapper
|
||||
|
||||
|
||||
fixture_reset_status_with_different_roles = (
|
||||
{'role': 'admin', 'valid_code': 202,
|
||||
'valid_status': constants.STATUS_ERROR},
|
||||
{'role': 'member', 'valid_code': 403,
|
||||
'valid_status': constants.STATUS_AVAILABLE}
|
||||
)
|
||||
|
||||
fixture_force_delete_with_different_roles = (
|
||||
{'role': 'admin', 'resp_code': 202},
|
||||
{'role': 'member', 'resp_code': 403},
|
||||
)
|
||||
|
||||
fixture_invalid_reset_status_body = (
|
||||
{'os-reset_status': {'x-status': 'bad'}},
|
||||
{'os-reset_status': {'status': 'invalid'}}
|
||||
)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class AdminActionsTest(test.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(AdminActionsTest, self).setUp()
|
||||
self.flags(rpc_backend='manila.openstack.common.rpc.impl_fake')
|
||||
self.share_api = share_api.API()
|
||||
self.admin_context = context.RequestContext('admin', 'fake', True)
|
||||
self.member_context = context.RequestContext('fake', 'fake')
|
||||
|
||||
def _get_context(self, role):
|
||||
return getattr(self, '%s_context' % role)
|
||||
|
||||
def _setup_share_data(self, share=None):
|
||||
if share is None:
|
||||
share = db_utils.create_share(status=constants.STATUS_AVAILABLE,
|
||||
size='1',
|
||||
override_defaults=True)
|
||||
req = webob.Request.blank('/v2/fake/shares/%s/action' % share['id'])
|
||||
return share, req
|
||||
|
||||
def _setup_snapshot_data(self, snapshot=None):
|
||||
if snapshot is None:
|
||||
share = db_utils.create_share()
|
||||
snapshot = db_utils.create_snapshot(
|
||||
status=constants.STATUS_AVAILABLE, share_id=share['id'])
|
||||
req = webob.Request.blank('/v2/fake/snapshots/%s/action' %
|
||||
snapshot['id'])
|
||||
return snapshot, req
|
||||
|
||||
def _setup_share_instance_data(self, instance=None):
|
||||
if instance is None:
|
||||
instance = db_utils.create_share(status=constants.STATUS_AVAILABLE,
|
||||
size='1').instance
|
||||
req = webob.Request.blank(
|
||||
'/v2/fake/share_instances/%s/action' % instance['id'])
|
||||
return instance, req
|
||||
|
||||
def _setup_cg_data(self, cg=None):
|
||||
if cg is None:
|
||||
cg = db_utils.create_consistency_group(
|
||||
status=constants.STATUS_AVAILABLE)
|
||||
req = webob.Request.blank('/v2/fake/consistency-groups/%s/action' %
|
||||
cg['id'])
|
||||
req.headers[wsgi.API_VERSION_REQUEST_HEADER] = '2.4'
|
||||
req.headers[wsgi.EXPERIMENTAL_API_REQUEST_HEADER] = 'True'
|
||||
|
||||
return cg, req
|
||||
|
||||
def _setup_cgsnapshot_data(self, cgsnapshot=None):
|
||||
if cgsnapshot is None:
|
||||
cgsnapshot = db_utils.create_cgsnapshot(
|
||||
'fake_id', status=constants.STATUS_AVAILABLE)
|
||||
req = webob.Request.blank('/v2/fake/cgsnapshots/%s/action' %
|
||||
cgsnapshot['id'])
|
||||
req.headers[wsgi.API_VERSION_REQUEST_HEADER] = '2.4'
|
||||
req.headers[wsgi.EXPERIMENTAL_API_REQUEST_HEADER] = 'True'
|
||||
return cgsnapshot, req
|
||||
|
||||
def _reset_status(self, ctxt, model, req, db_access_method,
|
||||
valid_code, valid_status=None, body=None):
|
||||
if body is None:
|
||||
body = {'os-reset_status': {'status': constants.STATUS_ERROR}}
|
||||
req.method = 'POST'
|
||||
req.headers['content-type'] = 'application/json'
|
||||
req.body = six.b(jsonutils.dumps(body))
|
||||
req.environ['manila.context'] = ctxt
|
||||
|
||||
resp = req.get_response(app())
|
||||
|
||||
# validate response code and model status
|
||||
self.assertEqual(valid_code, resp.status_int)
|
||||
|
||||
if valid_code == 404:
|
||||
self.assertRaises(exception.NotFound,
|
||||
db_access_method,
|
||||
ctxt,
|
||||
model['id'])
|
||||
else:
|
||||
actual_model = db_access_method(ctxt, model['id'])
|
||||
self.assertEqual(valid_status, actual_model['status'])
|
||||
|
||||
@ddt.data(*fixture_reset_status_with_different_roles)
|
||||
@ddt.unpack
|
||||
def test_share_reset_status_with_different_roles(self, role, valid_code,
|
||||
valid_status):
|
||||
share, req = self._setup_share_data()
|
||||
ctxt = self._get_context(role)
|
||||
|
||||
self._reset_status(ctxt, share, req, db.share_get, valid_code,
|
||||
valid_status)
|
||||
|
||||
@ddt.data(*fixture_reset_status_with_different_roles)
|
||||
@ddt.unpack
|
||||
def test_snapshot_reset_status_with_different_roles(self, role, valid_code,
|
||||
valid_status):
|
||||
ctxt = self._get_context(role)
|
||||
snapshot, req = self._setup_snapshot_data()
|
||||
|
||||
self._reset_status(ctxt, snapshot, req, db.share_snapshot_get,
|
||||
valid_code, valid_status)
|
||||
|
||||
@ddt.data(*fixture_reset_status_with_different_roles)
|
||||
@ddt.unpack
|
||||
def test_share_instances_reset_status_with_different_roles(self, role,
|
||||
valid_code,
|
||||
valid_status):
|
||||
ctxt = self._get_context(role)
|
||||
instance, req = self._setup_share_instance_data()
|
||||
|
||||
self._reset_status(ctxt, instance, req, db.share_instance_get,
|
||||
valid_code, valid_status)
|
||||
|
||||
@ddt.data(*fixture_reset_status_with_different_roles)
|
||||
@ddt.unpack
|
||||
def test_consistency_groups_reset_status_with_different_roles(
|
||||
self, role, valid_code, valid_status):
|
||||
ctxt = self._get_context(role)
|
||||
cg, req = self._setup_cg_data()
|
||||
|
||||
self._reset_status(ctxt, cg, req, db.consistency_group_get,
|
||||
valid_code, valid_status)
|
||||
|
||||
@ddt.data(*fixture_reset_status_with_different_roles)
|
||||
@ddt.unpack
|
||||
def test_cgsnapshot_reset_status_with_different_roles(
|
||||
self, role, valid_code, valid_status):
|
||||
ctxt = self._get_context(role)
|
||||
cgsnap, req = self._setup_cgsnapshot_data()
|
||||
|
||||
self._reset_status(ctxt, cgsnap, req, db.cgsnapshot_get,
|
||||
valid_code, valid_status)
|
||||
|
||||
@ddt.data(*fixture_invalid_reset_status_body)
|
||||
def test_share_invalid_reset_status_body(self, body):
|
||||
share, req = self._setup_share_data()
|
||||
ctxt = self.admin_context
|
||||
|
||||
self._reset_status(ctxt, share, req, db.share_get, 400,
|
||||
constants.STATUS_AVAILABLE, body)
|
||||
|
||||
@ddt.data(*fixture_invalid_reset_status_body)
|
||||
def test_snapshot_invalid_reset_status_body(self, body):
|
||||
snapshot, req = self._setup_snapshot_data()
|
||||
|
||||
self._reset_status(self.admin_context, snapshot, req,
|
||||
db.share_snapshot_get, 400,
|
||||
constants.STATUS_AVAILABLE, body)
|
||||
|
||||
@ddt.data(*fixture_invalid_reset_status_body)
|
||||
def test_share_instance_invalid_reset_status_body(self, body):
|
||||
instance, req = self._setup_share_instance_data()
|
||||
|
||||
self._reset_status(self.admin_context, instance, req,
|
||||
db.share_instance_get, 400,
|
||||
constants.STATUS_AVAILABLE, body)
|
||||
|
||||
def test_share_reset_status_for_missing(self):
|
||||
fake_share = {'id': 'missing-share-id'}
|
||||
req = webob.Request.blank('/v1/fake/shares/%s/action' %
|
||||
fake_share['id'])
|
||||
|
||||
self._reset_status(self.admin_context, fake_share, req,
|
||||
db.share_snapshot_get, 404)
|
||||
|
||||
def _force_delete(self, ctxt, model, req, db_access_method, valid_code,
|
||||
check_model_in_db=False):
|
||||
req.method = 'POST'
|
||||
req.headers['content-type'] = 'application/json'
|
||||
req.body = six.b(jsonutils.dumps({'os-force_delete': {}}))
|
||||
req.environ['manila.context'] = ctxt
|
||||
|
||||
resp = req.get_response(app())
|
||||
|
||||
# validate response
|
||||
self.assertEqual(valid_code, resp.status_int)
|
||||
|
||||
if valid_code == 202 and check_model_in_db:
|
||||
self.assertRaises(exception.NotFound,
|
||||
db_access_method,
|
||||
ctxt,
|
||||
model['id'])
|
||||
|
||||
@ddt.data(*fixture_force_delete_with_different_roles)
|
||||
@ddt.unpack
|
||||
def test_share_force_delete_with_different_roles(self, role, resp_code):
|
||||
share, req = self._setup_share_data()
|
||||
ctxt = self._get_context(role)
|
||||
|
||||
self._force_delete(ctxt, share, req, db.share_get, resp_code,
|
||||
check_model_in_db=True)
|
||||
|
||||
def test_share_force_delete_missing(self):
|
||||
share, req = self._setup_share_data(share={'id': 'fake'})
|
||||
ctxt = self._get_context('admin')
|
||||
|
||||
self._force_delete(ctxt, share, req, db.share_get, 404)
|
||||
|
||||
@ddt.data(*fixture_force_delete_with_different_roles)
|
||||
@ddt.unpack
|
||||
def test_snapshot_force_delete_with_different_roles(self, role, resp_code):
|
||||
snapshot, req = self._setup_snapshot_data()
|
||||
ctxt = self._get_context(role)
|
||||
|
||||
self._force_delete(ctxt, snapshot, req, db.share_snapshot_get,
|
||||
resp_code)
|
||||
|
||||
def test_snapshot_force_delete_missing(self):
|
||||
snapshot, req = self._setup_snapshot_data(snapshot={'id': 'fake'})
|
||||
ctxt = self._get_context('admin')
|
||||
|
||||
self._force_delete(ctxt, snapshot, req, db.share_snapshot_get, 404)
|
||||
|
||||
@ddt.data(*fixture_force_delete_with_different_roles)
|
||||
@ddt.unpack
|
||||
def test_instance_force_delete_with_different_roles(self, role, resp_code):
|
||||
instance, req = self._setup_share_instance_data()
|
||||
ctxt = self._get_context(role)
|
||||
|
||||
self._force_delete(ctxt, instance, req, db.share_instance_get,
|
||||
resp_code)
|
||||
|
||||
def test_instance_force_delete_missing(self):
|
||||
instance, req = self._setup_share_instance_data(
|
||||
instance={'id': 'fake'})
|
||||
ctxt = self._get_context('admin')
|
||||
|
||||
self._force_delete(ctxt, instance, req, db.share_instance_get, 404)
|
||||
|
||||
@ddt.data(*fixture_force_delete_with_different_roles)
|
||||
@ddt.unpack
|
||||
def test_consistency_group_force_delete_with_different_roles(self, role,
|
||||
resp_code):
|
||||
cg, req = self._setup_cg_data()
|
||||
ctxt = self._get_context(role)
|
||||
|
||||
self._force_delete(ctxt, cg, req, db.consistency_group_get,
|
||||
resp_code)
|
||||
|
||||
@ddt.data(*fixture_force_delete_with_different_roles)
|
||||
@ddt.unpack
|
||||
def test_cgsnapshot_force_delete_with_different_roles(self, role,
|
||||
resp_code):
|
||||
cgsnap, req = self._setup_cgsnapshot_data()
|
||||
ctxt = self._get_context(role)
|
||||
|
||||
self._force_delete(ctxt, cgsnap, req, db.cgsnapshot_get,
|
||||
resp_code)
|
@ -30,6 +30,7 @@ from manila.api import urlmap
|
||||
from manila.api.v1 import limits
|
||||
from manila.api.v1 import router
|
||||
from manila.api import versions
|
||||
from manila.common import constants
|
||||
from manila import context
|
||||
from manila import wsgi
|
||||
|
||||
@ -165,3 +166,39 @@ def get_fake_uuid(token=0):
|
||||
if token not in FAKE_UUIDS:
|
||||
FAKE_UUIDS[token] = str(uuid.uuid4())
|
||||
return FAKE_UUIDS[token]
|
||||
|
||||
|
||||
def app():
|
||||
"""API application.
|
||||
|
||||
No auth, just let environ['manila.context'] pass through.
|
||||
"""
|
||||
api = router.APIRouter()
|
||||
mapper = urlmap.URLMap()
|
||||
mapper['/v2'] = api
|
||||
mapper['/v1'] = api
|
||||
return mapper
|
||||
|
||||
|
||||
fixture_reset_status_with_different_roles = (
|
||||
{
|
||||
'role': 'admin', 'valid_code': 202,
|
||||
'valid_status': constants.STATUS_ERROR,
|
||||
},
|
||||
{
|
||||
'role': 'member', 'valid_code': 403,
|
||||
'valid_status': constants.STATUS_AVAILABLE,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
fixture_force_delete_with_different_roles = (
|
||||
{'role': 'admin', 'resp_code': 202},
|
||||
{'role': 'member', 'resp_code': 403},
|
||||
)
|
||||
|
||||
|
||||
fixture_invalid_reset_status_body = (
|
||||
{'os-reset_status': {'x-status': 'bad'}},
|
||||
{'os-reset_status': {'status': 'invalid'}}
|
||||
)
|
||||
|
@ -17,29 +17,39 @@ import copy
|
||||
import datetime
|
||||
import uuid
|
||||
|
||||
import ddt
|
||||
import mock
|
||||
from oslo_config import cfg
|
||||
from oslo_serialization import jsonutils
|
||||
import six
|
||||
import webob
|
||||
|
||||
from manila.api.openstack import wsgi
|
||||
import manila.api.v1.cgsnapshots as cgs
|
||||
from manila.common import constants
|
||||
from manila import context
|
||||
from manila import db
|
||||
from manila import exception
|
||||
from manila import test
|
||||
from manila.tests.api import fakes
|
||||
|
||||
from manila.tests import db_utils
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class CGSnapshotApiTest(test.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(CGSnapshotApiTest, self).setUp()
|
||||
super(self.__class__, self).setUp()
|
||||
self.controller = cgs.CGSnapshotController()
|
||||
self.api_version = '2.4'
|
||||
self.request = fakes.HTTPRequest.blank('/consistency-groups',
|
||||
version=self.api_version,
|
||||
experimental=True)
|
||||
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')
|
||||
|
||||
def _get_fake_cgsnapshot(self, **values):
|
||||
snap = {
|
||||
@ -425,3 +435,58 @@ class CGSnapshotApiTest(test.TestCase):
|
||||
|
||||
self.assertEqual(1, len(res_dict['cgsnapshot_members']))
|
||||
self.assertEqual([expected_member2], res_dict['cgsnapshot_members'])
|
||||
|
||||
def _get_context(self, role):
|
||||
return getattr(self, '%s_context' % role)
|
||||
|
||||
def _setup_cgsnapshot_data(self, cgsnapshot=None):
|
||||
if cgsnapshot is None:
|
||||
cgsnapshot = db_utils.create_cgsnapshot(
|
||||
'fake_id', status=constants.STATUS_AVAILABLE)
|
||||
req = webob.Request.blank('/v2/fake/cgsnapshots/%s/action' %
|
||||
cgsnapshot['id'])
|
||||
req.headers[wsgi.API_VERSION_REQUEST_HEADER] = '2.4'
|
||||
req.headers[wsgi.EXPERIMENTAL_API_REQUEST_HEADER] = 'True'
|
||||
return cgsnapshot, req
|
||||
|
||||
@ddt.data(*fakes.fixture_force_delete_with_different_roles)
|
||||
@ddt.unpack
|
||||
def test_cgsnapshot_force_delete_with_different_roles(self, role,
|
||||
resp_code):
|
||||
cgsnap, req = self._setup_cgsnapshot_data()
|
||||
ctxt = self._get_context(role)
|
||||
req.method = 'POST'
|
||||
req.headers['content-type'] = 'application/json'
|
||||
req.body = six.b(jsonutils.dumps({'os-force_delete': {}}))
|
||||
req.environ['manila.context'] = ctxt
|
||||
|
||||
resp = req.get_response(fakes.app())
|
||||
|
||||
# Validate response
|
||||
self.assertEqual(resp_code, resp.status_int)
|
||||
|
||||
@ddt.data(*fakes.fixture_reset_status_with_different_roles)
|
||||
@ddt.unpack
|
||||
def test_cgsnapshot_reset_status_with_different_roles(
|
||||
self, role, valid_code, valid_status):
|
||||
ctxt = self._get_context(role)
|
||||
cgsnap, req = self._setup_cgsnapshot_data()
|
||||
body = {'os-reset_status': {'status': constants.STATUS_ERROR}}
|
||||
req.method = 'POST'
|
||||
req.headers['content-type'] = 'application/json'
|
||||
req.body = six.b(jsonutils.dumps(body))
|
||||
req.environ['manila.context'] = ctxt
|
||||
|
||||
resp = req.get_response(fakes.app())
|
||||
|
||||
# Validate response code and model status
|
||||
self.assertEqual(valid_code, resp.status_int)
|
||||
|
||||
if valid_code == 404:
|
||||
self.assertRaises(exception.NotFound,
|
||||
db.cgsnapshot_get,
|
||||
ctxt,
|
||||
cgsnap['id'])
|
||||
else:
|
||||
actual_model = db.cgsnapshot_get(ctxt, cgsnap['id'])
|
||||
self.assertEqual(valid_status, actual_model['status'])
|
||||
|
@ -17,33 +17,58 @@ import copy
|
||||
import datetime
|
||||
import uuid
|
||||
|
||||
import ddt
|
||||
import mock
|
||||
from oslo_config import cfg
|
||||
from oslo_serialization import jsonutils
|
||||
import six
|
||||
import webob
|
||||
|
||||
from manila.api.openstack import wsgi
|
||||
import manila.api.v1.consistency_groups as cgs
|
||||
from manila.common import constants
|
||||
import manila.consistency_group.api as cg_api
|
||||
from manila import context
|
||||
from manila import db
|
||||
from manila import exception
|
||||
from manila.share import share_types
|
||||
from manila import test
|
||||
from manila.tests.api import fakes
|
||||
from manila.tests import db_utils
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class CGApiTest(test.TestCase):
|
||||
"""Share Api Test."""
|
||||
"""Consistency Groups API Test suite."""
|
||||
|
||||
def setUp(self):
|
||||
super(CGApiTest, self).setUp()
|
||||
super(self.__class__, self).setUp()
|
||||
self.controller = cgs.CGController()
|
||||
self.fake_share_type = {'id': six.text_type(uuid.uuid4())}
|
||||
self.api_version = '2.4'
|
||||
self.request = fakes.HTTPRequest.blank('/consistency-groups',
|
||||
version=self.api_version,
|
||||
experimental=True)
|
||||
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')
|
||||
|
||||
def _get_context(self, role):
|
||||
return getattr(self, '%s_context' % role)
|
||||
|
||||
def _setup_cg_data(self, cg=None):
|
||||
if cg is None:
|
||||
cg = db_utils.create_consistency_group(
|
||||
status=constants.STATUS_AVAILABLE)
|
||||
req = webob.Request.blank('/v2/fake/consistency-groups/%s/action' %
|
||||
cg['id'])
|
||||
req.headers[wsgi.API_VERSION_REQUEST_HEADER] = '2.4'
|
||||
req.headers[wsgi.EXPERIMENTAL_API_REQUEST_HEADER] = 'True'
|
||||
|
||||
return cg, req
|
||||
|
||||
def _get_fake_cg(self, **values):
|
||||
cg = {
|
||||
@ -503,3 +528,46 @@ class CGApiTest(test.TestCase):
|
||||
|
||||
self.assertRaises(webob.exc.HTTPNotFound, self.controller.show,
|
||||
req, fake_cg['id'])
|
||||
|
||||
@ddt.data(*fakes.fixture_reset_status_with_different_roles)
|
||||
@ddt.unpack
|
||||
def test_consistency_groups_reset_status_with_different_roles(
|
||||
self, role, valid_code, valid_status):
|
||||
ctxt = self._get_context(role)
|
||||
cg, req = self._setup_cg_data()
|
||||
|
||||
body = {'os-reset_status': {'status': constants.STATUS_ERROR}}
|
||||
req.method = 'POST'
|
||||
req.headers['content-type'] = 'application/json'
|
||||
req.body = six.b(jsonutils.dumps(body))
|
||||
req.environ['manila.context'] = ctxt
|
||||
|
||||
resp = req.get_response(fakes.app())
|
||||
|
||||
# validate response code and model status
|
||||
self.assertEqual(valid_code, resp.status_int)
|
||||
|
||||
if valid_code == 404:
|
||||
self.assertRaises(exception.NotFound,
|
||||
db.consistency_group_get,
|
||||
ctxt,
|
||||
cg['id'])
|
||||
else:
|
||||
actual_model = db.consistency_group_get(ctxt, cg['id'])
|
||||
self.assertEqual(valid_status, actual_model['status'])
|
||||
|
||||
@ddt.data(*fakes.fixture_force_delete_with_different_roles)
|
||||
@ddt.unpack
|
||||
def test_consistency_group_force_delete_with_different_roles(self, role,
|
||||
resp_code):
|
||||
ctxt = self._get_context(role)
|
||||
cg, req = self._setup_cg_data()
|
||||
req.method = 'POST'
|
||||
req.headers['content-type'] = 'application/json'
|
||||
req.body = six.b(jsonutils.dumps({'os-force_delete': {}}))
|
||||
req.environ['manila.context'] = ctxt
|
||||
|
||||
resp = req.get_response(fakes.app())
|
||||
|
||||
# validate response
|
||||
self.assertEqual(resp_code, resp.status_int)
|
||||
|
@ -12,10 +12,16 @@
|
||||
|
||||
import ddt
|
||||
from oslo_config import cfg
|
||||
from oslo_serialization import jsonutils
|
||||
import six
|
||||
import webob
|
||||
from webob import exc as webob_exc
|
||||
|
||||
from manila.api.v1 import share_instances
|
||||
from manila.common import constants
|
||||
from manila import context
|
||||
from manila import db
|
||||
from manila import exception
|
||||
from manila import test
|
||||
from manila.tests.api import fakes
|
||||
from manila.tests import db_utils
|
||||
@ -24,16 +30,29 @@ CONF = cfg.CONF
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class ShareInstancesApiTest(test.TestCase):
|
||||
"""Share Api Test."""
|
||||
class ShareInstancesAPITest(test.TestCase):
|
||||
"""Share instances API Test."""
|
||||
|
||||
def setUp(self):
|
||||
super(ShareInstancesApiTest, self).setUp()
|
||||
super(self.__class__, self).setUp()
|
||||
self.controller = share_instances.ShareInstancesController()
|
||||
self.context = context.RequestContext('admin', 'fake', True)
|
||||
self.admin_context = context.RequestContext('admin', 'fake', True)
|
||||
self.member_context = context.RequestContext('fake', 'fake')
|
||||
|
||||
def _get_context(self, role):
|
||||
return getattr(self, '%s_context' % role)
|
||||
|
||||
def _setup_share_instance_data(self, instance=None):
|
||||
if instance is None:
|
||||
instance = db_utils.create_share(status=constants.STATUS_AVAILABLE,
|
||||
size='1').instance
|
||||
req = webob.Request.blank(
|
||||
'/v2/fake/share_instances/%s/action' % instance['id'])
|
||||
return instance, req
|
||||
|
||||
def _get_request(self, uri, context=None):
|
||||
if context is None:
|
||||
context = self.context
|
||||
context = self.admin_context
|
||||
req = fakes.HTTPRequest.blank('/shares', version="2.3")
|
||||
req.environ['manila.context'] = context
|
||||
return req
|
||||
@ -91,3 +110,82 @@ class ShareInstancesApiTest(test.TestCase):
|
||||
args = [i for i in range(1, args_count)]
|
||||
|
||||
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):
|
||||
if body is None:
|
||||
body = {'os-reset_status': {'status': constants.STATUS_ERROR}}
|
||||
req.method = 'POST'
|
||||
req.headers['content-type'] = 'application/json'
|
||||
req.body = six.b(jsonutils.dumps(body))
|
||||
req.environ['manila.context'] = ctxt
|
||||
|
||||
resp = req.get_response(fakes.app())
|
||||
|
||||
# validate response code and model status
|
||||
self.assertEqual(valid_code, resp.status_int)
|
||||
|
||||
if valid_code == 404:
|
||||
self.assertRaises(exception.NotFound,
|
||||
db_access_method,
|
||||
ctxt,
|
||||
model['id'])
|
||||
else:
|
||||
actual_model = db_access_method(ctxt, model['id'])
|
||||
self.assertEqual(valid_status, actual_model['status'])
|
||||
|
||||
@ddt.data(*fakes.fixture_reset_status_with_different_roles)
|
||||
@ddt.unpack
|
||||
def test_share_instances_reset_status_with_different_roles(self, role,
|
||||
valid_code,
|
||||
valid_status):
|
||||
ctxt = self._get_context(role)
|
||||
instance, req = self._setup_share_instance_data()
|
||||
req.headers['X-Openstack-Manila-Api-Version'] = '2.3'
|
||||
|
||||
self._reset_status(ctxt, instance, req, db.share_instance_get,
|
||||
valid_code, valid_status)
|
||||
|
||||
@ddt.data(*fakes.fixture_invalid_reset_status_body)
|
||||
def test_share_instance_invalid_reset_status_body(self, body):
|
||||
instance, req = self._setup_share_instance_data()
|
||||
req.headers['X-Openstack-Manila-Api-Version'] = '2.3'
|
||||
|
||||
self._reset_status(self.admin_context, instance, req,
|
||||
db.share_instance_get, 400,
|
||||
constants.STATUS_AVAILABLE, body)
|
||||
|
||||
def _force_delete(self, ctxt, model, req, db_access_method, valid_code,
|
||||
check_model_in_db=False):
|
||||
req.method = 'POST'
|
||||
req.headers['content-type'] = 'application/json'
|
||||
req.headers['X-Openstack-Manila-Api-Version'] = '2.3'
|
||||
req.body = six.b(jsonutils.dumps({'os-force_delete': {}}))
|
||||
req.environ['manila.context'] = ctxt
|
||||
|
||||
resp = req.get_response(fakes.app())
|
||||
|
||||
# validate response
|
||||
self.assertEqual(valid_code, resp.status_int)
|
||||
|
||||
if valid_code == 202 and check_model_in_db:
|
||||
self.assertRaises(exception.NotFound,
|
||||
db_access_method,
|
||||
ctxt,
|
||||
model['id'])
|
||||
|
||||
@ddt.data(*fakes.fixture_force_delete_with_different_roles)
|
||||
@ddt.unpack
|
||||
def test_instance_force_delete_with_different_roles(self, role, resp_code):
|
||||
instance, req = self._setup_share_instance_data()
|
||||
ctxt = self._get_context(role)
|
||||
|
||||
self._force_delete(ctxt, instance, req, db.share_instance_get,
|
||||
resp_code)
|
||||
|
||||
def test_instance_force_delete_missing(self):
|
||||
instance, req = self._setup_share_instance_data(
|
||||
instance={'id': 'fake'})
|
||||
ctxt = self._get_context('admin')
|
||||
|
||||
self._force_delete(ctxt, instance, req, db.share_instance_get, 404)
|
||||
|
@ -17,21 +17,28 @@ import datetime
|
||||
|
||||
import ddt
|
||||
import mock
|
||||
from oslo_serialization import jsonutils
|
||||
import six
|
||||
import webob
|
||||
|
||||
from manila.api.v1 import share_snapshots
|
||||
from manila.common import constants
|
||||
from manila import context
|
||||
from manila import db
|
||||
from manila import exception
|
||||
from manila.share import api as share_api
|
||||
from manila import test
|
||||
from manila.tests.api.contrib import stubs
|
||||
from manila.tests.api import fakes
|
||||
from manila.tests import db_utils
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class ShareSnapshotApiTest(test.TestCase):
|
||||
"""Share Snapshot Api Test."""
|
||||
class ShareSnapshotAPITest(test.TestCase):
|
||||
"""Share Snapshot API Test."""
|
||||
|
||||
def setUp(self):
|
||||
super(ShareSnapshotApiTest, self).setUp()
|
||||
super(self.__class__, self).setUp()
|
||||
self.controller = share_snapshots.ShareSnapshotsController()
|
||||
|
||||
self.mock_object(share_api.API, 'get', stubs.stub_share_get)
|
||||
@ -368,3 +375,93 @@ class ShareSnapshotApiTest(test.TestCase):
|
||||
res_dict = self.controller.update(req, 1, body)
|
||||
|
||||
self.assertNotEqual(snp["size"], res_dict['snapshot']["size"])
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class ShareSnapshotAdminActionsAPITest(test.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(self.__class__, self).setUp()
|
||||
self.controller = share_snapshots.ShareSnapshotsController()
|
||||
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')
|
||||
|
||||
def _get_context(self, role):
|
||||
return getattr(self, '%s_context' % role)
|
||||
|
||||
def _setup_snapshot_data(self, snapshot=None):
|
||||
if snapshot is None:
|
||||
share = db_utils.create_share()
|
||||
snapshot = db_utils.create_snapshot(
|
||||
status=constants.STATUS_AVAILABLE, share_id=share['id'])
|
||||
req = webob.Request.blank('/v2/fake/snapshots/%s/action' %
|
||||
snapshot['id'])
|
||||
return snapshot, req
|
||||
|
||||
def _reset_status(self, ctxt, model, req, db_access_method,
|
||||
valid_code, valid_status=None, body=None):
|
||||
if body is None:
|
||||
body = {'os-reset_status': {'status': constants.STATUS_ERROR}}
|
||||
req.method = 'POST'
|
||||
req.headers['content-type'] = 'application/json'
|
||||
req.body = six.b(jsonutils.dumps(body))
|
||||
req.environ['manila.context'] = ctxt
|
||||
|
||||
resp = req.get_response(fakes.app())
|
||||
|
||||
# validate response code and model status
|
||||
self.assertEqual(valid_code, resp.status_int)
|
||||
|
||||
if valid_code == 404:
|
||||
self.assertRaises(exception.NotFound,
|
||||
db_access_method,
|
||||
ctxt,
|
||||
model['id'])
|
||||
else:
|
||||
actual_model = db_access_method(ctxt, model['id'])
|
||||
self.assertEqual(valid_status, actual_model['status'])
|
||||
|
||||
@ddt.data(*fakes.fixture_reset_status_with_different_roles)
|
||||
@ddt.unpack
|
||||
def test_snapshot_reset_status_with_different_roles(self, role, valid_code,
|
||||
valid_status):
|
||||
ctxt = self._get_context(role)
|
||||
snapshot, req = self._setup_snapshot_data()
|
||||
|
||||
self._reset_status(ctxt, snapshot, req, db.share_snapshot_get,
|
||||
valid_code, valid_status)
|
||||
|
||||
@ddt.data(*fakes.fixture_invalid_reset_status_body)
|
||||
def test_snapshot_invalid_reset_status_body(self, body):
|
||||
snapshot, req = self._setup_snapshot_data()
|
||||
|
||||
self._reset_status(self.admin_context, snapshot, req,
|
||||
db.share_snapshot_get, 400,
|
||||
constants.STATUS_AVAILABLE, body)
|
||||
|
||||
def _force_delete(self, ctxt, model, req, db_access_method, valid_code):
|
||||
req.method = 'POST'
|
||||
req.headers['content-type'] = 'application/json'
|
||||
req.body = six.b(jsonutils.dumps({'os-force_delete': {}}))
|
||||
req.environ['manila.context'] = ctxt
|
||||
|
||||
resp = req.get_response(fakes.app())
|
||||
|
||||
# Validate response
|
||||
self.assertEqual(valid_code, resp.status_int)
|
||||
|
||||
@ddt.data(*fakes.fixture_force_delete_with_different_roles)
|
||||
@ddt.unpack
|
||||
def test_snapshot_force_delete_with_different_roles(self, role, resp_code):
|
||||
ctxt = self._get_context(role)
|
||||
snapshot, req = self._setup_snapshot_data()
|
||||
|
||||
self._force_delete(ctxt, snapshot, req, db.share_snapshot_get,
|
||||
resp_code)
|
||||
|
||||
def test_snapshot_force_delete_missing(self):
|
||||
ctxt = self._get_context('admin')
|
||||
snapshot, req = self._setup_snapshot_data(snapshot={'id': 'fake'})
|
||||
|
||||
self._force_delete(ctxt, snapshot, req, db.share_snapshot_get, 404)
|
||||
|
@ -19,6 +19,8 @@ import datetime
|
||||
import ddt
|
||||
import mock
|
||||
from oslo_config import cfg
|
||||
from oslo_serialization import jsonutils
|
||||
import six
|
||||
import webob
|
||||
|
||||
from manila.api import common
|
||||
@ -48,10 +50,11 @@ def app():
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class ShareApiTest(test.TestCase):
|
||||
"""Share Api Test."""
|
||||
class ShareAPITest(test.TestCase):
|
||||
"""Share API Test."""
|
||||
|
||||
def setUp(self):
|
||||
super(ShareApiTest, self).setUp()
|
||||
super(self.__class__, self).setUp()
|
||||
self.controller = shares.ShareController()
|
||||
self.mock_object(db, 'availability_zone_get')
|
||||
self.mock_object(share_api.API, 'get_all',
|
||||
@ -1009,3 +1012,108 @@ class ShareActionsTest(test.TestCase):
|
||||
mock.Mock(side_effect=source('fake')))
|
||||
|
||||
self.assertRaises(target, self.controller._shrink, req, id, body)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class ShareAdminActionsAPITest(test.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(self.__class__, self).setUp()
|
||||
CONF.set_default("default_share_type", None)
|
||||
self.flags(rpc_backend='manila.openstack.common.rpc.impl_fake')
|
||||
self.share_api = share_api.API()
|
||||
self.admin_context = context.RequestContext('admin', 'fake', True)
|
||||
self.member_context = context.RequestContext('fake', 'fake')
|
||||
|
||||
def _get_context(self, role):
|
||||
return getattr(self, '%s_context' % role)
|
||||
|
||||
def _setup_share_data(self, share=None):
|
||||
if share is None:
|
||||
share = db_utils.create_share(status=constants.STATUS_AVAILABLE,
|
||||
size='1',
|
||||
override_defaults=True)
|
||||
req = webob.Request.blank('/v2/fake/shares/%s/action' % share['id'])
|
||||
return share, req
|
||||
|
||||
def _reset_status(self, ctxt, model, req, db_access_method,
|
||||
valid_code, valid_status=None, body=None):
|
||||
if body is None:
|
||||
body = {'os-reset_status': {'status': constants.STATUS_ERROR}}
|
||||
req.method = 'POST'
|
||||
req.headers['content-type'] = 'application/json'
|
||||
req.body = six.b(jsonutils.dumps(body))
|
||||
req.environ['manila.context'] = ctxt
|
||||
|
||||
resp = req.get_response(fakes.app())
|
||||
|
||||
# validate response code and model status
|
||||
self.assertEqual(valid_code, resp.status_int)
|
||||
|
||||
if valid_code == 404:
|
||||
self.assertRaises(exception.NotFound,
|
||||
db_access_method,
|
||||
ctxt,
|
||||
model['id'])
|
||||
else:
|
||||
actual_model = db_access_method(ctxt, model['id'])
|
||||
self.assertEqual(valid_status, actual_model['status'])
|
||||
|
||||
@ddt.data(*fakes.fixture_invalid_reset_status_body)
|
||||
def test_share_invalid_reset_status_body(self, body):
|
||||
share, req = self._setup_share_data()
|
||||
ctxt = self.admin_context
|
||||
|
||||
self._reset_status(ctxt, share, req, db.share_get, 400,
|
||||
constants.STATUS_AVAILABLE, body)
|
||||
|
||||
def test_share_reset_status_for_missing(self):
|
||||
fake_share = {'id': 'missing-share-id'}
|
||||
req = webob.Request.blank('/v1/fake/shares/%s/action' %
|
||||
fake_share['id'])
|
||||
|
||||
self._reset_status(self.admin_context, fake_share, req,
|
||||
db.share_snapshot_get, 404)
|
||||
|
||||
def _force_delete(self, ctxt, model, req, db_access_method, valid_code,
|
||||
check_model_in_db=False):
|
||||
req.method = 'POST'
|
||||
req.headers['content-type'] = 'application/json'
|
||||
req.body = six.b(jsonutils.dumps({'os-force_delete': {}}))
|
||||
req.environ['manila.context'] = ctxt
|
||||
|
||||
resp = req.get_response(fakes.app())
|
||||
|
||||
# validate response
|
||||
self.assertEqual(valid_code, resp.status_int)
|
||||
|
||||
if valid_code == 202 and check_model_in_db:
|
||||
self.assertRaises(exception.NotFound,
|
||||
db_access_method,
|
||||
ctxt,
|
||||
model['id'])
|
||||
|
||||
@ddt.data(*fakes.fixture_reset_status_with_different_roles)
|
||||
@ddt.unpack
|
||||
def test_share_reset_status_with_different_roles(self, role, valid_code,
|
||||
valid_status):
|
||||
share, req = self._setup_share_data()
|
||||
ctxt = self._get_context(role)
|
||||
|
||||
self._reset_status(ctxt, share, req, db.share_get, valid_code,
|
||||
valid_status)
|
||||
|
||||
@ddt.data(*fakes.fixture_force_delete_with_different_roles)
|
||||
@ddt.unpack
|
||||
def test_share_force_delete_with_different_roles(self, role, resp_code):
|
||||
share, req = self._setup_share_data()
|
||||
ctxt = self._get_context(role)
|
||||
|
||||
self._force_delete(ctxt, share, req, db.share_get, resp_code,
|
||||
check_model_in_db=True)
|
||||
|
||||
def test_share_force_delete_missing(self):
|
||||
share, req = self._setup_share_data(share={'id': 'fake'})
|
||||
ctxt = self._get_context('admin')
|
||||
|
||||
self._force_delete(ctxt, share, req, db.share_get, 404)
|
||||
|
@ -31,6 +31,8 @@
|
||||
"share:shrink": "",
|
||||
"share:manage": "rule:admin_api",
|
||||
"share:unmanage": "rule:admin_api",
|
||||
"share:force_delete": "rule:admin_api",
|
||||
"share:reset_status": "rule:admin_api",
|
||||
|
||||
"share_type:index": "rule:default",
|
||||
"share_type:show": "rule:default",
|
||||
@ -38,6 +40,11 @@
|
||||
|
||||
"share_instance:index": "rule:admin_api",
|
||||
"share_instance:show": "rule:admin_api",
|
||||
"share_instance:force_delete": "rule:admin_api",
|
||||
"share_instance:reset_status": "rule:admin_api",
|
||||
|
||||
"share_snapshot:force_delete": "rule:admin_api",
|
||||
"share_snapshot:reset_status": "rule:admin_api",
|
||||
|
||||
"share_network:create": "",
|
||||
"share_network:index": "",
|
||||
@ -55,16 +62,6 @@
|
||||
"share:get_share_metadata": "",
|
||||
"share:delete_share_metadata": "",
|
||||
"share:update_share_metadata": "",
|
||||
"share_extension:share_admin_actions:force_delete": "rule:admin_api",
|
||||
"share_extension:share_admin_actions:reset_status": "rule:admin_api",
|
||||
"share_extension:snapshot_admin_actions:force_delete": "rule:admin_api",
|
||||
"share_extension:snapshot_admin_actions:reset_status": "rule:admin_api",
|
||||
"share_extension:share_instance_admin_actions:force_delete": "rule:admin_api",
|
||||
"share_extension:share_instance_admin_actions:reset_status": "rule:admin_api",
|
||||
"share_extension:consistency_group_admin_actions:force_delete": "rule:admin_api",
|
||||
"share_extension:consistency_group_admin_actions:reset_status": "rule:admin_api",
|
||||
"share_extension:cgsnapshot_admin_actions:force_delete": "rule:admin_api",
|
||||
"share_extension:cgsnapshot_admin_actions:reset_status": "rule:admin_api",
|
||||
"share_extension:types_manage": "",
|
||||
"share_extension:types_extra_specs": "",
|
||||
"share_extension:share_type_access": "",
|
||||
@ -83,9 +80,13 @@
|
||||
"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"
|
||||
"consistency_group:get_all_cgsnapshots": "rule:default",
|
||||
|
||||
"cgsnapshot:force_delete": "rule:admin_api",
|
||||
"cgsnapshot:reset_status": "rule:admin_api"
|
||||
}
|
||||
|
@ -1012,7 +1012,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
rule = self.api.get_snapshot(self.context, 'fakeid')
|
||||
self.assertEqual(fake_get_snap, rule)
|
||||
share_api.policy.check_policy.assert_called_once_with(
|
||||
self.context, 'share', 'get_snapshot')
|
||||
self.context, 'share_snapshot', 'get_snapshot')
|
||||
db_api.share_snapshot_get.assert_called_once_with(
|
||||
self.context, 'fakeid')
|
||||
|
||||
@ -1171,7 +1171,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
ctx = context.RequestContext('fakeuid', 'fakepid', is_admin=True)
|
||||
self.api.get_all_snapshots(ctx)
|
||||
share_api.policy.check_policy.assert_called_once_with(
|
||||
ctx, 'share', 'get_all_snapshots')
|
||||
ctx, 'share_snapshot', 'get_all_snapshots')
|
||||
db_api.share_snapshot_get_all_by_project.assert_called_once_with(
|
||||
ctx, 'fakepid', sort_dir='desc', sort_key='share_id', filters={})
|
||||
|
||||
@ -1180,7 +1180,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
self.api.get_all_snapshots(self.context,
|
||||
search_opts={'all_tenants': 1})
|
||||
share_api.policy.check_policy.assert_called_once_with(
|
||||
self.context, 'share', 'get_all_snapshots')
|
||||
self.context, 'share_snapshot', 'get_all_snapshots')
|
||||
db_api.share_snapshot_get_all.assert_called_once_with(
|
||||
self.context, sort_dir='desc', sort_key='share_id', filters={})
|
||||
|
||||
@ -1190,7 +1190,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
ctx = context.RequestContext('fakeuid', 'fakepid', is_admin=False)
|
||||
self.api.get_all_snapshots(ctx)
|
||||
share_api.policy.check_policy.assert_called_once_with(
|
||||
ctx, 'share', 'get_all_snapshots')
|
||||
ctx, 'share_snapshot', 'get_all_snapshots')
|
||||
db_api.share_snapshot_get_all_by_project.assert_called_once_with(
|
||||
ctx, 'fakepid', sort_dir='desc', sort_key='share_id', filters={})
|
||||
|
||||
@ -1205,7 +1205,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
|
||||
self.assertEqual([search_opts], result)
|
||||
share_api.policy.check_policy.assert_called_once_with(
|
||||
ctx, 'share', 'get_all_snapshots')
|
||||
ctx, 'share_snapshot', 'get_all_snapshots')
|
||||
db_api.share_snapshot_get_all_by_project.assert_called_once_with(
|
||||
ctx, 'fakepid', sort_dir='desc', sort_key='share_id',
|
||||
filters=search_opts)
|
||||
@ -1218,7 +1218,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
snapshots = self.api.get_all_snapshots(
|
||||
ctx, sort_key='status', sort_dir='asc')
|
||||
share_api.policy.check_policy.assert_called_once_with(
|
||||
ctx, 'share', 'get_all_snapshots')
|
||||
ctx, 'share_snapshot', 'get_all_snapshots')
|
||||
db_api.share_snapshot_get_all_by_project.assert_called_once_with(
|
||||
ctx, 'fake_pid_1', sort_dir='asc', sort_key='status', filters={})
|
||||
self.assertEqual(_FAKE_LIST_OF_ALL_SNAPSHOTS[0], snapshots)
|
||||
@ -1235,7 +1235,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
sort_key=1,
|
||||
)
|
||||
share_api.policy.check_policy.assert_called_once_with(
|
||||
ctx, 'share', 'get_all_snapshots')
|
||||
ctx, 'share_snapshot', 'get_all_snapshots')
|
||||
|
||||
def test_get_all_snapshots_sort_dir_invalid(self):
|
||||
self.mock_object(
|
||||
@ -1249,7 +1249,7 @@ class ShareAPITestCase(test.TestCase):
|
||||
sort_dir=1,
|
||||
)
|
||||
share_api.policy.check_policy.assert_called_once_with(
|
||||
ctx, 'share', 'get_all_snapshots')
|
||||
ctx, 'share_snapshot', 'get_all_snapshots')
|
||||
|
||||
@ddt.data(None, 'rw', 'ro')
|
||||
def test_allow_access(self, level):
|
||||
|
@ -100,7 +100,8 @@ class SharesV2Client(shares_client.SharesClient):
|
||||
"""Resets the state of a share, snapshot, cg, or a cgsnapshot.
|
||||
|
||||
status: available, error, creating, deleting, error_deleting
|
||||
s_type: shares, snapshots, consistency-groups, cgsnapshots
|
||||
s_type: shares, share_instances, snapshots, consistency-groups,
|
||||
cgsnapshots.
|
||||
"""
|
||||
body = {"os-reset_status": {"status": status}}
|
||||
body = json.dumps(body)
|
||||
|
@ -40,14 +40,14 @@ class AdminActionsTest(base.BaseSharesAdminTest):
|
||||
@test.attr(type=["gate", ])
|
||||
def test_reset_share_state(self):
|
||||
for status in self.states:
|
||||
self.shares_client.reset_state(self.sh["id"], status=status)
|
||||
self.shares_client.wait_for_share_status(self.sh["id"], status)
|
||||
self.shares_v2_client.reset_state(self.sh["id"], status=status)
|
||||
self.shares_v2_client.wait_for_share_status(self.sh["id"], status)
|
||||
|
||||
@test.attr(type=["gate", ])
|
||||
def test_reset_share_instance_state(self):
|
||||
id = self.sh_instance["id"]
|
||||
for status in self.states:
|
||||
self.shares_client.reset_state(
|
||||
self.shares_v2_client.reset_state(
|
||||
id, s_type="share_instances", status=status)
|
||||
self.shares_v2_client.wait_for_share_instance_status(id, status)
|
||||
|
||||
@ -56,24 +56,25 @@ class AdminActionsTest(base.BaseSharesAdminTest):
|
||||
"Snapshot tests are disabled.")
|
||||
def test_reset_snapshot_state_to_error(self):
|
||||
for status in self.states:
|
||||
self.shares_client.reset_state(
|
||||
self.shares_v2_client.reset_state(
|
||||
self.sn["id"], s_type="snapshots", status=status)
|
||||
self.shares_client.wait_for_snapshot_status(self.sn["id"], status)
|
||||
self.shares_v2_client.wait_for_snapshot_status(
|
||||
self.sn["id"], status)
|
||||
|
||||
@test.attr(type=["gate", ])
|
||||
def test_force_delete_share(self):
|
||||
share = self.create_share()
|
||||
|
||||
# Change status from 'available' to 'error_deleting'
|
||||
self.shares_client.reset_state(share["id"], status=self.bad_status)
|
||||
self.shares_v2_client.reset_state(share["id"], status=self.bad_status)
|
||||
|
||||
# Check that status was changed
|
||||
check_status = self.shares_client.get_share(share["id"])
|
||||
check_status = self.shares_v2_client.get_share(share["id"])
|
||||
self.assertEqual(check_status["status"], self.bad_status)
|
||||
|
||||
# Share with status 'error_deleting' should be deleted
|
||||
self.shares_client.force_delete(share["id"])
|
||||
self.shares_client.wait_for_resource_deletion(share_id=share["id"])
|
||||
self.shares_v2_client.force_delete(share["id"])
|
||||
self.shares_v2_client.wait_for_resource_deletion(share_id=share["id"])
|
||||
|
||||
@test.attr(type=["gate", ])
|
||||
def test_force_delete_share_instance(self):
|
||||
@ -85,7 +86,7 @@ class AdminActionsTest(base.BaseSharesAdminTest):
|
||||
instance = instances[0]
|
||||
|
||||
# Change status from 'available' to 'error_deleting'
|
||||
self.shares_client.reset_state(
|
||||
self.shares_v2_client.reset_state(
|
||||
instance["id"], s_type="share_instances", status=self.bad_status)
|
||||
|
||||
# Check that status was changed
|
||||
@ -93,7 +94,7 @@ class AdminActionsTest(base.BaseSharesAdminTest):
|
||||
self.assertEqual(self.bad_status, check_status["status"])
|
||||
|
||||
# Share with status 'error_deleting' should be deleted
|
||||
self.shares_client.force_delete(
|
||||
self.shares_v2_client.force_delete(
|
||||
instance["id"], s_type="share_instances")
|
||||
self.shares_v2_client.wait_for_resource_deletion(
|
||||
share_instance_id=instance["id"])
|
||||
@ -105,13 +106,13 @@ class AdminActionsTest(base.BaseSharesAdminTest):
|
||||
sn = self.create_snapshot_wait_for_active(self.sh["id"])
|
||||
|
||||
# Change status from 'available' to 'error_deleting'
|
||||
self.shares_client.reset_state(
|
||||
self.shares_v2_client.reset_state(
|
||||
sn["id"], s_type="snapshots", status=self.bad_status)
|
||||
|
||||
# Check that status was changed
|
||||
check_status = self.shares_client.get_snapshot(sn["id"])
|
||||
check_status = self.shares_v2_client.get_snapshot(sn["id"])
|
||||
self.assertEqual(check_status["status"], self.bad_status)
|
||||
|
||||
# Snapshot with status 'error_deleting' should be deleted
|
||||
self.shares_client.force_delete(sn["id"], s_type="snapshots")
|
||||
self.shares_client.wait_for_resource_deletion(snapshot_id=sn["id"])
|
||||
self.shares_v2_client.force_delete(sn["id"], s_type="snapshots")
|
||||
self.shares_v2_client.wait_for_resource_deletion(snapshot_id=sn["id"])
|
||||
|
@ -45,7 +45,7 @@ class AdminActionsNegativeTest(base.BaseSharesAdminTest):
|
||||
|
||||
@test.attr(type=["gate", "negative", ])
|
||||
def test_reset_nonexistent_share_instance_state(self):
|
||||
self.assertRaises(lib_exc.NotFound, self.shares_client.reset_state,
|
||||
self.assertRaises(lib_exc.NotFound, self.shares_v2_client.reset_state,
|
||||
"fake", s_type="share_instances")
|
||||
|
||||
@test.attr(type=["gate", "negative", ])
|
||||
@ -65,7 +65,7 @@ class AdminActionsNegativeTest(base.BaseSharesAdminTest):
|
||||
def test_reset_share_instance_state_to_unacceptable_state(self):
|
||||
self.assertRaises(
|
||||
lib_exc.BadRequest,
|
||||
self.shares_client.reset_state,
|
||||
self.shares_v2_client.reset_state,
|
||||
self.sh_instance["id"],
|
||||
s_type="share_instances",
|
||||
status="fake"
|
||||
@ -90,7 +90,7 @@ class AdminActionsNegativeTest(base.BaseSharesAdminTest):
|
||||
def test_try_reset_share_instance_state_with_member(self):
|
||||
# Even if member from another tenant, it should be unauthorized
|
||||
self.assertRaises(lib_exc.Forbidden,
|
||||
self.member_shares_client.reset_state,
|
||||
self.member_shares_v2_client.reset_state,
|
||||
self.sh_instance["id"], s_type="share_instances")
|
||||
|
||||
@test.attr(type=["gate", "negative", ])
|
||||
@ -110,7 +110,7 @@ class AdminActionsNegativeTest(base.BaseSharesAdminTest):
|
||||
@test.attr(type=["gate", "negative", ])
|
||||
def test_force_delete_nonexistent_share_instance(self):
|
||||
self.assertRaises(lib_exc.NotFound,
|
||||
self.shares_client.force_delete,
|
||||
self.shares_v2_client.force_delete,
|
||||
"fake",
|
||||
s_type="share_instances")
|
||||
|
||||
@ -134,7 +134,7 @@ class AdminActionsNegativeTest(base.BaseSharesAdminTest):
|
||||
def test_try_force_delete_share_instance_with_member(self):
|
||||
# If a non-admin tries to do force_delete, it should be unauthorized
|
||||
self.assertRaises(lib_exc.Forbidden,
|
||||
self.member_shares_client.force_delete,
|
||||
self.member_shares_v2_client.force_delete,
|
||||
self.sh_instance["id"], s_type="share_instances")
|
||||
|
||||
@test.attr(type=["gate", "negative", ])
|
||||
|
Loading…
Reference in New Issue
Block a user