Port admin actions extension to core API
Changes: - Register admin actions API as core API. - Remove extension code for admin actions. - Leave rename of admin actions API 'post' data for future update which will be done with bump of microversion after port of all extensions to core API. Partially implements bp ext-to-core Closes-Bug: #1510620 Change-Id: Ic8804cff5fa46003d2991372c6eb2a854b886dec
This commit is contained in:
parent
61bab6cc29
commit
9912d296ec
@ -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']
|
||||
|
@ -720,13 +720,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"
|
||||
}
|
||||
|
@ -998,7 +998,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')
|
||||
|
||||
@ -1157,7 +1157,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={})
|
||||
|
||||
@ -1166,7 +1166,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={})
|
||||
|
||||
@ -1176,7 +1176,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={})
|
||||
|
||||
@ -1191,7 +1191,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)
|
||||
@ -1204,7 +1204,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)
|
||||
@ -1221,7 +1221,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(
|
||||
@ -1235,7 +1235,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…
x
Reference in New Issue
Block a user